From ac9740a0966c42ce08e92737fa0b8e476cdd490b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 9 Jul 2019 12:03:38 +0200 Subject: [PATCH 001/376] VERSION: Bump version up to 4.11.0rc2... and re-enable GIT_SNAPSHOT. Signed-off-by: Stefan Metzmacher --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index e9931834e6c..c70b521219c 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=1 +SAMBA_VERSION_RC_RELEASE=2 ######################################################## # To mark SVN snapshots this should be set to 'yes' # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=1 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 1c64a2e37b695fcae9f64dea6f82c6fcadc990c4 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 9 Jul 2019 12:21:10 +0200 Subject: [PATCH 002/376] WHATSNEW: preview release -> release candidate Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index c0d13d20d6b..b07e9eba778 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,7 +1,7 @@ Release Announcements ===================== -This is the first preview release of Samba 4.11. This is *not* +This is the second release candidate of Samba 4.11. This is *not* intended for production environments and is designed for testing purposes only. Please report any defects via the Samba bug reporting system at https://bugzilla.samba.org/. -- 2.17.1 From 6877eabea8f34e49b2ccec3ac1793600b8a0475e Mon Sep 17 00:00:00 2001 From: Aaron Haslett Date: Thu, 11 Jul 2019 17:12:06 +1200 Subject: [PATCH 003/376] partition: correcting lock ordering A schema reading bug was traced to a lock ordering issue in partition.c. This patch fixes the problem by: 1. Releasing locks/transactions in the order they were acquired. 2. Always lock/start_trans on metadata.tdb first, before any other databases, and release it last, after all others. This is so that we are never exposed to MDB's lock semantics, which we don't support. Signed-off-by: Aaron Haslett Reviewed-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit 7f4bc0ea81f2b34607849911f1271b030be8ca02) --- source4/dsdb/samdb/ldb_modules/partition.c | 135 +++++++++++++-------- 1 file changed, 84 insertions(+), 51 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 4cfcf6f3ba7..93fa129c14e 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -1032,8 +1032,8 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req) /* start a transaction */ int partition_start_trans(struct ldb_module *module) { - int i; - int ret; + int i = 0; + int ret = 0; struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), struct partition_private_data); /* Look at base DN */ @@ -1043,18 +1043,58 @@ int partition_start_trans(struct ldb_module *module) ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> (metadata partition)"); } - /* This order must match that in prepare_commit() and read_lock() */ + /* + * We start a transaction on metadata.tdb first and end it last in + * end_trans. This makes locking semantics follow TDB rather than MDB, + * and effectively locks all partitions at once. + * Detail: + * Samba AD is special in that the partitions module (this file) + * combines multiple independently locked databases into one overall + * transaction. Changes across multiple partition DBs in a single + * transaction must ALL be either visible or invisible. + * The way this is achieved is by taking out a write lock on + * metadata.tdb at the start of prepare_commit, while unlocking it at + * the end of end_trans. This is matched by read_lock, ensuring it + * can't progress until that write lock is released. + * + * metadata.tdb needs to be a TDB file because MDB uses independent + * locks, which means a read lock and a write lock can be held at the + * same time, whereas in TDB, the two locks block each other. The TDB + * behaviour is required to implement the functionality described + * above. + * + * An important additional detail here is that if prepare_commit is + * called on a TDB without any changes being made, no write lock is + * taken. We address this by storing a sequence number in metadata.tdb + * which is updated every time a replicated attribute is modified. + * The possibility of a few unreplicated attributes being out of date + * turns out not to be a problem. + * For this reason, a lock on sam.ldb (which is a TDB) won't achieve + * the same end as locking metadata.tdb, unless we made a modification + * to the @ records found there before every prepare_commit. + */ + ret = partition_metadata_start_trans(module); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_next_start_trans(module); if (ret != LDB_SUCCESS) { + partition_metadata_del_trans(module); return ret; } ret = partition_reload_if_required(module, data, NULL); if (ret != LDB_SUCCESS) { ldb_next_del_trans(module); + partition_metadata_del_trans(module); return ret; } + /* + * The following per partition locks are required mostly because TDB + * and MDB require locks before read and write ops are permitted. + */ for (i=0; data && data->partitions && data->partitions[i]; i++) { if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> %s", @@ -1072,20 +1112,6 @@ int partition_start_trans(struct ldb_module *module) } } - /* - * Because in prepare_commit this must come last, to ensure - * lock ordering we have to do this last here also - */ - ret = partition_metadata_start_trans(module); - if (ret != LDB_SUCCESS) { - /* Back it out, if it fails on one */ - for (i--; i >= 0; i--) { - ldb_next_del_trans(data->partitions[i]->module); - } - ldb_next_del_trans(module); - return ret; - } - data->in_transaction++; return LDB_SUCCESS; @@ -1099,6 +1125,15 @@ int partition_prepare_commit(struct ldb_module *module) struct partition_private_data); int ret; + /* + * Order of prepare_commit calls must match that in + * partition_start_trans. See comment in that function for detail. + */ + ret = partition_metadata_prepare_commit(module); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_next_prepare_commit(module); if (ret != LDB_SUCCESS) { return ret; @@ -1122,9 +1157,7 @@ int partition_prepare_commit(struct ldb_module *module) ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> (metadata partition)"); } - /* metadata prepare commit must come last, as other partitions could modify - * the database inside the prepare commit method of a module */ - return partition_metadata_prepare_commit(module); + return LDB_SUCCESS; } @@ -1145,7 +1178,10 @@ int partition_end_trans(struct ldb_module *module) data->in_transaction--; } - + /* + * Order of end_trans calls must be the reverse of that in + * partition_start_trans. See comment in that function for detail. + */ for (i=0; data && data->partitions && data->partitions[i]; i++) { if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_end_trans() -> %s", @@ -1184,6 +1220,10 @@ int partition_del_trans(struct ldb_module *module) struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), struct partition_private_data); + /* + * Order of del_trans calls must be the reverse of that in + * partition_start_trans. See comment in that function for detail. + */ for (i=0; data && data->partitions && data->partitions[i]; i++) { if (ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING) { @@ -1382,9 +1422,9 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque /* lock all the backends */ int partition_read_lock(struct ldb_module *module) { - int i; - int ret; - int ret2; + int i = 0; + int ret = 0; + int ret2 = 0; struct ldb_context *ldb = ldb_module_get_ctx(module); struct partition_private_data *data = \ talloc_get_type(ldb_module_get_private(module), @@ -1430,9 +1470,8 @@ int partition_read_lock(struct ldb_module *module) } /* - * This will lock the metadata partition (sam.ldb) and - * will also call event loops, so we do it before we - * get the whole db lock. + * This will lock sam.ldb and will also call event loops, + * so we do it before we get the whole db lock. */ ret = partition_reload_if_required(module, data, NULL); if (ret != LDB_SUCCESS) { @@ -1440,8 +1479,20 @@ int partition_read_lock(struct ldb_module *module) } /* - * This order must match that in prepare_commit(), start with - * the top level DB (sam.ldb) lock + * Order of read_lock calls must match that in partition_start_trans. + * See comment in that function for detail. + */ + ret = partition_metadata_read_lock(module); + if (ret != LDB_SUCCESS) { + goto failed; + } + + /* + * The top level DB (sam.ldb) lock is not enough to block another + * process in prepare_commit(), because if nothing was changed in the + * specific backend, then prepare_commit() is a no-op. Therefore the + * metadata.tdb lock is taken out above, as it is the best we can do + * right now. */ ret = ldb_next_read_lock(module); if (ret != LDB_SUCCESS) { @@ -1455,12 +1506,8 @@ int partition_read_lock(struct ldb_module *module) } /* - * The top level DB (sam.ldb) lock is not - * enough to block another process in prepare_commit(), - * because prepare_commit() is a no-op, if nothing - * was changed in the specific backend. - * - * That means the following per partition locks are required. + * The following per partition locks are required mostly because TDB + * and MDB require locks before reads are permitted. */ for (i=0; data && data->partitions && data->partitions[i]; i++) { if ((module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING)) { @@ -1485,15 +1532,6 @@ int partition_read_lock(struct ldb_module *module) goto failed; } - /* - * Because in prepare_commit this must come last, to ensure - * lock ordering we have to do this last here also - */ - ret = partition_metadata_read_lock(module); - if (ret != LDB_SUCCESS) { - goto failed; - } - return LDB_SUCCESS; failed: @@ -1531,10 +1569,9 @@ int partition_read_unlock(struct ldb_module *module) struct partition_private_data); /* - * This order must be similar to partition_{end,del}_trans() - * the metadata partition (sam.ldb) unlock must be at the end. + * Order of read_unlock calls must be the reverse of that in + * partition_start_trans. See comment in that function for detail. */ - for (i=0; data && data->partitions && data->partitions[i]; i++) { if ((module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING)) { ldb_debug(ldb, LDB_DEBUG_TRACE, @@ -1584,10 +1621,6 @@ int partition_read_unlock(struct ldb_module *module) } } - /* - * Because in prepare_commit this must come last, to ensure - * lock ordering we have to do this last here also - */ ret = partition_metadata_read_unlock(module); /* -- 2.17.1 From 29fa37b717cc83080ed9eb50345370b8f40d7ce7 Mon Sep 17 00:00:00 2001 From: Aaron Haslett Date: Mon, 15 Jul 2019 13:32:41 +1200 Subject: [PATCH 004/376] partition: reversing partition unlocking Unlock partition databases in the reverse order from which they were acquired. This is separated from the previous commit for future bisecting purposes, since the last commit was made to fix specific CI failures, while this one is a speculative fix made based on code inspection. Signed-off-by: Aaron Haslett Reviewed-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit 6c691bf84e41b1edd3228c219f7a94e108795d28) --- source4/dsdb/samdb/ldb_modules/partition.c | 125 ++++++++++++--------- 1 file changed, 72 insertions(+), 53 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 93fa129c14e..e34ba35680b 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -1165,9 +1165,11 @@ int partition_prepare_commit(struct ldb_module *module) int partition_end_trans(struct ldb_module *module) { int ret, ret2; - unsigned int i; + int i; + struct ldb_context *ldb = ldb_module_get_ctx(module); struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), struct partition_private_data); + bool trace = module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING; ret = LDB_SUCCESS; @@ -1182,21 +1184,28 @@ int partition_end_trans(struct ldb_module *module) * Order of end_trans calls must be the reverse of that in * partition_start_trans. See comment in that function for detail. */ - for (i=0; data && data->partitions && data->partitions[i]; i++) { - if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { - ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_end_trans() -> %s", - ldb_dn_get_linearized(data->partitions[i]->ctrl->dn)); - } - ret2 = ldb_next_end_trans(data->partitions[i]->module); - if (ret2 != LDB_SUCCESS) { - ldb_asprintf_errstring(ldb_module_get_ctx(module), "end_trans error on %s: %s", - ldb_dn_get_linearized(data->partitions[i]->ctrl->dn), - ldb_errstring(ldb_module_get_ctx(module))); - ret = ret2; + if (data && data->partitions) { + for (i=0; data->partitions[i]; i++);; + for (i--; i>=0; i--) { + struct dsdb_partition *p = data->partitions[i]; + if (trace) { + ldb_debug(ldb, + LDB_DEBUG_TRACE, + "partition_end_trans() -> %s", + ldb_dn_get_linearized(p->ctrl->dn)); + } + ret2 = ldb_next_end_trans(p->module); + if (ret2 != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, + "end_trans error on %s: %s", + ldb_dn_get_linearized(p->ctrl->dn), + ldb_errstring(ldb)); + ret = ret2; + } } } - if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { + if (trace) { ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_end_trans() -> (metadata partition)"); } ret2 = ldb_next_end_trans(module); @@ -1216,31 +1225,38 @@ int partition_end_trans(struct ldb_module *module) int partition_del_trans(struct ldb_module *module) { int ret, final_ret = LDB_SUCCESS; - unsigned int i; + int i; + struct ldb_context *ldb = ldb_module_get_ctx(module); struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), struct partition_private_data); + bool trace = module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING; /* * Order of del_trans calls must be the reverse of that in * partition_start_trans. See comment in that function for detail. */ - for (i=0; data && data->partitions && data->partitions[i]; i++) { - if (ldb_module_flags(ldb_module_get_ctx(module)) & - LDB_FLG_ENABLE_TRACING) { - ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_del_trans() -> %s", - ldb_dn_get_linearized(data->partitions[i]->ctrl->dn)); - } - ret = ldb_next_del_trans(data->partitions[i]->module); - if (ret != LDB_SUCCESS) { - ldb_asprintf_errstring(ldb_module_get_ctx(module), "del_trans error on %s: %s", - ldb_dn_get_linearized(data->partitions[i]->ctrl->dn), - ldb_errstring(ldb_module_get_ctx(module))); - final_ret = ret; + if (data && data->partitions) { + for (i=0; data->partitions[i]; i++);; + for (i--; i>=0; i--) { + struct dsdb_partition *p = data->partitions[i]; + if (trace) { + ldb_debug(ldb, + LDB_DEBUG_TRACE, + "partition_del_trans() -> %s", + ldb_dn_get_linearized(p->ctrl->dn)); + } + ret = ldb_next_del_trans(p->module); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, + "del_trans error on %s: %s", + ldb_dn_get_linearized(p->ctrl->dn), + ldb_errstring(ldb)); + final_ret = ret; + } } - } + } - if (ldb_module_flags(ldb_module_get_ctx(module)) & - LDB_FLG_ENABLE_TRACING) { + if (trace) { ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_del_trans() -> (metadata partition)"); } ret = ldb_next_del_trans(module); @@ -1567,39 +1583,42 @@ int partition_read_unlock(struct ldb_module *module) struct partition_private_data *data = \ talloc_get_type(ldb_module_get_private(module), struct partition_private_data); + bool trace = module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING; /* * Order of read_unlock calls must be the reverse of that in * partition_start_trans. See comment in that function for detail. */ - for (i=0; data && data->partitions && data->partitions[i]; i++) { - if ((module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING)) { - ldb_debug(ldb, LDB_DEBUG_TRACE, - "partition_read_unlock() -> %s", - ldb_dn_get_linearized( - data->partitions[i]->ctrl->dn)); - } - ret2 = ldb_next_read_unlock(data->partitions[i]->module); - if (ret2 != LDB_SUCCESS) { - ldb_debug_set(ldb, - LDB_DEBUG_FATAL, - "Failed to lock db: %s / %s for %s", - ldb_errstring(ldb), - ldb_strerror(ret), - ldb_dn_get_linearized( - data->partitions[i]->ctrl->dn)); - - /* - * Don't overwrite the original failure code - * if there was one - */ - if (ret == LDB_SUCCESS) { - ret = ret2; + if (data && data->partitions) { + for (i=0; data->partitions[i]; i++);; + for (i--; i>=0; i--) { + struct dsdb_partition *p = data->partitions[i]; + if (trace) { + ldb_debug(ldb, LDB_DEBUG_TRACE, + "partition_read_unlock() -> %s", + ldb_dn_get_linearized(p->ctrl->dn)); + } + ret2 = ldb_next_read_unlock(p->module); + if (ret2 != LDB_SUCCESS) { + ldb_debug_set(ldb, + LDB_DEBUG_FATAL, + "Failed to lock db: %s / %s for %s", + ldb_errstring(ldb), + ldb_strerror(ret), + ldb_dn_get_linearized(p->ctrl->dn)); + + /* + * Don't overwrite the original failure code + * if there was one + */ + if (ret == LDB_SUCCESS) { + ret = ret2; + } } } } - if (ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING) { + if (trace) { ldb_debug(ldb, LDB_DEBUG_TRACE, "partition_read_unlock() -> (metadata partition)"); } -- 2.17.1 From f2c40f4d41a4729bf31534ce34261d70c5dd0071 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Thu, 18 Jul 2019 14:50:57 +1200 Subject: [PATCH 005/376] gp_inf: Read/write files with a UTF-16LE BOM in GptTmpl.inf Regression caused by 16596842a62bec0a9d974c48d64000e3c079254e [MS-GPSB] 2.2 Message Syntax says that you have to write a BOM which I didn't do up until this patch. UTF-16 as input encoding was marked much higher up in the inheritance tree, which got overriden with the Python 3 fixes. I've now marked the encoding much more obviously for this file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14004 Signed-off-by: Garming Sam Reviewed-by: Gary Lockyer Autobuild-User(master): Gary Lockyer Autobuild-Date(master): Fri Jul 19 02:20:47 UTC 2019 on sn-devel-184 (cherry picked from commit 0bcfc550b1a902e3a6a766b06603ac9285d0ff63) --- python/samba/gp_parse/gp_inf.py | 9 ++++++--- .../SecEdit/GptTmpl.inf.SAMBABACKUP | Bin 2580 -> 2582 bytes 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/python/samba/gp_parse/gp_inf.py b/python/samba/gp_parse/gp_inf.py index 79e28159f1f..a3c828fa82d 100644 --- a/python/samba/gp_parse/gp_inf.py +++ b/python/samba/gp_parse/gp_inf.py @@ -29,11 +29,11 @@ from samba.gp_parse import GPParser # [MS-GPSB] Security Protocol Extension class GptTmplInfParser(GPParser): sections = None - encoding = 'utf-16le' + encoding = 'utf-16' + output_encoding = 'utf-16le' class AbstractParam: __metaclass__ = ABCMeta - encoding = 'utf-16le' def __init__(self): self.param_list = [] @@ -333,7 +333,10 @@ class GptTmplInfParser(GPParser): def write_binary(self, filename): with codecs.open(filename, 'wb+', - self.encoding) as f: + self.output_encoding) as f: + # Write the byte-order mark + f.write(u'\ufeff') + for s in self.sections: self.sections[s].write_section(s, f) diff --git a/source4/selftest/provisions/generalized-gpo-backup/policy/{1E1DC8EA-390C-4800-B327-98B56A0AEA5D}/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf.SAMBABACKUP b/source4/selftest/provisions/generalized-gpo-backup/policy/{1E1DC8EA-390C-4800-B327-98B56A0AEA5D}/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf.SAMBABACKUP index 18c58a7baa9566be4977086640f4ad8c3e4c38a7..8de94078e703e9adf222dfc0bd4bfff31e797bbd 100644 GIT binary patch delta 10 RcmbOtGEIc(|Gy0)TmTmX1Rwwa delta 8 PcmbOxGDTz~lL!|83>*R^ -- 2.17.1 From 98051741ea5069b0e6fb7274cd1959460c7f95a1 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Mon, 8 Jul 2019 13:42:50 +0200 Subject: [PATCH 006/376] WHATSNEW: add CephFS Snapshot Integration section Bug: https://bugzilla.samba.org/show_bug.cgi?id=14039 Signed-off-by: David Disseldorp Reviewed-by: Aurelien Aptel --- WHATSNEW.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index b07e9eba778..fce43f55cfa 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -59,8 +59,8 @@ worker processes at startup and share the client connections amongst these workers. The number of worker processes can be configured by the 'prefork children' setting in the smb.conf (the default is 4). -Authentication Logging. ------------------------ +Authentication Logging +---------------------- Winbind now logs PAM_AUTH and NTLM_AUTH events, a new attribute "logonId" has been added to the Authentication JSON log messages. This contains a random @@ -254,6 +254,12 @@ CTDB changes swap) utilisation using the existing CTDB_MONITOR_MEMORY_USAGE script configuration variable. +CephFS Snapshot Integration +--------------------------- + +CephFS snapshots can now be exposed as previous file versions using the new +ceph_snapshots VFS module. See the vfs_ceph_snapshots(8) man page for details. + REMOVED FEATURES ================ -- 2.17.1 From 122d7afb50e7d9b67954979b38d4f1b168dfde97 Mon Sep 17 00:00:00 2001 From: Aurelien Aptel Date: Tue, 9 Jul 2019 23:55:30 +0200 Subject: [PATCH 007/376] WHATSNEW: document new debug encryption smb.conf param Bug: https://bugzilla.samba.org/show_bug.cgi?id=14039 Signed-off-by: Aurelien Aptel Reviewed-by: David Disseldorp --- WHATSNEW.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index fce43f55cfa..e91ad51c71b 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -312,6 +312,7 @@ smb.conf changes mangled names Changed default illegal web port Removed fruit:zero_file_id Changed default False + debug encryption New: dump encryption keys False KNOWN ISSUES -- 2.17.1 From b95186a533201b8eeeb49a073e65e60a3a57bf75 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Mon, 8 Jul 2019 16:59:33 +1200 Subject: [PATCH 008/376] ldap_server: Regression in 0559430ab6e5c48d6e853fda0d8b63f2e149015c Extended DN requests seem to have been incorrectly handled. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14029 Signed-off-by: Garming Sam Reviewed-by: Gary Lockyer Autobuild-User(master): Gary Lockyer Autobuild-Date(master): Thu Jul 11 05:25:26 UTC 2019 on sn-devel-184 (cherry picked from commit 9f6b87d3f6cc9930d75c1f8d38ad4f5a37da34ab) --- source4/ldap_server/ldap_backend.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c index c6a65122ab0..bf724335a25 100644 --- a/source4/ldap_server/ldap_backend.c +++ b/source4/ldap_server/ldap_backend.c @@ -826,6 +826,7 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call) } else { extended_type = 0; } + callback_ctx->extended_type = extended_type; } notification_control = ldb_request_get_control(lreq, LDB_CONTROL_NOTIFICATION_OID); -- 2.17.1 From dd36cafdb96e37eb8ee6b55feb3233dc07558b41 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 31 Jul 2019 01:08:23 +0000 Subject: [PATCH 009/376] tldap: Make memcpy of no controls safe Static analyzers sometimes complain about this case. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14029 (cherry picked from commit e5452a37425484a95f90604a3e58e8a731460793) --- source3/lib/tldap_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source3/lib/tldap_util.c b/source3/lib/tldap_util.c index 152942dab2c..bdf8eb031a5 100644 --- a/source3/lib/tldap_util.c +++ b/source3/lib/tldap_util.c @@ -588,7 +588,9 @@ struct tldap_control *tldap_add_control(TALLOC_CTX *mem_ctx, if (result == NULL) { return NULL; } - memcpy(result, ctrls, sizeof(struct tldap_control) * num_ctrls); + if (num_ctrls > 0) { + memcpy(result, ctrls, sizeof(struct tldap_control) * num_ctrls); + } result[num_ctrls] = *ctrl; return result; } -- 2.17.1 From 23f8a8ee71b6aa2b88174e5d9556508ae48e733e Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 31 Jul 2019 13:39:13 +1200 Subject: [PATCH 010/376] tldap: Paged searches fail when they get to the end The normal case hit the goto label, and should have just returned. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14029 (cherry picked from commit bff466943e01540b4d3210392e0fd5b1c882c0b9) --- source3/lib/tldap_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/lib/tldap_util.c b/source3/lib/tldap_util.c index bdf8eb031a5..1b86962a32e 100644 --- a/source3/lib/tldap_util.c +++ b/source3/lib/tldap_util.c @@ -810,7 +810,8 @@ static void tldap_search_paged_done(struct tevent_req *subreq) } tevent_req_set_callback(subreq, tldap_search_paged_done, req); - err: + return; +err: TALLOC_FREE(asn1); tevent_req_ldap_error(req, TLDAP_DECODING_ERROR); -- 2.17.1 From a1d0ce447e782b88386189969afa46f2dc4ed43a Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 31 Jul 2019 15:29:07 +1200 Subject: [PATCH 011/376] tests/tldap: Actually check the paging return code The test never worked correctly because the code was overlooked. It was also the case that the connection was never authenticated, and so an LDAP BIND call has now been added. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14029 (cherry picked from commit 85a7b594c56f7729bdfa194fee9299a08f6b4785) --- source3/torture/torture.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 2cb32efea46..20a7459b4db 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -11286,6 +11286,8 @@ static bool run_shortname_test(int dummy) return correct; } +TLDAPRC callback_code; + static void pagedsearch_cb(struct tevent_req *req) { TLDAPRC rc; @@ -11296,6 +11298,7 @@ static void pagedsearch_cb(struct tevent_req *req) if (!TLDAP_RC_IS_SUCCESS(rc)) { d_printf("tldap_search_paged_recv failed: %s\n", tldap_rc2string(rc)); + callback_code = rc; return; } if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) { @@ -11360,6 +11363,18 @@ static bool run_tldap(int dummy) return false; } + rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL, + loadparm_init_s3(talloc_tos(), + loadparm_s3_helpers()), + GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL); + + if (!TLDAP_RC_IS_SUCCESS(rc)) { + d_printf("tldap_gensec_bind failed\n"); + return false; + } + + callback_code = TLDAP_SUCCESS; + req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn, TLDAP_SCOPE_SUB, "(objectclass=*)", NULL, 0, 0, @@ -11374,6 +11389,14 @@ static bool run_tldap(int dummy) TALLOC_FREE(req); + rc = callback_code; + + if (!TLDAP_RC_IS_SUCCESS(rc)) { + d_printf("tldap_search with paging failed: %s\n", + tldap_errstr(talloc_tos(), ld, rc)); + return false; + } + /* test search filters against rootDSE */ filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))" "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))"; -- 2.17.1 From 636f7dedd40d1f357d0b0799496fabeb82e73450 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 31 Jul 2019 01:14:42 +0000 Subject: [PATCH 012/376] tests/ldap: Use TLDAP to check the extended DN return Tests commit 9f6b87d3f6cc9930d75c1f8d38ad4f5a37da34ab To run: make test TESTS="samba3.smbtorture_s3.plain.TLDAP" Reverting the above commit makes this test fail: 'GUID format in control (no hyphens) doesn't match output tldap_search with extended dn (no val) failed: LDAP error 0 (TLDAP_SUCCESS), TEST TLDAP FAILED!' This behaviour couldn't be tested via LDB libraries because they never deal with the underlying DN string. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14029 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Thu Aug 1 06:20:28 UTC 2019 on sn-devel-184 (adapted from commit 464fef34d1d047d73be347cd446b74e0f5eb2370) --- source3/torture/torture.c | 155 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 20a7459b4db..f26c634b7a7 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -26,6 +26,7 @@ #include "libcli/security/security.h" #include "tldap.h" #include "tldap_util.h" +#include "tldap_gensec_bind.h" #include "../librpc/gen_ndr/svcctl.h" #include "../lib/util/memcache.h" #include "nsswitch/winbind_client.h" @@ -45,6 +46,9 @@ #include "lib/util/base64.h" #include "lib/util/time.h" #include "lib/gencache.h" +#include "lib/util/asn1.h" +#include "lib/param/param.h" +#include "auth/gensec/gensec.h" #include #include @@ -11313,6 +11317,134 @@ static void pagedsearch_cb(struct tevent_req *req) TALLOC_FREE(msg); } +enum tldap_extended_val { + EXTENDED_ZERO = 0, + EXTENDED_ONE = 1, + EXTENDED_NONE = 2, +}; + +/* + * Construct an extended dn control with either no value, 0 or 1 + * + * No value and 0 are equivalent (non-hyphenated GUID) + * 1 has the hyphenated GUID + */ +static struct tldap_control * +tldap_build_extended_control(enum tldap_extended_val val) +{ + struct tldap_control empty_control; + struct asn1_data *data; + + ZERO_STRUCT(empty_control); + + if (val != EXTENDED_NONE) { + data = asn1_init(talloc_tos()); + + if (!data) { + return NULL; + } + + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) { + return NULL; + } + + if (!asn1_write_Integer(data, (int)val)) { + return NULL; + } + + if (!asn1_pop_tag(data)) { + return NULL; + } + + if (!asn1_blob(data, &empty_control.value)) { + return NULL; + } + } + + empty_control.oid = "1.2.840.113556.1.4.529"; + empty_control.critical = true; + + return tldap_add_control(talloc_tos(), NULL, 0, &empty_control); + +} + +static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn, + enum tldap_extended_val control_val) +{ + struct tldap_control *control = tldap_build_extended_control(control_val); + char *dn = NULL; + struct tldap_message **msg; + TLDAPRC rc; + + rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE, + "(objectClass=*)", NULL, 0, 0, + control, 1, NULL, + 0, 0, 0, 0, talloc_tos(), &msg); + if (!TLDAP_RC_IS_SUCCESS(rc)) { + d_printf("tldap_search for domain DN failed: %s\n", + tldap_errstr(talloc_tos(), ld, rc)); + return false; + } + + if (!tldap_entry_dn(msg[0], &dn)) { + d_printf("tldap_search domain DN fetch failed: %s\n", + tldap_errstr(talloc_tos(), ld, rc)); + return false; + } + + d_printf("%s\n", dn); + { + uint32_t time_low; + uint32_t time_mid, time_hi_and_version; + uint32_t clock_seq[2]; + uint32_t node[6]; + char next; + + switch (control_val) { + case EXTENDED_NONE: + case EXTENDED_ZERO: + /* + * When reading GUIDs with hyphens, scanf will treat + * hyphen as a hex character (and counts as part of the + * width). This creates leftover GUID string which we + * check will for with 'next' and closing '>'. + */ + if (12 == sscanf(dn, "%c", + &time_low, &time_mid, + &time_hi_and_version, &clock_seq[0], + &clock_seq[1], &node[0], &node[1], + &node[2], &node[3], &node[4], + &node[5], &next)) { + /* This GUID is good */ + } else { + d_printf("GUID format in control (no hyphens) doesn't match output\n"); + return false; + } + + break; + case EXTENDED_ONE: + if (12 == sscanf(dn, + "%c", + &time_low, &time_mid, + &time_hi_and_version, &clock_seq[0], + &clock_seq[1], &node[0], &node[1], + &node[2], &node[3], &node[4], + &node[5], &next)) { + /* This GUID is good */ + } else { + d_printf("GUID format in control (with hyphens) doesn't match output\n"); + return false; + } + + break; + default: + return false; + } + } + + return true; +} + static bool run_tldap(int dummy) { struct tldap_context *ld; @@ -11410,6 +11542,29 @@ static bool run_tldap(int dummy) return false; } + /* + * Tests to check for regression of: + * + * https://bugzilla.samba.org/show_bug.cgi?id=14029 + * + * TLDAP used here to pick apart the original string DN (with GUID) + */ + if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) { + d_printf("tldap_search with extended dn (no val) failed: %s\n", + tldap_errstr(talloc_tos(), ld, rc)); + return false; + } + if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) { + d_printf("tldap_search with extended dn (0) failed: %s\n", + tldap_errstr(talloc_tos(), ld, rc)); + return false; + } + if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) { + d_printf("tldap_search with extended dn (1) failed: %s\n", + tldap_errstr(talloc_tos(), ld, rc)); + return false; + } + TALLOC_FREE(ld); return true; } -- 2.17.1 From 816053b7bba894aa217a895925621801f0d17681 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Wed, 24 Jul 2019 11:00:01 +1200 Subject: [PATCH 013/376] join: Use a specific attribute order for the DsAddEntry nTDSDSA object Joining a Windows domain can throw an error if the HasMasterNCs attribute occurs before msDS-HasMasterNCs. This patch changes the attribute order so that msDS-HasMasterNCs is always first. Previously on python2, the dictionary hash order was arbitrary but constant. By luck, msDS-HasMasterNCs was always before HasMasterNCs, so we never noticed any problem. With python3, the dictionary hash order now changes everytime you run the command, so the order is unpredictable. To enforce a order, we can change to use an OrderedDict, which will return the keys in the order they're added. I've asked Microsoft to clarify the protocol requirement here WRT attribute order. However, in the meantime we may as well fix the problem for users. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14046 RN: When trying to join a Windows domain (with functional level 2008R2) as an AD domain controller, the 'samba-tool domain join' command could throw a python exception: 'RuntimeError ("DsAddEntry failed")'. When this problem occurred, you would also see the message "DsAddEntry failed with status WERR_ACCESS_DENIED info (8363, 'WERR_DS_NO_CROSSREF_FOR_NC')" in the command output. This issue has now been resolved. Note that this problem would only occur on Samba v4.10 when using the Python3 packages. Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Jul 24 04:18:21 UTC 2019 on sn-devel-184 (cherry picked from commit 256684c7a86301d26d6cf7298fb70e647bf45cf5) --- python/samba/join.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/python/samba/join.py b/python/samba/join.py index ac4346c62a3..40920f4f8e5 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -48,6 +48,7 @@ import time import re import os import tempfile +from collections import OrderedDict from samba.compat import text_type from samba.compat import get_string from samba.netcmd import CommandError @@ -555,11 +556,14 @@ class DCJoinContext(object): '''return the ntdsdsa object to add''' print("Adding %s" % ctx.ntds_dn) - rec = { - "dn": ctx.ntds_dn, - "objectclass": "nTDSDSA", - "systemFlags": str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE), - "dMDLocation": ctx.schema_dn} + + # When joining Windows, the order of certain attributes (mostly only + # msDS-HasMasterNCs and HasMasterNCs) seems to matter + rec = OrderedDict([ + ("dn", ctx.ntds_dn), + ("objectclass", "nTDSDSA"), + ("systemFlags", str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE)), + ("dMDLocation", ctx.schema_dn)]) nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] @@ -575,12 +579,17 @@ class DCJoinContext(object): rec["options"] = "37" else: rec["objectCategory"] = "CN=NTDS-DSA,%s" % ctx.schema_dn + + # Note that Windows seems to have an undocumented requirement that + # the msDS-HasMasterNCs attribute occurs before HasMasterNCs + if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003: + rec["msDS-HasMasterNCs"] = ctx.full_nc_list + rec["HasMasterNCs"] = [] for nc in nc_list: if nc in ctx.full_nc_list: rec["HasMasterNCs"].append(nc) - if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003: - rec["msDS-HasMasterNCs"] = ctx.full_nc_list + rec["options"] = "1" rec["invocationId"] = ndr_pack(ctx.invocation_id) -- 2.17.1 From 8a09ea3c70f95a577ed42123ebe8d3ab26f2c39d Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 24 Jul 2019 15:18:40 +1200 Subject: [PATCH 014/376] netcmd: Allow drs replicate --local to create partitions Currently, neither the offline (--local) or online (normal replica sync) methods allow partition creation post-join. This overrides the Python default to not create the DB, which allows TDB + MDB to work. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14051 Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit d90ccce59754bc833027c06683afac25f7a8d474) --- python/samba/netcmd/drs.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/samba/netcmd/drs.py b/python/samba/netcmd/drs.py index 739498cca1b..9d6e8087e87 100644 --- a/python/samba/netcmd/drs.py +++ b/python/samba/netcmd/drs.py @@ -449,8 +449,10 @@ class cmd_drs_replicate(Command): self.server = SOURCE_DC drsuapi_connect(self) + # Override the default flag LDB_FLG_DONT_CREATE_DB self.local_samdb = SamDB(session_info=system_session(), url=None, - credentials=self.creds, lp=self.lp) + credentials=self.creds, lp=self.lp, + flags=0) self.samdb = SamDB(url="ldap://%s" % self.server, session_info=system_session(), -- 2.17.1 From c7a5694f4f81676f89969464645c9ff021680eb2 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 24 Jul 2019 15:13:43 +1200 Subject: [PATCH 015/376] tests: Add samba_upgradedns to the list of possible cmds This will be used to test the replication scenario with no DNS partitions BUG: https://bugzilla.samba.org/show_bug.cgi?id=14051 Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit 7d2875bd70cf727730be8dc705bfd01eacaaaa6f) --- python/samba/tests/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index c5c212ef829..fef21d261ca 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -404,6 +404,7 @@ class BlackboxTestCase(TestCaseInTempDir): python_cmds = ["samba-tool", "samba_dnsupdate", + "samba_upgradedns", "script/traffic_replay", "script/traffic_learner"] -- 2.17.1 From 97a742fe7617d153e38aac5ad6c887c79a6e2447 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 24 Jul 2019 14:53:33 +1200 Subject: [PATCH 016/376] tests/drs_no_dns: Check dbcheck and ldapcmp pass When joining a DC without DNS partitions, make sure that the alternate flow of creating them afterwards results in a database with everything that is necessary. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14051 RN: Allow a DC join without DNS partitions, to add them later Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit 35c54007e6183829d9d85a24b3bd95f469739ad3) --- source4/selftest/tests.py | 7 + .../drs/python/samba_tool_drs_no_dns.py | 183 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 source4/torture/drs/python/samba_tool_drs_no_dns.py diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 1a7e8c757f0..bf3dd98cbef 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -949,6 +949,13 @@ for env in ['backupfromdc', 'offlinebackupdc', 'restoredc', 'renamedc', plantestsuite("samba4.blackbox.join_ldapcmp", env, ["PYTHON=%s" % python, os.path.join(bbdir, "join_ldapcmp.sh")]) +env = 'backupfromdc' +planoldpythontestsuite("%s:local" % env, "samba_tool_drs_no_dns", + extra_path=[os.path.join(samba4srcdir, 'torture/drs/python')], + name="samba4.drs.samba_tool_drs_no_dns.python(%s)" % env, + environ={'DC1': '$DC_SERVER', 'DC2': '$DC_SERVER'}, + extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD']) + plantestsuite_loadlist("samba4.ldap.rodc.python(rodc)", "rodc", [python, os.path.join(DSDB_PYTEST_DIR, "rodc.py"), diff --git a/source4/torture/drs/python/samba_tool_drs_no_dns.py b/source4/torture/drs/python/samba_tool_drs_no_dns.py new file mode 100644 index 00000000000..b9cab49e82b --- /dev/null +++ b/source4/torture/drs/python/samba_tool_drs_no_dns.py @@ -0,0 +1,183 @@ +# Blackbox tests for "samba-tool drs" command +# Copyright (C) Kamen Mazdrashki 2011 +# Copyright (C) Andrew Bartlett 2017 +# Copyright (C) Catalyst.Net Ltd 2019 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +""" +Blackbox tests for samba-tool drs with no DNS partitions + +Adapted from samba_tool_drs.py +""" + +import samba.tests +import shutil +import os +import ldb +import drs_base + +from samba.tests import BlackboxProcessError +from samba.compat import get_string + + +class SambaToolDrsNoDnsTests(drs_base.DrsBaseTestCase): + """Blackbox test case for samba-tool drs.""" + + def setUp(self): + super(SambaToolDrsNoDnsTests, self).setUp() + + self.dc1 = samba.tests.env_get_var_value("DC1") + + creds = self.get_credentials() + self.cmdline_creds = "-U%s/%s%%%s" % (creds.get_domain(), + creds.get_username(), creds.get_password()) + + def tearDown(self): + self._enable_inbound_repl(self.dnsname_dc1) + + try: + shutil.rmtree(os.path.join(self.tempdir, "private")) + shutil.rmtree(os.path.join(self.tempdir, "etc")) + shutil.rmtree(os.path.join(self.tempdir, "msg.lock")) + os.remove(os.path.join(self.tempdir, "names.tdb")) + shutil.rmtree(os.path.join(self.tempdir, "state")) + shutil.rmtree(os.path.join(self.tempdir, "bind-dns")) + except Exception: + pass + + super(SambaToolDrsNoDnsTests, self).tearDown() + + def _get_rootDSE(self, dc, ldap_only=True): + samdb = samba.tests.connect_samdb(dc, lp=self.get_loadparm(), + credentials=self.get_credentials(), + ldap_only=ldap_only) + return samdb.search(base="", scope=samba.tests.ldb.SCOPE_BASE)[0], samdb + + def test_samba_tool_replicate_local_no_dns_tdb(self): + self.backend = 'tdb' + self._test_samba_tool_replicate_local_no_dns() + + def test_samba_tool_replicate_local_no_dns_mdb(self): + self.backend = 'mdb' + self._test_samba_tool_replicate_local_no_dns() + + def _test_samba_tool_replicate_local_no_dns(self): + """Check we can provision a database without DNS partitions + (and then add them afterwards).""" + + server_rootdse, _ = self._get_rootDSE(self.dc1) + nc_name = server_rootdse["defaultNamingContext"] + server_ldap_service_name = str(server_rootdse["ldapServiceName"][0]) + server_realm = server_ldap_service_name.split(":")[0] + creds = self.get_credentials() + + # We have to give it a different netbiosname every time + # it runs, otherwise the collision causes strange issues + # to happen. This should be different on different environments. + netbiosname = "dns" + self.backend + self.dc1 + if len(netbiosname) > 15: + netbiosname = netbiosname[:15] + + out = self.check_output("samba-tool domain join %s dc --server=%s %s --targetdir=%s --option=netbiosname=%s %s --backend-store=%s" + % (server_realm, self.dc1, self.cmdline_creds, + self.tempdir, netbiosname, + "--dns-backend=NONE", + self.backend)) + + new_dc_config_file = os.path.join(self.tempdir, "etc", "smb.conf") + new_dc_sam = os.path.join(self.tempdir, "private", "sam.ldb") + + forestdns_dn = ldb.binary_encode('DC=ForestDNSZones,' + str(nc_name)) + domaindns_dn = ldb.binary_encode('DC=DomainDNSZones,' + str(nc_name)) + + self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s --full-sync" + % ("invalid", self.dc1, forestdns_dn, + self.cmdline_creds, new_dc_config_file)) + + self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s --full-sync" + % ("invalid", self.dc1, domaindns_dn, + self.cmdline_creds, new_dc_config_file)) + + server_rootdse, samdb = self._get_rootDSE("ldb://" + new_dc_sam, ldap_only=False) + server_ds_name = ldb.binary_encode(server_rootdse["dsServiceName"][0].decode('utf-8')) + + # Show that Has-Master-NCs is fixed by samba_upgradedns + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % forestdns_dn) + self.assertEquals(len(res), 0) + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % domaindns_dn) + self.assertEquals(len(res), 0) + + self.check_output("samba_upgradedns -s %s" % (new_dc_config_file)) + + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % forestdns_dn) + self.assertEquals(len(res), 1) + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % domaindns_dn) + self.assertEquals(len(res), 1) + + # Show that replica locations is fixed by dbcheck + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, forestdns_dn)) + self.assertEquals(len(res), 0) + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, domaindns_dn)) + self.assertEquals(len(res), 0) + + try: + # This fixes any forward-link-backward-link issues with the tools + self.check_output("samba-tool dbcheck -s %s --cross-ncs --fix --yes" % (new_dc_config_file)) + except BlackboxProcessError as e: + self.assertTrue("Checked " in get_string(e.stdout)) + + self.check_output("samba-tool dbcheck -s %s --cross-ncs" % (new_dc_config_file)) + + # Compare the two directories + self.check_output("samba-tool ldapcmp ldap://%s ldb://%s %s --filter=%s" % + (self.dc1, new_dc_sam, self.cmdline_creds, + "msDs-masteredBy,msDS-NC-Replica-Locations,msDS-hasMasterNCs")) + + # Check all ForestDNS connections and backlinks + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % forestdns_dn) + self.assertEquals(len(res), 1) + res = samdb.search(base=forestdns_dn, + expression="(msds-masteredby=%s)" % server_ds_name) + self.assertEquals(len(res), 1) + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, forestdns_dn)) + self.assertEquals(len(res), 1) + + # Check all DomainDNS connections and backlinks + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % domaindns_dn) + self.assertEquals(len(res), 1) + res = samdb.search(base=domaindns_dn, + expression="(msds-masteredby=%s)" % server_ds_name) + self.assertEquals(len(res), 1) + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, domaindns_dn)) + self.assertEquals(len(res), 1) + + # Demote the DC we created in the test + self.check_output("samba-tool domain demote --remove-other-dead-server=%s -H ldap://%s %s -s %s" + % (netbiosname, self.dc1, self.cmdline_creds, new_dc_config_file)) -- 2.17.1 From 02352ebbef6dd5669cb28369a3c7e7579c796384 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Mon, 29 Jul 2019 10:14:06 +1200 Subject: [PATCH 017/376] WHATSNEW: Make it clearer how the AD database changes will affect users The release notes currently just have a brief mention of a new LDB pack format. They don't really cover how this change will actually affect AD users when upgrading (or more specifically downgrading) with v4.11. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14057 Signed-off-by: Tim Beale --- WHATSNEW.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index e91ad51c71b..c94b3541d7d 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -12,6 +12,32 @@ Samba 4.11 will be the next version of the Samba suite. UPGRADING ========= +AD Database compatibility +------------------------- + +Samba v4.11 has changed how the AD database is stored on disk. AD users should +not really be affected by this change when upgrading to v4.11. However, AD +users should be extremely careful if they need to downgrade from Samba v4.11 to +an older release. + +Samba v4.11 maintains database compatibility with older Samba releases. The +database will automatically get rewritten in the new v4.11 format when you +first start the upgraded samba executable. + +However, when downgrading from v4.11 you will need to manually downgrade the AD +database yourself. Note that you will need to do this step before you install +the downgraded Samba packages. For more details, see: +https://wiki.samba.org/index.php/Downgrading_an_Active_Directory_DC + +When either upgrading or downgrading, users should also avoid making any +database modifications between installing the new Samba packages and starting +the samba executable. + +Note that when moving between major Samba releases in general, we recommend +that the AD DC is rejoined to the domain. Using this approach avoids the need +to explicitly downgrade the database manually. For more details, see: +https://wiki.samba.org/index.php/Upgrading_a_Samba_AD_DC + SMB1 is disabled by default --------------------------- -- 2.17.1 From 6b4c51d0c94a34ccd310f4c0e470f043407659d6 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Mon, 29 Jul 2019 10:35:23 +1200 Subject: [PATCH 018/376] WHATSNEW: Add link to 2012 Windows compatibility wiki page There's now a lot more info on the wiki on Windows 2012 compatibility, and how the schema is just a small part of overall compatibility. Link to this wiki page from the WHATSNEW, so users can read more about this. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14057 Signed-off-by: Tim Beale --- WHATSNEW.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index c94b3541d7d..3276d884f3a 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -142,6 +142,10 @@ Samba's replication code has also been improved to handle replication with the 2012 schema (the core of this replication fix has also been backported to 4.9.11 and will be in a 4.10.x release). +For more about how the AD schema relates to overall Windows compatibility, +please read: +https://wiki.samba.org/index.php/Windows_2012_Server_compatibility + GnuTLS 3.2 required ------------------- -- 2.17.1 From 62e65124e9d720d5dd27d822e7a25df24ea9f81b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jul 2019 14:17:02 +0200 Subject: [PATCH 019/376] smbd: Fix use-after-free from exit_server_common() We need to keep the smbXsrv_connection structures around until all pending requests have had their chance to clean up behind them. If you look at srv_send_smb(), it's exactly prepared already to just drop anything on the floor when the transport has been declared dead: if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ return true; } Bug: https://bugzilla.samba.org/show_bug.cgi?id=14064 Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Aug 1 15:39:13 UTC 2019 on sn-devel-184 (cherry picked from commit c226dc6e8a18343031829c35552e557903593daf) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Aug 7 12:53:51 UTC 2019 on sn-devel-184 --- source3/smbd/server_exit.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 2378c0c15ca..b21501a7a23 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -91,7 +91,6 @@ static void exit_server_common(enum server_exit_reason how, { struct smbXsrv_client *client = global_smbXsrv_client; struct smbXsrv_connection *xconn = NULL; - struct smbXsrv_connection *xconn_next = NULL; struct smbd_server_connection *sconn = NULL; struct messaging_context *msg_ctx = global_messaging_context(); @@ -110,10 +109,7 @@ static void exit_server_common(enum server_exit_reason how, /* * Here we typically have just one connection */ - for (; xconn != NULL; xconn = xconn_next) { - xconn_next = xconn->next; - DLIST_REMOVE(client->connections, xconn); - + for (; xconn != NULL; xconn = xconn->next) { /* * This is typically the disconnect for the only * (or with multi-channel last) connection of the client @@ -128,8 +124,6 @@ static void exit_server_common(enum server_exit_reason how, break; } } - - TALLOC_FREE(xconn); DO_PROFILE_INC(disconnect); } @@ -172,6 +166,20 @@ static void exit_server_common(enum server_exit_reason how, change_to_root_user(); + if (client != NULL) { + struct smbXsrv_connection *xconn_next = NULL; + + for (xconn = client->connections; + xconn != NULL; + xconn = xconn_next) { + xconn_next = xconn->next; + DLIST_REMOVE(client->connections, xconn); + TALLOC_FREE(xconn); + } + } + + change_to_root_user(); + /* 3 second timeout. */ print_notify_send_messages(msg_ctx, 3); -- 2.17.1 From 428ecb5f4e2bb399e90f50dcd56054062bbaf85a Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 13 Aug 2019 11:33:01 +0200 Subject: [PATCH 020/376] WHATSNEW: Fix some minor formatting issues. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 3276d884f3a..6a0cc9d72fd 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -15,16 +15,16 @@ UPGRADING AD Database compatibility ------------------------- -Samba v4.11 has changed how the AD database is stored on disk. AD users should -not really be affected by this change when upgrading to v4.11. However, AD -users should be extremely careful if they need to downgrade from Samba v4.11 to +Samba 4.11 has changed how the AD database is stored on disk. AD users should +not really be affected by this change when upgrading to 4.11. However, AD +users should be extremely careful if they need to downgrade from Samba 4.11 to an older release. -Samba v4.11 maintains database compatibility with older Samba releases. The -database will automatically get rewritten in the new v4.11 format when you +Samba 4.11 maintains database compatibility with older Samba releases. The +database will automatically get rewritten in the new 4.11 format when you first start the upgraded samba executable. -However, when downgrading from v4.11 you will need to manually downgrade the AD +However, when downgrading from 4.11 you will need to manually downgrade the AD database yourself. Note that you will need to do this step before you install the downgraded Samba packages. For more details, see: https://wiki.samba.org/index.php/Downgrading_an_Active_Directory_DC @@ -56,7 +56,7 @@ and LANMAN1 for client and server, as well as CORE and COREPLUS on the client. Note that most commandline tools e.g. smbclient, smbcacls and others -also support the --option argument to overwrite smb.conf options, +also support the '--option' argument to overwrite smb.conf options, e.g. --option='client min protocol=NT1' might be useful. As Microsoft no longer installs SMB1 support in recent releases @@ -74,7 +74,7 @@ NEW FEATURES/CHANGES Default samba process model --------------------------- -The default for the --model argument passed to the samba executable has changed +The default for the '--model' argument passed to the samba executable has changed from 'standard' to 'prefork'. This means a difference in the number of samba child processes that are created to handle client connections. The previous default would create a separate process for every LDAP or NETLOGON client @@ -102,26 +102,27 @@ where: is the name of the command makinmg the winbind request i.e. wbinfo is the process id of the requesting process. -The version of the JSON Authentication messages has been changed to 1.2 from 1.1 +The version of the JSON Authentication messages has been changed from 1.1 to +1.2. LDAP referrals -------------- The scheme of returned LDAP referrals now reflects the scheme of the original request, i.e. referrals received via ldap are prefixed with "ldap://" -and those over ldaps are prefixed with "ldaps://" +and those over ldaps are prefixed with "ldaps://". -Previously all referrals were prefixed with "ldap://" +Previously all referrals were prefixed with "ldap://". Bind9 logging ------------- -It is now possible to log the duration of DNS operations performed by Bind9 -This should aid future diagnosis of performance issues, and could be used to +It is now possible to log the duration of DNS operations performed by Bind9. +This should aid future diagnosis of performance issues and could be used to monitor DNS performance. The logging is enabled by setting log level to -"dns:10" in smb.conf +"dns:10" in smb.conf. -The logs are currently Human readable text only, i.e. no JSON formatted output. +The logs are currently human readable text only, i.e. no JSON formatted output. Log lines are of the form: @@ -210,7 +211,7 @@ multiple times into memory. Setting lmdb map size --------------------- -It is now possible to set the lmdb map size (The maximum permitted +It is now possible to set the lmdb map size (the maximum permitted size for the database). "samba-tool" now accepts the "--backend-store-size" i.e. --backend-store-size=4Gb. If not specified it defaults to 8Gb. @@ -302,14 +303,12 @@ Samba still supported a Python WSGI web server (which could still be turned on from the 'server services' smb.conf parameter). This service was unused and has now been removed from Samba. - samba-tool join subdomain ------------------------- The subdomain role has been removed from the join command. This option did not work and has no tests. - Python2 support --------------- -- 2.17.1 From 8dfa63d9f7236a534fb454e50e6dff41d07ae89c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 1 Aug 2019 21:08:52 +0300 Subject: [PATCH 021/376] torture/rpc/lsa: allow testing different lookup levels Convert torture/rpc/lsa LookupNames/LookupSids code to allow testing different LSA_LOOKUP_NAMES_* levels. Keep existing level 1 (LSA_LOOKUP_NAMES_ALL) for the current set of tests. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14091 Signed-off-by: Alexander Bokovoy Reviewed-by: Andreas Schneider (cherry picked from commit 317bc6a7342edfa2c503f5932142bf5883485cc9) --- source4/torture/rpc/lsa.c | 118 ++++++++++++++++++--------------- source4/torture/rpc/schannel.c | 2 +- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 5b16ed9a014..fdbfcbffc16 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -281,6 +281,7 @@ static bool test_OpenPolicy2_fail(struct dcerpc_binding_handle *b, static bool test_LookupNames(struct dcerpc_binding_handle *b, struct torture_context *tctx, struct policy_handle *handle, + enum lsa_LookupNamesLevel level, struct lsa_TransNameArray *tnames) { struct lsa_LookupNames r; @@ -313,7 +314,7 @@ static bool test_LookupNames(struct dcerpc_binding_handle *b, r.in.handle = handle; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.out.count = &count; r.out.sids = &sids; @@ -369,7 +370,8 @@ static bool test_LookupNames(struct dcerpc_binding_handle *b, static bool test_LookupNames_bogus(struct dcerpc_binding_handle *b, struct torture_context *tctx, - struct policy_handle *handle) + struct policy_handle *handle, + enum lsa_LookupNamesLevel level) { struct lsa_LookupNames r; struct lsa_TransSidArray sids; @@ -388,7 +390,7 @@ static bool test_LookupNames_bogus(struct dcerpc_binding_handle *b, r.in.num_names = 1; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.out.count = &count; r.out.sids = &sids; @@ -409,7 +411,8 @@ static bool test_LookupNames_bogus(struct dcerpc_binding_handle *b, static bool test_LookupNames_NULL(struct dcerpc_binding_handle *b, struct torture_context *tctx, - struct policy_handle *handle) + struct policy_handle *handle, + enum lsa_LookupNamesLevel level) { struct lsa_LookupNames r; struct lsa_TransSidArray sids; @@ -428,7 +431,7 @@ static bool test_LookupNames_NULL(struct dcerpc_binding_handle *b, r.in.num_names = 1; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.out.count = &count; r.out.sids = &sids; @@ -453,7 +456,8 @@ static bool test_LookupNames_NULL(struct dcerpc_binding_handle *b, static bool test_LookupNames_wellknown(struct dcerpc_binding_handle *b, struct torture_context *tctx, - struct policy_handle *handle) + struct policy_handle *handle, + enum lsa_LookupNamesLevel level) { struct lsa_TranslatedName name; struct lsa_TransNameArray tnames; @@ -465,45 +469,46 @@ static bool test_LookupNames_wellknown(struct dcerpc_binding_handle *b, tnames.count = 1; name.name.string = "NT AUTHORITY\\SYSTEM"; name.sid_type = SID_NAME_WKN_GRP; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); name.name.string = "NT AUTHORITY\\ANONYMOUS LOGON"; name.sid_type = SID_NAME_WKN_GRP; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); name.name.string = "NT AUTHORITY\\Authenticated Users"; name.sid_type = SID_NAME_WKN_GRP; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); #if 0 name.name.string = "NT AUTHORITY"; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); name.name.string = "NT AUTHORITY\\"; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); #endif name.name.string = "BUILTIN\\"; name.sid_type = SID_NAME_DOMAIN; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); name.name.string = "BUILTIN\\Administrators"; name.sid_type = SID_NAME_ALIAS; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); name.name.string = "SYSTEM"; name.sid_type = SID_NAME_WKN_GRP; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); name.name.string = "Everyone"; name.sid_type = SID_NAME_WKN_GRP; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, level, &tnames); return ret; } static bool test_LookupNames2(struct dcerpc_binding_handle *b, struct torture_context *tctx, struct policy_handle *handle, + enum lsa_LookupNamesLevel level, struct lsa_TransNameArray2 *tnames, bool check_result) { @@ -536,7 +541,7 @@ static bool test_LookupNames2(struct dcerpc_binding_handle *b, r.in.handle = handle; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -565,6 +570,7 @@ static bool test_LookupNames2(struct dcerpc_binding_handle *b, static bool test_LookupNames3(struct dcerpc_binding_handle *b, struct torture_context *tctx, struct policy_handle *handle, + enum lsa_LookupNamesLevel level, struct lsa_TransNameArray2 *tnames, bool check_result) { @@ -596,7 +602,7 @@ static bool test_LookupNames3(struct dcerpc_binding_handle *b, r.in.handle = handle; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -624,6 +630,7 @@ static bool test_LookupNames3(struct dcerpc_binding_handle *b, static bool test_LookupNames4(struct dcerpc_binding_handle *b, struct torture_context *tctx, + enum lsa_LookupNamesLevel level, struct lsa_TransNameArray2 *tnames, bool check_result) { @@ -655,7 +662,7 @@ static bool test_LookupNames4(struct dcerpc_binding_handle *b, r.in.num_names = tnames->count; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -693,7 +700,8 @@ static bool test_LookupNames4(struct dcerpc_binding_handle *b, } static bool test_LookupNames4_fail(struct dcerpc_binding_handle *b, - struct torture_context *tctx) + struct torture_context *tctx, + enum lsa_LookupNamesLevel level) { struct lsa_LookupNames4 r; struct lsa_TransSidArray3 sids; @@ -712,7 +720,7 @@ static bool test_LookupNames4_fail(struct dcerpc_binding_handle *b, r.in.num_names = count; r.in.names = names; r.in.sids = &sids; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -760,6 +768,7 @@ static bool test_LookupNames4_fail(struct dcerpc_binding_handle *b, static bool test_LookupSids(struct dcerpc_binding_handle *b, struct torture_context *tctx, struct policy_handle *handle, + enum lsa_LookupNamesLevel level, struct lsa_SidArray *sids) { struct lsa_LookupSids r; @@ -775,7 +784,7 @@ static bool test_LookupSids(struct dcerpc_binding_handle *b, r.in.handle = handle; r.in.sids = sids; r.in.names = &names; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.out.count = &count; r.out.names = &names; @@ -790,7 +799,7 @@ static bool test_LookupSids(struct dcerpc_binding_handle *b, torture_comment(tctx, "\n"); - if (!test_LookupNames(b, tctx, handle, &names)) { + if (!test_LookupNames(b, tctx, handle, level, &names)) { return false; } @@ -801,6 +810,7 @@ static bool test_LookupSids(struct dcerpc_binding_handle *b, static bool test_LookupSids2(struct dcerpc_binding_handle *b, struct torture_context *tctx, struct policy_handle *handle, + enum lsa_LookupNamesLevel level, struct lsa_SidArray *sids) { struct lsa_LookupSids2 r; @@ -816,7 +826,7 @@ static bool test_LookupSids2(struct dcerpc_binding_handle *b, r.in.handle = handle; r.in.sids = sids; r.in.names = &names; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -835,11 +845,11 @@ static bool test_LookupSids2(struct dcerpc_binding_handle *b, torture_comment(tctx, "\n"); - if (!test_LookupNames2(b, tctx, handle, &names, false)) { + if (!test_LookupNames2(b, tctx, handle, level, &names, false)) { return false; } - if (!test_LookupNames3(b, tctx, handle, &names, false)) { + if (!test_LookupNames3(b, tctx, handle, level, &names, false)) { return false; } @@ -848,6 +858,7 @@ static bool test_LookupSids2(struct dcerpc_binding_handle *b, static bool test_LookupSids3(struct dcerpc_binding_handle *b, struct torture_context *tctx, + enum lsa_LookupNamesLevel level, struct lsa_SidArray *sids) { struct lsa_LookupSids3 r; @@ -862,7 +873,7 @@ static bool test_LookupSids3(struct dcerpc_binding_handle *b, r.in.sids = sids; r.in.names = &names; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -891,7 +902,7 @@ static bool test_LookupSids3(struct dcerpc_binding_handle *b, torture_comment(tctx, "\n"); - if (!test_LookupNames4(b, tctx, &names, true)) { + if (!test_LookupNames4(b, tctx, level, &names, true)) { return false; } @@ -900,6 +911,7 @@ static bool test_LookupSids3(struct dcerpc_binding_handle *b, static bool test_LookupSids3_fail(struct dcerpc_binding_handle *b, struct torture_context *tctx, + enum lsa_LookupNamesLevel level, struct lsa_SidArray *sids) { struct lsa_LookupSids3 r; @@ -915,7 +927,7 @@ static bool test_LookupSids3_fail(struct dcerpc_binding_handle *b, r.in.sids = sids; r.in.names = &names; - r.in.level = 1; + r.in.level = level; r.in.count = &count; r.in.lookup_options = 0; r.in.client_revision = 0; @@ -959,7 +971,8 @@ static bool test_LookupSids3_fail(struct dcerpc_binding_handle *b, bool test_many_LookupSids(struct dcerpc_pipe *p, struct torture_context *tctx, - struct policy_handle *handle) + struct policy_handle *handle, + enum lsa_LookupNamesLevel level) { uint32_t count; struct lsa_SidArray sids; @@ -990,7 +1003,7 @@ bool test_many_LookupSids(struct dcerpc_pipe *p, r.in.handle = handle; r.in.sids = &sids; r.in.names = &names; - r.in.level = 1; + r.in.level = level; r.in.count = &names.count; r.out.count = &count; r.out.names = &names; @@ -1006,16 +1019,16 @@ bool test_many_LookupSids(struct dcerpc_pipe *p, torture_comment(tctx, "\n"); - if (!test_LookupNames(b, tctx, handle, &names)) { + if (!test_LookupNames(b, tctx, handle, level, &names)) { return false; } } if (transport == NCACN_NP) { - if (!test_LookupSids3_fail(b, tctx, &sids)) { + if (!test_LookupSids3_fail(b, tctx, level, &sids)) { return false; } - if (!test_LookupNames4_fail(b, tctx)) { + if (!test_LookupNames4_fail(b, tctx, level)) { return false; } } else if (transport == NCACN_IP_TCP) { @@ -1031,10 +1044,10 @@ bool test_many_LookupSids(struct dcerpc_pipe *p, if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL && auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) { - if (!test_LookupSids3(b, tctx, &sids)) { + if (!test_LookupSids3(b, tctx, level, &sids)) { return false; } - if (!test_LookupNames4(b, tctx, &names, true)) { + if (!test_LookupNames4(b, tctx, level, &names, true)) { return false; } } else { @@ -1042,10 +1055,10 @@ bool test_many_LookupSids(struct dcerpc_pipe *p, * If we don't have a secure channel these tests must * fail with ACCESS_DENIED. */ - if (!test_LookupSids3_fail(b, tctx, &sids)) { + if (!test_LookupSids3_fail(b, tctx, level, &sids)) { return false; } - if (!test_LookupNames4_fail(b, tctx)) { + if (!test_LookupNames4_fail(b, tctx, level)) { return false; } } @@ -1077,7 +1090,8 @@ static void lookupsids_cb(struct tevent_req *subreq) static bool test_LookupSids_async(struct dcerpc_binding_handle *b, struct torture_context *tctx, - struct policy_handle *handle) + struct policy_handle *handle, + enum lsa_LookupNamesLevel level) { struct lsa_SidArray sids; struct lsa_SidPtr sidptr; @@ -1112,7 +1126,7 @@ static bool test_LookupSids_async(struct dcerpc_binding_handle *b, r[i].in.handle = handle; r[i].in.sids = &sids; r[i].in.names = &names[i]; - r[i].in.level = 1; + r[i].in.level = level; r[i].in.count = &names[i].count; r[i].out.count = &count[i]; r[i].out.names = &names[i]; @@ -1923,11 +1937,11 @@ static bool test_EnumAccounts(struct dcerpc_binding_handle *b, torture_assert_ntstatus_ok(tctx, r.out.result, "EnumAccounts failed"); - if (!test_LookupSids(b, tctx, handle, &sids1)) { + if (!test_LookupSids(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &sids1)) { return false; } - if (!test_LookupSids2(b, tctx, handle, &sids1)) { + if (!test_LookupSids2(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &sids1)) { return false; } @@ -4836,7 +4850,7 @@ static bool test_QueryInfoPolicyCalls( bool version2, tnames.names[12].sid_type = SID_NAME_USER; tnames.names[13].name.string = talloc_asprintf(tctx, TEST_MACHINENAME "$@%s", info->dns.dns_domain.string); tnames.names[13].sid_type = SID_NAME_USER; - ret &= test_LookupNames(b, tctx, handle, &tnames); + ret &= test_LookupNames(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &tnames); } } @@ -5002,7 +5016,7 @@ bool torture_rpc_lsa(struct torture_context *tctx) ret = false; } - if (!test_many_LookupSids(p, tctx, handle)) { + if (!test_many_LookupSids(p, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } @@ -5023,7 +5037,7 @@ bool torture_rpc_lsa(struct torture_context *tctx) ret = false; } - if (!test_LookupSids_async(b, tctx, handle)) { + if (!test_LookupSids_async(b, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } @@ -5047,7 +5061,7 @@ bool torture_rpc_lsa(struct torture_context *tctx) ret = false; } - if (!test_many_LookupSids(p, tctx, handle)) { + if (!test_many_LookupSids(p, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } @@ -5058,7 +5072,7 @@ bool torture_rpc_lsa(struct torture_context *tctx) torture_leave_domain(tctx, join); } else { - if (!test_many_LookupSids(p, tctx, handle)) { + if (!test_many_LookupSids(p, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } } @@ -5133,7 +5147,7 @@ static bool testcase_LookupNames(struct torture_context *tctx, tnames.names[0].name.string = "BUILTIN"; tnames.names[0].sid_type = SID_NAME_DOMAIN; - if (!test_LookupNames(b, tctx, handle, &tnames)) { + if (!test_LookupNames(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &tnames)) { ret = false; } @@ -5143,23 +5157,23 @@ static bool testcase_LookupNames(struct torture_context *tctx, tnames2.names[0].name.string = "BUILTIN"; tnames2.names[0].sid_type = SID_NAME_DOMAIN; - if (!test_LookupNames2(b, tctx, handle, &tnames2, true)) { + if (!test_LookupNames2(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &tnames2, true)) { ret = false; } - if (!test_LookupNames3(b, tctx, handle, &tnames2, true)) { + if (!test_LookupNames3(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &tnames2, true)) { ret = false; } - if (!test_LookupNames_wellknown(b, tctx, handle)) { + if (!test_LookupNames_wellknown(b, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } - if (!test_LookupNames_NULL(b, tctx, handle)) { + if (!test_LookupNames_NULL(b, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } - if (!test_LookupNames_bogus(b, tctx, handle)) { + if (!test_LookupNames_bogus(b, tctx, handle, LSA_LOOKUP_NAMES_ALL)) { ret = false; } diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index 5b40af216a5..fff0b1aacbd 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -470,7 +470,7 @@ static bool test_schannel(struct torture_context *tctx, "failed to connect lsarpc with schannel"); torture_assert(tctx, - test_many_LookupSids(p_lsa, tctx, NULL), + test_many_LookupSids(p_lsa, tctx, NULL, LSA_LOOKUP_NAMES_ALL), "LsaLookupSids3 failed!\n"); status = dcerpc_binding_set_transport(b, transport); -- 2.17.1 From 60d222327343599d13643ee54e041cd65373a7eb Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 1 Aug 2019 15:48:58 +0300 Subject: [PATCH 022/376] lookup_name: allow own domain lookup when flags == 0 In 2007, we've added support for multiple lookup levels for LSA LookupNames family of calls. However, forest-wide lookups, as described in MS-LSAT 2.2.16, never worked because flags passed to lookup_name() were always set to zero, expecting at least default lookup on a DC to apply. lookup_name() was instead treating zero flags as 'skip all checks'. Allow at least own domain lookup in case domain name is the same. This should allow FreeIPA DC to respond to LSA LookupNames3 calls from a trusted AD DC side. For the reference, below is a request Windows Server 2016 domain controller sends to FreeIPA domain controller when attempting to look up a user from a trusted forest root domain that attemps to login to the domain controller. Notice the level in the lsa_LookupNames3 call and resulting flags in lookup_name(). [2019/08/03 07:14:24.156065, 1, pid=23639, effective(967001000, 967001000), real(967001000, 0), class=rpc_parse] ../../librpc/ndr/ndr.c:471(ndr_print_function_debug) lsa_LookupNames3: struct lsa_LookupNames3 in: struct lsa_LookupNames3 handle : * handle: struct policy_handle handle_type : 0x00000000 (0) uuid : 0000004c-0000-0000-455d-3018575c0000 num_names : 0x00000001 (1) names: ARRAY(1) names: struct lsa_String length : 0x000a (10) size : 0x000c (12) string : * string : 'XS\ab' sids : * sids: struct lsa_TransSidArray3 count : 0x00000000 (0) sids : NULL level : LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 (6) count : * count : 0x00000000 (0) lookup_options : LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES (0) client_revision : LSA_CLIENT_REVISION_2 (2) [2019/08/03 07:14:24.156189, 6, pid=23639, effective(967001000, 967001000), real(967001000, 0), class=rpc_srv] ../../source3/rpc_server/rpc_handles.c:339(find_policy_by_hnd_internal) Found policy hnd[0] [0000] 00 00 00 00 4C 00 00 00 00 00 00 00 45 5D 30 18 ....L... ....E]0. [0010] 57 5C 00 00 W\.. [2019/08/03 07:14:24.156228, 4, pid=23639, effective(967001000, 967001000), real(967001000, 0)] ../../source3/smbd/sec_ctx.c:215(push_sec_ctx) push_sec_ctx(967001000, 967001000) : sec_ctx_stack_ndx = 2 [2019/08/03 07:14:24.156246, 4, pid=23639, effective(967001000, 967001000), real(967001000, 0)] ../../source3/smbd/uid.c:552(push_conn_ctx) push_conn_ctx(0) : conn_ctx_stack_ndx = 0 [2019/08/03 07:14:24.156259, 4, pid=23639, effective(967001000, 967001000), real(967001000, 0)] ../../source3/smbd/sec_ctx.c:319(set_sec_ctx_internal) setting sec ctx (0, 0) - sec_ctx_stack_ndx = 2 [2019/08/03 07:14:24.156273, 5, pid=23639, effective(967001000, 967001000), real(967001000, 0)] ../../libcli/security/security_token.c:53(security_token_debug) Security token: (NULL) [2019/08/03 07:14:24.156285, 5, pid=23639, effective(967001000, 967001000), real(967001000, 0)] ../../source3/auth/token_util.c:865(debug_unix_user_token) UNIX token of user 0 Primary group is 0 and contains 0 supplementary groups [2019/08/03 07:14:24.156311, 5, pid=23639, effective(0, 0), real(0, 0), class=rpc_srv] ../../source3/rpc_server/lsa/srv_lsa_nt.c:244(lookup_lsa_sids) lookup_lsa_sids: looking up name XS\ab [2019/08/03 07:14:24.156327, 10, pid=23639, effective(0, 0), real(0, 0)] ../../source3/passdb/lookup_sid.c:112(lookup_name) lookup_name: XS\ab => domain=[XS], name=[ab] [2019/08/03 07:14:24.156340, 10, pid=23639, effective(0, 0), real(0, 0)] ../../source3/passdb/lookup_sid.c:114(lookup_name) lookup_name: flags = 0x00 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14091 Signed-off-by: Alexander Bokovoy Reviewed-by: Andreas Schneider (cherry picked from commit 685bb03de6ab733590831d1df4f5fd60d2ac427d) --- source3/passdb/lookup_sid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 6ab72e57838..c31a9e48739 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -113,7 +113,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, full_name, domain, name)); DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags)); - if ((flags & LOOKUP_NAME_DOMAIN) && + if (((flags & LOOKUP_NAME_DOMAIN) || (flags == 0)) && strequal(domain, get_global_sam_name())) { -- 2.17.1 From 38876ad4ef46fc3cf6a12329236918a87c2e2c65 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sat, 10 Aug 2019 11:53:12 +0300 Subject: [PATCH 023/376] smbtorture: extend rpc.lsa to lookup machine over forest-wide LookupNames Add a simple test to resolve DOMAIN\MACHINE$ via LSA LookupNames3 using LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 level. This level would pass zero lookup flags to lookup_name(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14091 Signed-off-by: Alexander Bokovoy Reviewed-by: Andreas Schneider Autobuild-User(master): Alexander Bokovoy Autobuild-Date(master): Wed Aug 14 13:07:42 UTC 2019 on sn-devel-184 (cherry picked from commit 4d276a93fc624dc04d880f5b4157f272d3555be6) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Mon Aug 19 12:36:22 UTC 2019 on sn-devel-184 --- source4/torture/rpc/lsa.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index fdbfcbffc16..0ce113feb5d 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -4819,7 +4819,7 @@ static bool test_QueryInfoPolicyCalls( bool version2, || i == LSA_POLICY_INFO_DNS_INT)) { /* Let's look up some of these names */ - struct lsa_TransNameArray tnames; + struct lsa_TransNameArray tnames, dnames; tnames.count = 14; tnames.names = talloc_zero_array(tctx, struct lsa_TranslatedName, tnames.count); tnames.names[0].name.string = info->dns.name.string; @@ -4852,6 +4852,12 @@ static bool test_QueryInfoPolicyCalls( bool version2, tnames.names[13].sid_type = SID_NAME_USER; ret &= test_LookupNames(b, tctx, handle, LSA_LOOKUP_NAMES_ALL, &tnames); + /* Try to use in-forest search for the test machine */ + dnames.count = 1; + dnames.names = talloc_zero_array(tctx, struct lsa_TranslatedName, dnames.count); + dnames.names[0].name.string = talloc_asprintf(tctx, "%s\\"TEST_MACHINENAME "$", info->dns.name.string); + dnames.names[0].sid_type = SID_NAME_USER; + ret &= test_LookupNames(b, tctx, handle, LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2, &dnames); } } -- 2.17.1 From fab20658b9a4d04e2eab89d95b6eb7e04187424d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Aug 2019 12:10:03 +0200 Subject: [PATCH 024/376] tdb: Rename tdb_oob() to tdb_notrans_oob() tdb_oob() will become a public function encapsulating the pointer dereferences. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 885ba572efaac6c20388b8e119315c837e8f5236) --- lib/tdb/common/io.c | 6 +++--- lib/tdb/test/run-3G-file.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c index df460176159..06492b1407d 100644 --- a/lib/tdb/common/io.c +++ b/lib/tdb/common/io.c @@ -136,8 +136,8 @@ static int tdb_fstat(struct tdb_context *tdb, struct stat *buf) see if the database has been expanded by someone else and expand if necessary */ -static int tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, - int probe) +static int tdb_notrans_oob( + struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) { struct stat st; if (len + off < len) { @@ -782,7 +782,7 @@ static const struct tdb_methods io_methods = { tdb_read, tdb_write, tdb_next_hash_chain, - tdb_oob, + tdb_notrans_oob, tdb_expand_file, }; diff --git a/lib/tdb/test/run-3G-file.c b/lib/tdb/test/run-3G-file.c index 748c972284a..79e291b294e 100644 --- a/lib/tdb/test/run-3G-file.c +++ b/lib/tdb/test/run-3G-file.c @@ -48,7 +48,7 @@ static const struct tdb_methods large_io_methods = { tdb_read, tdb_write, tdb_next_hash_chain, - tdb_oob, + tdb_notrans_oob, tdb_expand_file_sparse }; -- 2.17.1 From 6312223d6e609d629dfc7914d62bf80ced584c6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Aug 2019 12:15:14 +0200 Subject: [PATCH 025/376] tdb: Introduce tdb_oob() Initially just encapsulate the pointer dereferences Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 5a388453e0cb038fa3ed5fb46f972470f7793566) --- lib/tdb/common/check.c | 6 +++--- lib/tdb/common/freelist.c | 2 +- lib/tdb/common/io.c | 22 ++++++++++++++-------- lib/tdb/common/open.c | 6 +++--- lib/tdb/common/rescue.c | 4 ++-- lib/tdb/common/tdb_private.h | 1 + lib/tdb/common/transaction.c | 2 +- lib/tdb/common/traverse.c | 3 +-- 8 files changed, 26 insertions(+), 20 deletions(-) diff --git a/lib/tdb/common/check.c b/lib/tdb/common/check.c index 3a5c8b8ba94..d7741f6b2f9 100644 --- a/lib/tdb/common/check.c +++ b/lib/tdb/common/check.c @@ -94,7 +94,7 @@ static bool tdb_check_record(struct tdb_context *tdb, off, rec->next)); goto corrupt; } - if (tdb->methods->tdb_oob(tdb, rec->next, sizeof(*rec), 0)) + if (tdb_oob(tdb, rec->next, sizeof(*rec), 0)) goto corrupt; /* Check rec_len: similar to rec->next, implies next record. */ @@ -112,7 +112,7 @@ static bool tdb_check_record(struct tdb_context *tdb, goto corrupt; } /* OOB allows "right at the end" access, so this works for last rec. */ - if (tdb->methods->tdb_oob(tdb, off, sizeof(*rec)+rec->rec_len, 0)) + if (tdb_oob(tdb, off, sizeof(*rec)+rec->rec_len, 0)) goto corrupt; /* Check tailer. */ @@ -362,7 +362,7 @@ _PUBLIC_ int tdb_check(struct tdb_context *tdb, } /* Make sure we know true size of the underlying file. */ - tdb->methods->tdb_oob(tdb, tdb->map_size, 1, 1); + tdb_oob(tdb, tdb->map_size, 1, 1); /* Header must be OK: also gets us the recovery ptr, if any. */ if (!tdb_check_header(tdb, &recovery_start)) diff --git a/lib/tdb/common/freelist.c b/lib/tdb/common/freelist.c index 37a4c168533..046c747cf9b 100644 --- a/lib/tdb/common/freelist.c +++ b/lib/tdb/common/freelist.c @@ -50,7 +50,7 @@ int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct tdb_record rec->magic, off)); return -1; } - if (tdb->methods->tdb_oob(tdb, rec->next, sizeof(*rec), 0) != 0) + if (tdb_oob(tdb, rec->next, sizeof(*rec), 0) != 0) return -1; return 0; } diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c index 06492b1407d..f3ea7bf9856 100644 --- a/lib/tdb/common/io.c +++ b/lib/tdb/common/io.c @@ -216,7 +216,7 @@ static int tdb_write(struct tdb_context *tdb, tdb_off_t off, return -1; } - if (tdb->methods->tdb_oob(tdb, off, len, 0) != 0) + if (tdb_oob(tdb, off, len, 0) != 0) return -1; if (tdb->map_ptr) { @@ -271,7 +271,7 @@ void *tdb_convert(void *buf, uint32_t size) static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv) { - if (tdb->methods->tdb_oob(tdb, off, len, 0) != 0) { + if (tdb_oob(tdb, off, len, 0) != 0) { return -1; } @@ -596,7 +596,7 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) } /* must know about any previous expansions by another process */ - tdb->methods->tdb_oob(tdb, tdb->map_size, 1, 1); + tdb_oob(tdb, tdb->map_size, 1, 1); /* * Note: that we don't care about tdb->hdr_ofs != 0 here @@ -662,6 +662,12 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) return -1; } +int tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) +{ + int ret = tdb->methods->tdb_oob(tdb, off, len, probe); + return ret; +} + /* read/write a tdb_off_t */ int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) { @@ -714,7 +720,7 @@ int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, * Optimize by avoiding the malloc/memcpy/free, point the * parser directly at the mmap area. */ - if (tdb->methods->tdb_oob(tdb, offset, len, 0) != 0) { + if (tdb_oob(tdb, offset, len, 0) != 0) { return -1; } data.dptr = offset + (unsigned char *)tdb->map_ptr; @@ -756,20 +762,20 @@ int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *r return -1; } - ret = tdb->methods->tdb_oob(tdb, offset, rec->key_len, 1); + ret = tdb_oob(tdb, offset, rec->key_len, 1); if (ret == -1) { return -1; } - ret = tdb->methods->tdb_oob(tdb, offset, rec->data_len, 1); + ret = tdb_oob(tdb, offset, rec->data_len, 1); if (ret == -1) { return -1; } - ret = tdb->methods->tdb_oob(tdb, offset, rec->rec_len, 1); + ret = tdb_oob(tdb, offset, rec->rec_len, 1); if (ret == -1) { return -1; } - return tdb->methods->tdb_oob(tdb, rec->next, sizeof(*rec), 0); + return tdb_oob(tdb, rec->next, sizeof(*rec), 0); } int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c index dd5783ef8bc..f7f65b0e237 100644 --- a/lib/tdb/common/open.c +++ b/lib/tdb/common/open.c @@ -655,7 +655,7 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td * As this skips tdb->hdr_ofs. */ tdb->map_size = 0; - ret = tdb->methods->tdb_oob(tdb, 0, 1, 0); + ret = tdb_oob(tdb, 0, 1, 0); if (ret == -1) { errno = EIO; goto fail; @@ -677,7 +677,7 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td goto fail; } - ret = tdb->methods->tdb_oob(tdb, FREELIST_TOP, 4*tdb->hash_size, 1); + ret = tdb_oob(tdb, FREELIST_TOP, 4*tdb->hash_size, 1); if (ret == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " "hash size %"PRIu32" does not fit\n", tdb->hash_size)); @@ -895,7 +895,7 @@ static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock) * As this skips tdb->hdr_ofs. */ tdb->map_size = 0; - if (tdb->methods->tdb_oob(tdb, 0, 1, 0) != 0) { + if (tdb_oob(tdb, 0, 1, 0) != 0) { goto fail; } #endif /* fake pread or pwrite */ diff --git a/lib/tdb/common/rescue.c b/lib/tdb/common/rescue.c index e608db41dea..7a85ebc9311 100644 --- a/lib/tdb/common/rescue.c +++ b/lib/tdb/common/rescue.c @@ -60,7 +60,7 @@ static bool looks_like_valid_record(struct tdb_context *tdb, if (rec->next > 0 && rec->next < TDB_DATA_START(tdb->hash_size)) return false; - if (tdb->methods->tdb_oob(tdb, rec->next, sizeof(*rec), 1)) + if (tdb_oob(tdb, rec->next, sizeof(*rec), 1)) return false; key->dsize = rec->key_len; @@ -228,7 +228,7 @@ _PUBLIC_ int tdb_rescue(struct tdb_context *tdb, } /* Make sure we know true size of the underlying file. */ - tdb->methods->tdb_oob(tdb, tdb->map_size, 1, 1); + tdb_oob(tdb, tdb->map_size, 1, 1); /* Suppress logging, since we anticipate errors. */ tdb->log.log_fn = logging_suppressed; diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h index 42aaac62f59..2bed8200f94 100644 --- a/lib/tdb/common/tdb_private.h +++ b/lib/tdb/common/tdb_private.h @@ -304,6 +304,7 @@ void *tdb_convert(void *buf, uint32_t size); int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length, struct tdb_record *rec); +int tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe); int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c index e9b0b26ea59..b22624820d7 100644 --- a/lib/tdb/common/transaction.c +++ b/lib/tdb/common/transaction.c @@ -524,7 +524,7 @@ static int _tdb_transaction_start(struct tdb_context *tdb, /* make sure we know about any file expansions already done by anyone else */ - tdb->methods->tdb_oob(tdb, tdb->map_size, 1, 1); + tdb_oob(tdb, tdb->map_size, 1, 1); tdb->transaction->old_map_size = tdb->map_size; /* finally hook the io methods, replacing them with diff --git a/lib/tdb/common/traverse.c b/lib/tdb/common/traverse.c index 54a69dc8d03..d69e7dff285 100644 --- a/lib/tdb/common/traverse.c +++ b/lib/tdb/common/traverse.c @@ -453,8 +453,7 @@ _PUBLIC_ int tdb_traverse_chain(struct tdb_context *tdb, if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { - ret = tdb->methods->tdb_oob( - tdb, key_ofs, full_len, 0); + ret = tdb_oob(tdb, key_ofs, full_len, 0); if (ret == -1) { goto fail; } -- 2.17.1 From 3325a4d4146d5793b1ae6a7b7a502c52a489ac59 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Aug 2019 12:18:19 +0200 Subject: [PATCH 026/376] tdb: Speed up tdb_oob() This is common between both implementations of tdb_oob(). It's faster if we don't have to dereference function pointers. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 897bffa8166f643eb9063a848bb0c02455663317) --- lib/tdb/common/io.c | 13 ++++++++++++- lib/tdb/common/transaction.c | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c index f3ea7bf9856..28e808143a2 100644 --- a/lib/tdb/common/io.c +++ b/lib/tdb/common/io.c @@ -150,6 +150,11 @@ static int tdb_notrans_oob( return -1; } + /* + * This duplicates functionality from tdb_oob(). Don't remove: + * we still have direct callers of tdb->methods->tdb_oob() + * inside transaction.c. + */ if (off + len <= tdb->map_size) return 0; if (tdb->flags & TDB_INTERNAL) { @@ -664,7 +669,13 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) int tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) { - int ret = tdb->methods->tdb_oob(tdb, off, len, probe); + int ret; + + if (likely((off + len >= off) && (off + len <= tdb->map_size))) { + return 0; + } + + ret = tdb->methods->tdb_oob(tdb, off, len, probe); return ret; } diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c index b22624820d7..4f8d1f8cdcc 100644 --- a/lib/tdb/common/transaction.c +++ b/lib/tdb/common/transaction.c @@ -378,6 +378,11 @@ static void transaction_next_hash_chain(struct tdb_context *tdb, uint32_t *chain static int transaction_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) { + /* + * This duplicates functionality from tdb_oob(). Don't remove: + * we still have direct callers of tdb->methods->tdb_oob() + * inside transaction.c. + */ if (off + len >= off && off + len <= tdb->map_size) { return 0; } -- 2.17.1 From afd6b77bb849bdcfa30513626c61a7aade7d88e2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Aug 2019 18:26:05 +0200 Subject: [PATCH 027/376] tdb: Inline the common part of tdb_oob When you set in tdbtorture.c to make it more similar to locking.tdb use, bin/tdbtorture -m -n 1 -l 100000 -s becomes twice as fast. This is a pretty extreme case, but all other tests that I did improve significantly as well. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit f5735e2c666a5a494131c1d25f7ba5c7fbeae923) --- lib/tdb/common/io.c | 10 ++-------- lib/tdb/common/tdb_private.h | 14 +++++++++++++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c index 28e808143a2..0de0dabd827 100644 --- a/lib/tdb/common/io.c +++ b/lib/tdb/common/io.c @@ -667,15 +667,9 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) return -1; } -int tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) +int _tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) { - int ret; - - if (likely((off + len >= off) && (off + len <= tdb->map_size))) { - return 0; - } - - ret = tdb->methods->tdb_oob(tdb, off, len, probe); + int ret = tdb->methods->tdb_oob(tdb, off, len, probe); return ret; } diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h index 2bed8200f94..29790434211 100644 --- a/lib/tdb/common/tdb_private.h +++ b/lib/tdb/common/tdb_private.h @@ -304,7 +304,19 @@ void *tdb_convert(void *buf, uint32_t size); int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length, struct tdb_record *rec); -int tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe); + +int _tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe); + +static inline int tdb_oob( + struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe) +{ + if (likely((off + len >= off) && (off + len <= tdb->map_size))) { + return 0; + } + return _tdb_oob(tdb, off, len, probe); +} + + int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); -- 2.17.1 From c14427253e8cb4aab951ded527258e6f67fc4452 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 20 Aug 2019 14:55:27 +0200 Subject: [PATCH 028/376] tdb: Release tdb 1.4.2 * Build fixes * Improve the performance by inlining the tdb_oob() checks Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Tue Aug 20 14:45:41 UTC 2019 on sn-devel-184 (cherry picked from commit 60cba7b3a17104da1543d59609f50c6638880dd1) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Aug 21 09:57:08 UTC 2019 on sn-devel-184 --- lib/tdb/ABI/tdb-1.4.2.sigs | 73 ++++++++++++++++++++++++++++++++++++++ lib/tdb/wscript | 2 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 lib/tdb/ABI/tdb-1.4.2.sigs diff --git a/lib/tdb/ABI/tdb-1.4.2.sigs b/lib/tdb/ABI/tdb-1.4.2.sigs new file mode 100644 index 00000000000..e2b0427c347 --- /dev/null +++ b/lib/tdb/ABI/tdb-1.4.2.sigs @@ -0,0 +1,73 @@ +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_jenkins_hash: unsigned int (TDB_DATA *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: dptr = 0xXXXX, dsize = 0 +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_rescue: int (struct tdb_context *, void (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_runtime_check_for_robust_mutexes: bool (void) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_storev: int (struct tdb_context *, TDB_DATA, const TDB_DATA *, int, int) +tdb_summary: char *(struct tdb_context *) +tdb_transaction_active: bool (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_start_nonblock: int (struct tdb_context *) +tdb_transaction_write_lock_mark: int (struct tdb_context *) +tdb_transaction_write_lock_unmark: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_chain: int (struct tdb_context *, unsigned int, tdb_traverse_func, void *) +tdb_traverse_key_chain: int (struct tdb_context *, TDB_DATA, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) diff --git a/lib/tdb/wscript b/lib/tdb/wscript index ece44f82e33..1ab0e8d334a 100644 --- a/lib/tdb/wscript +++ b/lib/tdb/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tdb' -VERSION = '1.4.1' +VERSION = '1.4.2' import sys, os -- 2.17.1 From 521240aa3728d61e8b768c6e5f20146afaf97e2f Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Wed, 21 Aug 2019 12:34:58 +0200 Subject: [PATCH 029/376] VERSION: Disable GIT_SNAPSHOT for the 4.11.0rc2 release. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c70b521219c..12f04435907 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=2 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From ea38596181c8e64f87019d7cfa48b0e0dc225e70 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Wed, 21 Aug 2019 12:36:23 +0200 Subject: [PATCH 030/376] VERSION: Bump version up to 4.11.0rc3... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 12f04435907..67ae2000ebf 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=2 +SAMBA_VERSION_RC_RELEASE=3 ######################################################## # To mark SVN snapshots this should be set to 'yes' # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=2 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 72d79334a53917bd3ee6521bcea2a551906712da Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Fri, 7 Jun 2019 12:55:32 -0700 Subject: [PATCH 031/376] Revert "nfs4acl: Fix owner mapping with ID_TYPE_BOTH" This reverts commit 5d4f7bfda579cecb123cfb1d7130688f1d1c98b7. That patch broke the case with ID_TYPE_BOTH where a file is owned by a group (e.g. using autorid and having a file owned by BUILTIN\Administrators). In this case, the ACE entry for the group gets mapped a to a user ACL entry and the group no longer has access (as in the user's token the group is not mapped to a uid). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 42bd3a72a2525aa8a918f4bf7067b30ce8e0e197) --- source3/modules/nfs4_acls.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 7776caa16d2..6db5a6db6d9 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -723,14 +723,7 @@ static bool smbacl4_fill_ace4( uid_t uid; gid_t gid; - /* - * ID_TYPE_BOTH returns both uid and gid. Explicitly - * check for ownerUID to allow the mapping of the - * owner to a special entry in this idmap config. - */ - if (sid_to_uid(&ace_nt->trustee, &uid) && uid == ownerUID) { - ace_v4->who.uid = uid; - } else if (sid_to_gid(&ace_nt->trustee, &gid)) { + if (sid_to_gid(&ace_nt->trustee, &gid)) { ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; ace_v4->who.gid = gid; } else if (sid_to_uid(&ace_nt->trustee, &uid)) { -- 2.17.1 From 9e82d8ae7fa94228656e9a82d5a7d41d5cb0a4e3 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 11 Jun 2019 16:15:10 -0700 Subject: [PATCH 032/376] nfs4_acls: Remove fsp from smbacl4_win2nfs4 Only the information whether the ACL is for a file or a directory is required. Replacing the fsp with a flag is clearer and allows for unit testing of the mapping functions. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit a06486bb110d04a90b66a0bca4b1b600ef3c0ebf) --- source3/modules/nfs4_acls.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 6db5a6db6d9..5543b3a7f58 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -648,7 +648,7 @@ static SMB_ACE4PROP_T *smbacl4_find_equal_special( static bool smbacl4_fill_ace4( - const struct smb_filename *filename, + bool is_directory, const struct smbacl4_vfs_params *params, uid_t ownerUID, gid_t ownerGID, @@ -670,8 +670,7 @@ static bool smbacl4_fill_ace4( ace_nt->flags); /* remove inheritance flags on files */ - if (VALID_STAT(filename->st) && - !S_ISDIR(filename->st.st_ex_mode)) { + if (!is_directory) { DEBUG(10, ("Removing inheritance flags from a file\n")); ace_v4->aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE| SMB_ACE4_DIRECTORY_INHERIT_ACE| @@ -732,9 +731,8 @@ static bool smbacl4_fill_ace4( &global_sid_Unix_NFS) == 0) { return false; } else { - DEBUG(1, ("nfs4_acls.c: file [%s]: could not " + DEBUG(1, ("nfs4_acls.c: could not " "convert %s to uid or gid\n", - filename->base_name, dom_sid_str_buf(&ace_nt->trustee, &buf))); return false; } @@ -855,7 +853,7 @@ static int smbacl4_substitute_simple( static struct SMB4ACL_T *smbacl4_win2nfs4( TALLOC_CTX *mem_ctx, - const files_struct *fsp, + bool is_directory, const struct security_acl *dacl, const struct smbacl4_vfs_params *pparams, uid_t ownerUID, @@ -864,7 +862,6 @@ static struct SMB4ACL_T *smbacl4_win2nfs4( { struct SMB4ACL_T *theacl; uint32_t i; - const char *filename = fsp->fsp_name->base_name; DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); @@ -876,12 +873,11 @@ static struct SMB4ACL_T *smbacl4_win2nfs4( SMB_ACE4PROP_T ace_v4; bool addNewACE = true; - if (!smbacl4_fill_ace4(fsp->fsp_name, pparams, + if (!smbacl4_fill_ace4(is_directory, pparams, ownerUID, ownerGID, dacl->aces + i, &ace_v4)) { struct dom_sid_buf buf; - DEBUG(3, ("Could not fill ace for file %s, SID %s\n", - filename, + DEBUG(3, ("Could not fill ace for file, SID %s\n", dom_sid_str_buf(&((dacl->aces+i)->trustee), &buf))); continue; @@ -916,7 +912,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, { struct smbacl4_vfs_params params; struct SMB4ACL_T *theacl = NULL; - bool result; + bool result, is_directory; SMB_STRUCT_STAT sbuf; bool set_acl_as_root = false; @@ -951,6 +947,8 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, return map_nt_error_from_unix(errno); } + is_directory = S_ISDIR(sbuf.st_ex_mode); + if (pparams->do_chown) { /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ NTSTATUS status = unpack_nt_owners(fsp->conn, &newUID, &newGID, @@ -998,7 +996,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, return NT_STATUS_OK; } - theacl = smbacl4_win2nfs4(frame, fsp, psd->dacl, pparams, + theacl = smbacl4_win2nfs4(frame, is_directory, psd->dacl, pparams, sbuf.st_ex_uid, sbuf.st_ex_gid); if (!theacl) { TALLOC_FREE(frame); -- 2.17.1 From 88b0461ca0d120d39e10a8765d2f25429ef2faab Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:22:13 -0700 Subject: [PATCH 033/376] selftest: Start implementing unit test for nfs4_acls Existing smbtorture tests set and query ACLs through SMB, only working with the DACLs in the Security Descriptors, but never check the NFSv4 ACL representation. This patch introduces a unit test to verify the mapping between between Security Descriptors and NFSv4 ACLs. As the mapping code queries id mappings, the id mapping cache is first primed with the mappings used by the tests and those mappings are removed again during teardown. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 8fb906a1860452a320c79ac87917a97303729c19) --- source3/modules/test_nfs4_acls.c | 136 +++++++++++++++++++++++++++++++ source3/modules/wscript_build | 5 ++ source3/selftest/tests.py | 4 + 3 files changed, 145 insertions(+) create mode 100644 source3/modules/test_nfs4_acls.c diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c new file mode 100644 index 00000000000..557f27c7428 --- /dev/null +++ b/source3/modules/test_nfs4_acls.c @@ -0,0 +1,136 @@ +/* + * Unix SMB/CIFS implementation. + * + * Unit test for NFS4 ACL handling + * + * Copyright (C) Christof Schmitt 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "nfs4_acls.c" +#include "librpc/gen_ndr/idmap.h" +#include "idmap_cache.h" +#include + +struct test_sids { + const char *sid_str; + struct unixid unix_id; +} test_sids[] = { + { "S-1-5-2-123-456-789-100", { 1000, ID_TYPE_UID }}, + { "S-1-5-2-123-456-789-101", { 1001, ID_TYPE_GID }}, + { "S-1-5-2-123-456-789-102", { 1002, ID_TYPE_BOTH }}, + { SID_CREATOR_OWNER, { 1003, ID_TYPE_UID }}, + { SID_CREATOR_GROUP, { 1004, ID_TYPE_GID }}, + { "S-1-5-2-123-456-789-103", { 1000, ID_TYPE_GID }}, + { "S-1-5-2-123-456-789-104", { 1005, ID_TYPE_BOTH }}, + { "S-1-5-2-123-456-789-105", { 1006, ID_TYPE_BOTH }}, + { "S-1-5-2-123-456-789-106", { 1007, ID_TYPE_BOTH }}, +}; + +static int group_setup(void **state) +{ + struct dom_sid *sids = NULL; + int i; + + sids = talloc_array(NULL, struct dom_sid, ARRAY_SIZE(test_sids)); + assert_non_null(sids); + + for (i = 0; i < ARRAY_SIZE(test_sids); i++) { + assert_true(dom_sid_parse(test_sids[i].sid_str, &sids[i])); + idmap_cache_set_sid2unixid(&sids[i], &test_sids[i].unix_id); + } + + *state = sids; + + return 0; + +} + +static int group_teardown(void **state) +{ + struct dom_sid *sids = *state; + int i; + + for (i = 0; i < ARRAY_SIZE(test_sids); i++) { + assert_true(idmap_cache_del_sid(&sids[i])); + } + + TALLOC_FREE(sids); + *state = NULL; + + return 0; +} + +/* + * Run this as first test to verify that the id mappings used by other + * tests are available in the cache. + */ +static void test_cached_id_mappings(void **state) +{ + struct dom_sid *sids = *state; + int i; + + for (i = 0; i < ARRAY_SIZE(test_sids); i++) { + struct dom_sid *sid = &sids[i]; + struct unixid *unix_id = &test_sids[i].unix_id; + uid_t uid; + gid_t gid; + + switch(unix_id->type) { + case ID_TYPE_UID: + assert_true(sid_to_uid(sid, &uid)); + assert_int_equal(uid, unix_id->id); + assert_false(sid_to_gid(sid, &gid)); + break; + case ID_TYPE_GID: + assert_false(sid_to_uid(sid, &uid)); + assert_true(sid_to_gid(sid, &gid)); + assert_int_equal(gid, unix_id->id); + break; + case ID_TYPE_BOTH: + assert_true(sid_to_uid(sid, &uid)); + assert_int_equal(uid, unix_id->id); + assert_true(sid_to_gid(sid, &gid)); + assert_int_equal(gid, unix_id->id); + break; + default: + fail_msg("Unknown id type %d\n", unix_id->type); + break; + } + } +} + +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_cached_id_mappings), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + if (argc != 2) { + print_error("Usage: %s smb.conf\n", argv[0]); + exit(1); + } + + /* + * Initialize enough of the Samba internals to have the + * mappings tests work. + */ + talloc_stackframe(); + lp_load_global(argv[1]); + + return cmocka_run_group_tests(tests, group_setup, group_teardown); +} diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index 5e0047da917..80b0ce9ff90 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -4,6 +4,11 @@ bld.SAMBA3_SUBSYSTEM('NFS4_ACLS', source='nfs4_acls.c', deps='samba-util tdb') +bld.SAMBA3_BINARY('test_nfs4_acls', + source='test_nfs4_acls.c', + deps='smbd_base cmocka', + install=False) + bld.SAMBA3_SUBSYSTEM('vfs_acl_common', source='vfs_acl_common.c') diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 78f58bdb30c..9569aa9ae00 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -427,6 +427,10 @@ if with_pthreadpool: "script/tests/test_libwbclient_threads.sh"), "$DOMAIN", "$DC_USERNAME"]) +plantestsuite("samba3.test_nfs4_acl", "none", + [os.path.join(bindir(), "test_nfs4_acls"), + "$SMB_CONF_PATH"]) + plantestsuite( "samba3.resolvconf", "none", [os.path.join(samba3srcdir, "script/tests/test_resolvconf.sh")]) -- 2.17.1 From 526da3f215a12dca398ad6c615541e5edb359dae Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:23:40 -0700 Subject: [PATCH 034/376] test_nfs4_acls: Add tests for mapping of empty ACLs This is a fairly simple test that ensures the mapping of empty ACLs (without any ACL entries) is always done the same way. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 00f494b25f4e1d1aecf6191523e30f20a90b1e4f) --- source3/modules/test_nfs4_acls.c | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 557f27c7428..18322afb4a0 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -112,10 +112,63 @@ static void test_cached_id_mappings(void **state) } } +static void test_empty_nfs4_to_dacl(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], false, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 0); + assert_null(dacl_aces); + + TALLOC_FREE(frame); +} + +static void test_empty_dacl_to_nfs4(void **state) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, 0, NULL); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, ¶ms, 1001, 1002); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 0); + assert_null(smb_first_ace4(nfs4_acl)); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_cached_id_mappings), + cmocka_unit_test(test_empty_nfs4_to_dacl), + cmocka_unit_test(test_empty_dacl_to_nfs4), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 4120b8dcbe8e8de5cb4db7e09a8916f4ab4d4493 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:25:33 -0700 Subject: [PATCH 035/376] test_nfs4_acls: Add tests for mapping of ACL types Add testcases for mapping the type field (ALLOW or DENY) between NFSv4 ACLs and security descriptors. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit dd5934797526ebb4c6f3027a809401dad3abf701) --- source3/modules/test_nfs4_acls.c | 107 +++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 18322afb4a0..b29714d23e3 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -163,12 +163,119 @@ static void test_empty_dacl_to_nfs4(void **state) assert_null(smb_first_ace4(nfs4_acl)); } +struct ace_dacl_type_mapping { + uint32_t nfs4_type; + enum security_ace_type dacl_type; +} ace_dacl_type_mapping[] = { + { SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, SEC_ACE_TYPE_ACCESS_ALLOWED }, + { SMB_ACE4_ACCESS_DENIED_ACE_TYPE, SEC_ACE_TYPE_ACCESS_DENIED }, +}; + +static void test_acl_type_nfs4_to_dacl(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(ace_dacl_type_mapping); i++) { + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.uid = 1000, + .aceType = ace_dacl_type_mapping[i].nfs4_type, + .aceFlags = 0, + .aceMask = SMB_ACE4_READ_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[2], &sids[3], false, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 1); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, + ace_dacl_type_mapping[i].dacl_type); + assert_int_equal(dacl_aces[0].flags, 0); + assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); + } + + TALLOC_FREE(frame); +} + +static void test_acl_type_dacl_to_nfs4(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(ace_dacl_type_mapping); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[1]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + init_sec_ace(&dacl_aces[0], &sids[0], + ace_dacl_type_mapping[i].dacl_type, + SEC_FILE_READ_DATA, 0); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, ¶ms, + 101, 102); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, 0); + assert_int_equal(nfs4_ace->aceType, + ace_dacl_type_mapping[i].nfs4_type); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_cached_id_mappings), cmocka_unit_test(test_empty_nfs4_to_dacl), cmocka_unit_test(test_empty_dacl_to_nfs4), + cmocka_unit_test(test_acl_type_nfs4_to_dacl), + cmocka_unit_test(test_acl_type_dacl_to_nfs4), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From c1eb8ec5c3313cebee8dc4ea3643459ced76a2b1 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:28:31 -0700 Subject: [PATCH 036/376] test_nfs4_acls: Add test for flags mapping from NFS4 ACL to DACL Add testcase for the mapping of inheritance flags when mapping from a NFSv4 ACL to a DACL in the security descriptor. The mapping is different between files and directories, as some inheritance flags should never be present for files. Some defined flags like SUCCESSFUL_ACCESS are also not mapped at this point, also verify this behavior. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 16eb61a900c6749c2554d635ce2dd903f5de1704) --- source3/modules/test_nfs4_acls.c | 87 ++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index b29714d23e3..47ae14d0e65 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -268,6 +268,92 @@ static void test_acl_type_dacl_to_nfs4(void **state) TALLOC_FREE(frame); } +struct ace_flag_mapping_nfs4_to_dacl { + bool is_directory; + uint32_t nfs4_flag; + uint32_t dacl_flag; +} ace_flags_nfs4_to_dacl[] = { + { true, SMB_ACE4_FILE_INHERIT_ACE, + SEC_ACE_FLAG_OBJECT_INHERIT }, + { false, SMB_ACE4_FILE_INHERIT_ACE, + 0 }, + { true, SMB_ACE4_DIRECTORY_INHERIT_ACE, + SEC_ACE_FLAG_CONTAINER_INHERIT }, + { false, SMB_ACE4_DIRECTORY_INHERIT_ACE, + 0 }, + { true, SMB_ACE4_NO_PROPAGATE_INHERIT_ACE, + SEC_ACE_FLAG_NO_PROPAGATE_INHERIT }, + { false, SMB_ACE4_NO_PROPAGATE_INHERIT_ACE, + SEC_ACE_FLAG_NO_PROPAGATE_INHERIT }, + { true, SMB_ACE4_INHERIT_ONLY_ACE, + SEC_ACE_FLAG_INHERIT_ONLY }, + { false, SMB_ACE4_INHERIT_ONLY_ACE, + SEC_ACE_FLAG_INHERIT_ONLY }, + { true, SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG, + 0 }, + { false, SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG, + 0 }, + { true, SMB_ACE4_FAILED_ACCESS_ACE_FLAG, + 0 }, + { false, SMB_ACE4_FAILED_ACCESS_ACE_FLAG, + 0 }, + { true, SMB_ACE4_INHERITED_ACE, + SEC_ACE_FLAG_INHERITED_ACE }, + { false, SMB_ACE4_INHERITED_ACE, + SEC_ACE_FLAG_INHERITED_ACE }, +}; + +static void test_ace_flags_nfs4_to_dacl(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + SMB_ACE4PROP_T nfs4_ace; + int i; + + for (i = 0; i < ARRAY_SIZE(ace_flags_nfs4_to_dacl); i++) { + struct SMB4ACL_T *nfs4_acl; + bool is_directory; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.uid = 1000, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = ace_flags_nfs4_to_dacl[i].nfs4_flag, + .aceMask = SMB_ACE4_READ_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + is_directory = ace_flags_nfs4_to_dacl[i].is_directory; + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[2], &sids[3], is_directory, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 1); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, + SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, + ace_flags_nfs4_to_dacl[i].dacl_flag); + assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -276,6 +362,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_empty_dacl_to_nfs4), cmocka_unit_test(test_acl_type_nfs4_to_dacl), cmocka_unit_test(test_acl_type_dacl_to_nfs4), + cmocka_unit_test(test_ace_flags_nfs4_to_dacl), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From ec532e3ed55d94252a23639aad6937118fcf68f1 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:30:12 -0700 Subject: [PATCH 037/376] test_nfs4_acls: Add test for flags mapping from DACL to NFS4 ACL Add testcase for the mapping of inheritance flags from the DACL in the security descriptor to the NFSv4 ACL. The mapping is different for files and directories as some inheritance flags should not be present for files. Also other flags are not mapped at all, verify this behavior. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit bccd2612761e26ee2514935d56927b2c0c000859) --- source3/modules/test_nfs4_acls.c | 87 ++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 47ae14d0e65..a0e7db41b70 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -354,6 +354,92 @@ static void test_ace_flags_nfs4_to_dacl(void **state) TALLOC_FREE(frame); } +struct ace_flag_mapping_dacl_to_nfs4 { + bool is_directory; + uint32_t dacl_flag; + uint32_t nfs4_flag; +} ace_flags_dacl_to_nfs4[] = { + { true, SEC_ACE_FLAG_OBJECT_INHERIT, + SMB_ACE4_FILE_INHERIT_ACE }, + { false, SEC_ACE_FLAG_OBJECT_INHERIT, + 0 }, + { true, SEC_ACE_FLAG_CONTAINER_INHERIT, + SMB_ACE4_DIRECTORY_INHERIT_ACE }, + { false, SEC_ACE_FLAG_CONTAINER_INHERIT, + 0 }, + { true, SEC_ACE_FLAG_NO_PROPAGATE_INHERIT, + SMB_ACE4_NO_PROPAGATE_INHERIT_ACE }, + { false, SEC_ACE_FLAG_NO_PROPAGATE_INHERIT, + 0 }, + { true, SEC_ACE_FLAG_INHERIT_ONLY, + SMB_ACE4_INHERIT_ONLY_ACE }, + { false, SEC_ACE_FLAG_INHERIT_ONLY, + 0 }, + { true, SEC_ACE_FLAG_INHERITED_ACE, + SMB_ACE4_INHERITED_ACE }, + { false, SEC_ACE_FLAG_INHERITED_ACE, + SMB_ACE4_INHERITED_ACE }, + { true, SEC_ACE_FLAG_SUCCESSFUL_ACCESS, + 0 }, + { false, SEC_ACE_FLAG_SUCCESSFUL_ACCESS, + 0 }, + { true, SEC_ACE_FLAG_FAILED_ACCESS, + 0 }, + { false, SEC_ACE_FLAG_FAILED_ACCESS, + 0 }, +}; + +static void test_ace_flags_dacl_to_nfs4(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(ace_flags_dacl_to_nfs4); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + bool is_directory; + struct security_ace dacl_aces[1]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + init_sec_ace(&dacl_aces[0], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + ace_flags_dacl_to_nfs4[i].dacl_flag); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + is_directory = ace_flags_dacl_to_nfs4[i].is_directory; + nfs4_acl = smbacl4_win2nfs4(frame, is_directory, dacl, ¶ms, + 101, 102); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + ace_flags_dacl_to_nfs4[i].nfs4_flag); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -363,6 +449,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_acl_type_nfs4_to_dacl), cmocka_unit_test(test_acl_type_dacl_to_nfs4), cmocka_unit_test(test_ace_flags_nfs4_to_dacl), + cmocka_unit_test(test_ace_flags_dacl_to_nfs4), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 014ae431e64166de6c97660cfbfc6c90c52b532e Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:33:29 -0700 Subject: [PATCH 038/376] test_nfs4_acls: Add test for mapping permissions from NFS4 ACL to DACL Add testcase for mapping permissions from the NFSv4 ACL to DACL in the security descriptor. The mapping is simple as each permission bit exists on both sides. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 1767027b44a9e4ebd865022e3f8abb0c72bf15c6) --- source3/modules/test_nfs4_acls.c | 77 ++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index a0e7db41b70..42a69453f5a 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -440,6 +440,82 @@ static void test_ace_flags_dacl_to_nfs4(void **state) TALLOC_FREE(frame); } +struct ace_perm_mapping { + uint32_t nfs4_perm; + uint32_t dacl_perm; +} perm_table_nfs4_to_dacl[] = { + { SMB_ACE4_READ_DATA, SEC_FILE_READ_DATA }, + { SMB_ACE4_LIST_DIRECTORY, SEC_DIR_LIST }, + { SMB_ACE4_WRITE_DATA, SEC_FILE_WRITE_DATA }, + { SMB_ACE4_ADD_FILE, SEC_DIR_ADD_FILE }, + { SMB_ACE4_APPEND_DATA, SEC_FILE_APPEND_DATA }, + { SMB_ACE4_ADD_SUBDIRECTORY, SEC_DIR_ADD_SUBDIR, }, + { SMB_ACE4_READ_NAMED_ATTRS, SEC_FILE_READ_EA }, + { SMB_ACE4_READ_NAMED_ATTRS, SEC_DIR_READ_EA }, + { SMB_ACE4_WRITE_NAMED_ATTRS, SEC_FILE_WRITE_EA }, + { SMB_ACE4_WRITE_NAMED_ATTRS, SEC_DIR_WRITE_EA }, + { SMB_ACE4_EXECUTE, SEC_FILE_EXECUTE }, + { SMB_ACE4_EXECUTE, SEC_DIR_TRAVERSE }, + { SMB_ACE4_DELETE_CHILD, SEC_DIR_DELETE_CHILD }, + { SMB_ACE4_READ_ATTRIBUTES, SEC_FILE_READ_ATTRIBUTE }, + { SMB_ACE4_READ_ATTRIBUTES, SEC_DIR_READ_ATTRIBUTE }, + { SMB_ACE4_WRITE_ATTRIBUTES, SEC_FILE_WRITE_ATTRIBUTE }, + { SMB_ACE4_WRITE_ATTRIBUTES, SEC_DIR_WRITE_ATTRIBUTE }, + { SMB_ACE4_DELETE, SEC_STD_DELETE }, + { SMB_ACE4_READ_ACL, SEC_STD_READ_CONTROL }, + { SMB_ACE4_WRITE_ACL, SEC_STD_WRITE_DAC, }, + { SMB_ACE4_WRITE_OWNER, SEC_STD_WRITE_OWNER }, + { SMB_ACE4_SYNCHRONIZE, SEC_STD_SYNCHRONIZE }, +}; + +static void test_nfs4_permissions_to_dacl(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(perm_table_nfs4_to_dacl); i++) { + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.uid = 1000, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = perm_table_nfs4_to_dacl[i].nfs4_perm, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], false, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 1); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, + SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, 0); + assert_int_equal(dacl_aces[0].access_mask, + perm_table_nfs4_to_dacl[i].dacl_perm); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -450,6 +526,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_acl_type_dacl_to_nfs4), cmocka_unit_test(test_ace_flags_nfs4_to_dacl), cmocka_unit_test(test_ace_flags_dacl_to_nfs4), + cmocka_unit_test(test_nfs4_permissions_to_dacl), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 368c370dc2f82b03da2e910e1116f5afee064c29 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:35:34 -0700 Subject: [PATCH 039/376] test_nfs4_acls: Add test for mapping permissions from DACL to NFS4 ACL Add testcase for mapping the permission flags from the DACL in the Security Descriptor to a NFSv4 ACL. The mapping is straight-forward as the same permission bits exist for Security Descriptors and NFSv4 ACLs. In addition, the code also maps from the generic DACL permissions to a set of NFSv4 permissions, also verify this mapping. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit e4840e680744bd860beedeb5123704c3c0d6a4d7) --- source3/modules/test_nfs4_acls.c | 106 +++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 42a69453f5a..d77eceb1b88 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -516,6 +516,111 @@ static void test_nfs4_permissions_to_dacl(void **state) TALLOC_FREE(frame); } +struct ace_perm_mapping_dacl_to_nfs4 { + uint32_t dacl_perm; + uint32_t nfs4_perm; +} perm_table_dacl_to_nfs4[] = { + { SEC_FILE_READ_DATA, SMB_ACE4_READ_DATA, }, + { SEC_DIR_LIST, SMB_ACE4_LIST_DIRECTORY, }, + { SEC_FILE_WRITE_DATA, SMB_ACE4_WRITE_DATA, }, + { SEC_DIR_ADD_FILE, SMB_ACE4_ADD_FILE, }, + { SEC_FILE_APPEND_DATA, SMB_ACE4_APPEND_DATA, }, + { SEC_DIR_ADD_SUBDIR, SMB_ACE4_ADD_SUBDIRECTORY, }, + { SEC_FILE_READ_EA, SMB_ACE4_READ_NAMED_ATTRS, }, + { SEC_DIR_READ_EA, SMB_ACE4_READ_NAMED_ATTRS, }, + { SEC_FILE_WRITE_EA, SMB_ACE4_WRITE_NAMED_ATTRS, }, + { SEC_DIR_WRITE_EA, SMB_ACE4_WRITE_NAMED_ATTRS, }, + { SEC_FILE_EXECUTE, SMB_ACE4_EXECUTE, }, + { SEC_DIR_TRAVERSE, SMB_ACE4_EXECUTE, }, + { SEC_DIR_DELETE_CHILD, SMB_ACE4_DELETE_CHILD, }, + { SEC_FILE_READ_ATTRIBUTE, SMB_ACE4_READ_ATTRIBUTES, }, + { SEC_DIR_READ_ATTRIBUTE, SMB_ACE4_READ_ATTRIBUTES, }, + { SEC_FILE_WRITE_ATTRIBUTE, SMB_ACE4_WRITE_ATTRIBUTES, }, + { SEC_DIR_WRITE_ATTRIBUTE, SMB_ACE4_WRITE_ATTRIBUTES, }, + { SEC_STD_DELETE, SMB_ACE4_DELETE, }, + { SEC_STD_READ_CONTROL, SMB_ACE4_READ_ACL, }, + { SEC_STD_WRITE_DAC, SMB_ACE4_WRITE_ACL, }, + { SEC_STD_WRITE_OWNER, SMB_ACE4_WRITE_OWNER, }, + { SEC_STD_SYNCHRONIZE, SMB_ACE4_SYNCHRONIZE, }, + { SEC_GENERIC_READ, SMB_ACE4_READ_ACL| + SMB_ACE4_READ_DATA| + SMB_ACE4_READ_ATTRIBUTES| + SMB_ACE4_READ_NAMED_ATTRS| + SMB_ACE4_SYNCHRONIZE }, + { SEC_GENERIC_WRITE, SMB_ACE4_WRITE_ACL| + SMB_ACE4_WRITE_DATA| + SMB_ACE4_WRITE_ATTRIBUTES| + SMB_ACE4_WRITE_NAMED_ATTRS| + SMB_ACE4_SYNCHRONIZE }, + { SEC_GENERIC_EXECUTE, SMB_ACE4_READ_ACL| + SMB_ACE4_READ_ATTRIBUTES| + SMB_ACE4_EXECUTE| + SMB_ACE4_SYNCHRONIZE }, + { SEC_GENERIC_ALL, SMB_ACE4_DELETE| + SMB_ACE4_READ_ACL| + SMB_ACE4_WRITE_ACL| + SMB_ACE4_WRITE_OWNER| + SMB_ACE4_SYNCHRONIZE| + SMB_ACE4_WRITE_ATTRIBUTES| + SMB_ACE4_READ_ATTRIBUTES| + SMB_ACE4_EXECUTE| + SMB_ACE4_READ_NAMED_ATTRS| + SMB_ACE4_WRITE_NAMED_ATTRS| + SMB_ACE4_WRITE_DATA| + SMB_ACE4_APPEND_DATA| + SMB_ACE4_READ_DATA| + SMB_ACE4_DELETE_CHILD }, +}; + +static void test_dacl_permissions_to_nfs4(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(perm_table_nfs4_to_dacl); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + struct security_ace dacl_aces[1]; + struct security_acl *dacl; + + init_sec_ace(&dacl_aces[0], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, + perm_table_dacl_to_nfs4[i].dacl_perm, 0); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, ¶ms, + 101, 102); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, 0); + assert_int_equal(nfs4_ace->aceMask, + perm_table_dacl_to_nfs4[i].nfs4_perm); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -527,6 +632,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_ace_flags_nfs4_to_dacl), cmocka_unit_test(test_ace_flags_dacl_to_nfs4), cmocka_unit_test(test_nfs4_permissions_to_dacl), + cmocka_unit_test(test_dacl_permissions_to_nfs4), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From dda9e525c55c3602060fffc773e1d31b524ba93f Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:46:23 -0700 Subject: [PATCH 040/376] test_nfs4_acls: Add test for mapping of special NFS4 ACL entries to DACL entries In addition to entries for users and groups, NFSv4 ACLs have the concept of entries for "special" entries. Only the "owner", "group" and "everyone" entries are currently used in the ACL mapping. Add a testcase that verifies the mapping from NFSv4 "special" entries to the DACL in the security descriptor. Verify that only "owner", "group" and "everyone" are mapped and all other "special" entries are ignored. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit f86148948c7f89307a34e31f6ddede6923149d34) --- source3/modules/test_nfs4_acls.c | 139 +++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index d77eceb1b88..5b5b37adc82 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -621,6 +621,144 @@ static void test_dacl_permissions_to_nfs4(void **state) TALLOC_FREE(frame); } +/* + * Create NFS4 ACL with all possible "special" entries. Verify that + * the ones that should be mapped to a DACL are mapped and the other + * ones are ignored. + */ +static void test_special_nfs4_to_dacl(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_OWNER, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_READ_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_GROUP, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_WRITE_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_EVERYONE, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_APPEND_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_INTERACTIVE, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_READ_NAMED_ATTRS, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_NETWORK, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_WRITE_NAMED_ATTRS, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_DIALUP, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_EXECUTE, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_BATCH, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_READ_ATTRIBUTES, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_ANONYMOUS, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_WRITE_ATTRIBUTES, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_AUTHENTICATED, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_READ_ACL, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_SERVICE, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = SMB_ACE4_WRITE_ACL, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], false, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 3); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, 0); + assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); + + assert_int_equal(dacl_aces[1].type, SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[1].flags, 0); + assert_int_equal(dacl_aces[1].access_mask, SEC_FILE_WRITE_DATA); + assert_true(dom_sid_equal(&dacl_aces[1].trustee, &sids[1])); + + assert_int_equal(dacl_aces[2].type, SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[2].flags, 0); + assert_int_equal(dacl_aces[2].access_mask, SEC_FILE_APPEND_DATA); + assert_true(dom_sid_equal(&dacl_aces[2].trustee, &global_sid_World)); + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -633,6 +771,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_ace_flags_dacl_to_nfs4), cmocka_unit_test(test_nfs4_permissions_to_dacl), cmocka_unit_test(test_dacl_permissions_to_nfs4), + cmocka_unit_test(test_special_nfs4_to_dacl), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From aa466a0104d95f0a512c5d740df1c17a06116bd4 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:53:15 -0700 Subject: [PATCH 041/376] test_nfs4_acls: Add test for mapping from DACL to special NFS4 ACL entries Add testcase for mapping from entries in the DACL security descriptor to "special" entries in the NFSv4 ACL. Verify that the WORLD well-known SID maps to "everyone" in the NFSv4 ACL. Verify that the "Unix NFS" SID is ignored, as there is no meaningful mapping for this entry. Verify that SID entries matching the owner or group are mapped to "special owner" or "special group", but only if no inheritance flags are used. "special owner" and "special group" with inheritance flags have the meaning of CREATOR OWNER and CREATOR GROUP and will be tested in another testcase. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 1f1fa5bde2c76636c1beec39c21067b252ea10be) --- source3/modules/test_nfs4_acls.c | 108 +++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 5b5b37adc82..46119f83dc4 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -759,6 +759,113 @@ static void test_special_nfs4_to_dacl(void **state) TALLOC_FREE(frame); } +static void test_dacl_to_special_nfs4(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[6]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_dontcare, + .map_full_control = true, + }; + + /* + * global_Sid_World is mapped to EVERYONE. + */ + init_sec_ace(&dacl_aces[0], &global_sid_World, + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, 0); + /* + * global_sid_Unix_NFS is ignored. + */ + init_sec_ace(&dacl_aces[1], &global_sid_Unix_NFS, + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, 0); + /* + * Anything that maps to owner or owning group with inheritance flags + * is NOT mapped to special owner or special group. + */ + init_sec_ace(&dacl_aces[2], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + init_sec_ace(&dacl_aces[3], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&dacl_aces[4], &sids[1], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + init_sec_ace(&dacl_aces[5], &sids[1], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, 1000, 1001); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 5); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_EVERYONE); + assert_int_equal(nfs4_ace->aceFlags, 0); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_WRITE_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->who.gid, 1001); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE); + assert_int_equal(nfs4_ace->who.gid, 1001); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + assert_null(smb_next_ace4(nfs4_ace_container)); + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -772,6 +879,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_nfs4_permissions_to_dacl), cmocka_unit_test(test_dacl_permissions_to_nfs4), cmocka_unit_test(test_special_nfs4_to_dacl), + cmocka_unit_test(test_dacl_to_special_nfs4), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 4e46dbc7749753b9d6d89ef9aa995cb49e53969a Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:55:59 -0700 Subject: [PATCH 042/376] test_nfs4_acls: Add test for mapping CREATOR entries to NFS4 ACL entries Add testcase for mapping DACL entries CREATOR OWNER and CREATOR GROUP with inheritance flag in the security descriptor to NFSv4 "special owner" and "special group" entries. This is the correct mapping for these entries as inheriting "special owner" and "special group" grants permissions to the actual owner and owning group of the new file or directory, similar to what CREATOR entries do. The other side is that CREATOR entries without any inheritance flags do not make sense, so these are not mapped to NFSv4 ACL entries. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit bfcc19b705f83bdd5cf665fd4daf43e7eae997a9) --- source3/modules/test_nfs4_acls.c | 108 +++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 46119f83dc4..dcdcb89823f 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -866,6 +866,113 @@ static void test_dacl_to_special_nfs4(void **state) TALLOC_FREE(frame); } +struct creator_ace_flags { + uint32_t dacl_flags; + uint32_t nfs4_flags; +} creator_ace_flags[] = { + { 0, 0 }, + + { SEC_ACE_FLAG_INHERIT_ONLY, 0 }, + + { SEC_ACE_FLAG_CONTAINER_INHERIT, SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE }, + + { SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE }, + + { SEC_ACE_FLAG_OBJECT_INHERIT, SMB_ACE4_FILE_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE }, + { SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_FILE_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE }, + + { SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT, SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_FILE_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE }, + + { SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_FILE_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE }, +}; + +static void test_dacl_creator_to_nfs4(void **state) +{ + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(creator_ace_flags); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[2]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + init_sec_ace(&dacl_aces[0], &global_sid_Creator_Owner, + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + creator_ace_flags[i].dacl_flags); + init_sec_ace(&dacl_aces[1], &global_sid_Creator_Group, + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + creator_ace_flags[i].dacl_flags); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, + 101, 102); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + + if (creator_ace_flags[i].nfs4_flags == 0) { + /* + * CREATOR OWNER and CREATOR GROUP not mapped + * in thise case. + */ + assert_null(smb_first_ace4(nfs4_acl)); + } else { + assert_int_equal(smb_get_naces(nfs4_acl), 2); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->who.special_id, + SMB_ACE4_WHO_OWNER); + assert_int_equal(nfs4_ace->aceFlags, + creator_ace_flags[i].nfs4_flags); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->who.special_id, + SMB_ACE4_WHO_GROUP); + assert_int_equal(nfs4_ace->aceFlags, + creator_ace_flags[i].nfs4_flags); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + } + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -880,6 +987,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_dacl_permissions_to_nfs4), cmocka_unit_test(test_special_nfs4_to_dacl), cmocka_unit_test(test_dacl_to_special_nfs4), + cmocka_unit_test(test_dacl_creator_to_nfs4), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 61002278b801a1d5814954c44371e73d0a2eee43 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 11:57:45 -0700 Subject: [PATCH 043/376] test_nfs4_acls: Add test for mapping from NFS4 to DACL CREATOR entries Add testcase for mapping from NFSv4 ACL entries for "special owner" and "special group" to DACL entries in the security descriptor. Each NFSv4 entry here with INHERIT_ONLY maps directly to a CREATOR OWNER or CREATOR GROUP entry in the DACL. Entries without INHERIT_ONLY map to the CREATOR entry and an additional explicit entry granting permission on the current object. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 3c9cda0f6d80258ef0c2a80d6e24dfb650fea1b1) --- source3/modules/test_nfs4_acls.c | 122 +++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index dcdcb89823f..e4e5f1f8b6e 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -973,6 +973,127 @@ static void test_dacl_creator_to_nfs4(void **state) TALLOC_FREE(frame); } +struct creator_owner_nfs4_to_dacl { + uint32_t special_id; + uint32_t nfs4_ace_flags; + uint32_t dacl_ace_flags; +} creator_owner_nfs4_to_dacl[] = { + { SMB_ACE4_WHO_OWNER, + SMB_ACE4_FILE_INHERIT_ACE, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, + { SMB_ACE4_WHO_OWNER, + SMB_ACE4_DIRECTORY_INHERIT_ACE, + SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, + { SMB_ACE4_WHO_OWNER, + SMB_ACE4_FILE_INHERIT_ACE|SMB_ACE4_DIRECTORY_INHERIT_ACE, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY }, + { SMB_ACE4_WHO_GROUP, + SMB_ACE4_FILE_INHERIT_ACE, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, + { SMB_ACE4_WHO_GROUP, + SMB_ACE4_DIRECTORY_INHERIT_ACE, + SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, + { SMB_ACE4_WHO_GROUP, + SMB_ACE4_FILE_INHERIT_ACE|SMB_ACE4_DIRECTORY_INHERIT_ACE, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY }, +}; + +static void test_nfs4_to_dacl_creator(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(creator_owner_nfs4_to_dacl); i++) { + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces, *creator_dacl_ace; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id + = creator_owner_nfs4_to_dacl[i].special_id, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags + = creator_owner_nfs4_to_dacl[i].nfs4_ace_flags, + .aceMask = SMB_ACE4_READ_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], true, + &dacl_aces, &good_aces)); + assert_non_null(dacl_aces); + + if (creator_owner_nfs4_to_dacl[i].nfs4_ace_flags & + SMB_ACE4_INHERIT_ONLY_ACE) { + /* + * Only one ACE entry for the CREATOR ACE entry. + */ + assert_int_equal(good_aces, 1); + creator_dacl_ace = &dacl_aces[0]; + } else { + /* + * This creates an additional ACE entry for + * the permissions on the current object. + */ + assert_int_equal(good_aces, 2); + + assert_int_equal(dacl_aces[0].type, + SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, 0); + assert_int_equal(dacl_aces[0].access_mask, + SEC_FILE_READ_DATA); + + if (creator_owner_nfs4_to_dacl[i].special_id == + SMB_ACE4_WHO_OWNER) { + assert_true(dom_sid_equal(&dacl_aces[0].trustee, + &sids[0])); + } + + if (creator_owner_nfs4_to_dacl[i].special_id == + SMB_ACE4_WHO_GROUP) { + assert_true(dom_sid_equal(&dacl_aces[0].trustee, + &sids[1])); + } + + creator_dacl_ace = &dacl_aces[1]; + } + + assert_int_equal(creator_dacl_ace->type, + SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(creator_dacl_ace->flags, + creator_owner_nfs4_to_dacl[i].dacl_ace_flags); + assert_int_equal(creator_dacl_ace->access_mask, + SEC_FILE_READ_DATA); + if (creator_owner_nfs4_to_dacl[i].special_id == + SMB_ACE4_WHO_OWNER) { + assert_true(dom_sid_equal(&creator_dacl_ace->trustee, + &global_sid_Creator_Owner)); + } + + if (creator_owner_nfs4_to_dacl[i].special_id == + SMB_ACE4_WHO_GROUP) { + assert_true(dom_sid_equal(&creator_dacl_ace->trustee, + &global_sid_Creator_Group)); + } + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -988,6 +1109,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_special_nfs4_to_dacl), cmocka_unit_test(test_dacl_to_special_nfs4), cmocka_unit_test(test_dacl_creator_to_nfs4), + cmocka_unit_test(test_nfs4_to_dacl_creator), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 31d60e8cf2c27e7c05f18b087db5c5aa48075b79 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 12:02:58 -0700 Subject: [PATCH 044/376] test_nfs4_acls: Add test for 'map full control' option "map full control" when enabled adds the DELETE_CHILD permission, when all other permissions are present. This allows Windows clients to display the "FULL CONTROL" permissions. Add a testcase that verifies this mapping when mapping from NFSv4 ACL to the DACL in the security descriptor. Also verify that switching the option off disables this behavior. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 30677df4dac4ebfcf4e3198db33f14be37948197) --- source3/modules/test_nfs4_acls.c | 82 ++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index e4e5f1f8b6e..733217b1f2e 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1094,6 +1094,87 @@ static void test_nfs4_to_dacl_creator(void **state) TALLOC_FREE(frame); } +struct nfs4_to_dacl_map_full_control{ + bool is_dir; + bool config; + bool delete_child_added; +} nfs4_to_dacl_full_control[] = { + { true, true, false }, + { true, false, false }, + { false, true, true }, + { false, false, false }, +}; + +static void test_full_control_nfs4_to_dacl(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(nfs4_to_dacl_full_control); i++) { + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = nfs4_to_dacl_full_control[i].config, + }; + const uint32_t nfs4_ace_mask_except_deletes = + SMB_ACE4_READ_DATA|SMB_ACE4_WRITE_DATA| + SMB_ACE4_APPEND_DATA|SMB_ACE4_READ_NAMED_ATTRS| + SMB_ACE4_WRITE_NAMED_ATTRS|SMB_ACE4_EXECUTE| + SMB_ACE4_READ_ATTRIBUTES|SMB_ACE4_WRITE_ATTRIBUTES| + SMB_ACE4_READ_ACL|SMB_ACE4_WRITE_ACL| + SMB_ACE4_WRITE_OWNER|SMB_ACE4_SYNCHRONIZE; + const uint32_t dacl_ace_mask_except_deletes = + SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA| + SEC_FILE_APPEND_DATA|SEC_FILE_READ_EA| + SEC_FILE_WRITE_EA|SEC_FILE_EXECUTE| + SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE| + SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC| + SEC_STD_WRITE_OWNER|SEC_STD_SYNCHRONIZE; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.uid = 1000, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = 0, + .aceMask = nfs4_ace_mask_except_deletes, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true( + smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], + nfs4_to_dacl_full_control[i].is_dir, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 1); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, + SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, 0); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); + if (nfs4_to_dacl_full_control[i].delete_child_added) { + assert_int_equal(dacl_aces[0].access_mask, + dacl_ace_mask_except_deletes| + SEC_DIR_DELETE_CHILD); + } else { + assert_int_equal(dacl_aces[0].access_mask, + dacl_ace_mask_except_deletes); + } + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1110,6 +1191,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_dacl_to_special_nfs4), cmocka_unit_test(test_dacl_creator_to_nfs4), cmocka_unit_test(test_nfs4_to_dacl_creator), + cmocka_unit_test(test_full_control_nfs4_to_dacl), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 490d13557a4c2bd7046c85080930c0fc9d0d7ee0 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 12:07:36 -0700 Subject: [PATCH 045/376] test_nfs4_acls: Add test for acedup settings The NFSv4 ACL mapping code has a setting nfs4:acedup. Depending on the setting, when mapping from DACLs to NFSv4 ACLs, duplicate ACL entries are either merged, ignored or rejected. Add a testcase that has duplicate ACL entries and verify the expected behavior for all possible settings of the nfs4:acedup option. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 9671bf2b9f055012057620207624aa2f4ea6833e) --- source3/modules/test_nfs4_acls.c | 124 +++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 733217b1f2e..c4f3d8052e4 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1175,6 +1175,129 @@ static void test_full_control_nfs4_to_dacl(void **state) TALLOC_FREE(frame); } +struct acedup_settings { + enum smbacl4_acedup_enum setting; +} acedup_settings[] = { + { e_dontcare }, + { e_reject }, + { e_ignore }, + { e_merge }, +}; + +static void test_dacl_to_nfs4_acedup_settings(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(acedup_settings); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[2]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = acedup_settings[i].setting, + .map_full_control = true, + }; + + init_sec_ace(&dacl_aces[0], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + init_sec_ace(&dacl_aces[1], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, + 101, 102); + + switch(params.acedup) { + case e_dontcare: + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 2); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, + SMB_ACE4_WRITE_DATA); + break; + + case e_reject: + assert_null(nfs4_acl); + assert_int_equal(errno, EINVAL); + break; + + case e_ignore: + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + break; + + case e_merge: + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, + SMB_ACE4_READ_DATA| + SMB_ACE4_WRITE_DATA); + break; + + default: + fail_msg("Unexpected value for acedup: %d\n", + params.acedup); + }; + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1192,6 +1315,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_dacl_creator_to_nfs4), cmocka_unit_test(test_nfs4_to_dacl_creator), cmocka_unit_test(test_full_control_nfs4_to_dacl), + cmocka_unit_test(test_dacl_to_nfs4_acedup_settings), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 4022997f0305ff39db9af2ecb24bd1a2aa9ee0a6 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 12:09:04 -0700 Subject: [PATCH 046/376] test_nfs4_acls: Add test for matching DACL entries for acedup The NFSv4 mapping code has a config option nfs4:acedup for the mapping path from DACLs to NFSv4 ACLs. Part of this codepath is detecting duplicate ACL entries. Add a testcase with different ACL entries and verify that only exactly matching entries are detected as duplicates and treated accordingly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit f55cdf42a14f314102f2e13cb06d4db48c08ad4b) --- source3/modules/test_nfs4_acls.c | 122 +++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index c4f3d8052e4..80078311ce8 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1298,6 +1298,127 @@ static void test_dacl_to_nfs4_acedup_settings(void **state) TALLOC_FREE(frame); } +struct acedup_match { + int sid_idx1; + enum security_ace_type type1; + uint32_t ace_mask1; + uint8_t flag1; + int sid_idx2; + enum security_ace_type type2; + uint32_t ace_mask2; + uint8_t flag2; + bool match; +} acedup_match[] = { + { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + true }, + { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + 1, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + false }, + { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + 0, SEC_ACE_TYPE_ACCESS_DENIED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + false }, + { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + true }, + { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_CONTAINER_INHERIT, + false }, + { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + 5, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT, + false }, +}; + +static void test_dacl_to_nfs4_acedup_match(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + for (i = 0; i < ARRAY_SIZE(acedup_match); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[2]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_ignore, + .map_full_control = true, + }; + + init_sec_ace(&dacl_aces[0], + &sids[acedup_match[i].sid_idx1], + acedup_match[i].type1, + acedup_match[i].ace_mask1, + acedup_match[i].flag1); + init_sec_ace(&dacl_aces[1], + &sids[acedup_match[i].sid_idx2], + acedup_match[i].type2, + acedup_match[i].ace_mask2, + acedup_match[i].flag2); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, + 101, 102); + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + + if (acedup_match[i].match) { + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + } else { + assert_int_equal(smb_get_naces(nfs4_acl), 2); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->who.uid, 1000); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + } + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1316,6 +1437,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_nfs4_to_dacl_creator), cmocka_unit_test(test_full_control_nfs4_to_dacl), cmocka_unit_test(test_dacl_to_nfs4_acedup_settings), + cmocka_unit_test(test_dacl_to_nfs4_acedup_match), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From d3a9648eb63a0624ba2c500ab0a1c477140912ec Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 12:16:08 -0700 Subject: [PATCH 047/376] test_nfs4_acls: Add test for mapping from DACL to NFS4 ACL with config special The mapping code between NFSv4 ACLs and security descriptors still has the deprecated config setting "nfs4:mode = special". This should not be used as it has security problems: All entries matching owner or group are mapped to "special owner" or "special group", which can change its meaning when being inherited to a new file or directory with different owner and owning group. This mode should eventually be removed, but as long as it still exists add testcases to verify the expected behavior. This patch adds the testcase for "nfs4:mode = special" when mapping from the DACL in the security descriptor to the NFSv4 ACL. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 7ae06d96eb59722154d30e21949f9dba4f2f0bc6) --- source3/modules/test_nfs4_acls.c | 119 +++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 80078311ce8..eda2fe56d32 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1419,6 +1419,124 @@ static void test_dacl_to_nfs4_acedup_match(void **state) TALLOC_FREE(frame); } +static void test_dacl_to_nfs4_config_special(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[6]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_special, + .do_chown = true, + .acedup = e_dontcare, + .map_full_control = true, + }; + + /* + * global_sid_Creator_Owner or global_sid_Special_Group is NOT mapped + * to SMB_ACE4_ID_SPECIAL. + */ + init_sec_ace(&dacl_aces[0], &global_sid_Creator_Owner, + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + init_sec_ace(&dacl_aces[1], &global_sid_Creator_Group, + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, + SEC_ACE_FLAG_CONTAINER_INHERIT); + /* + * Anything that maps to owner or owning group with inheritance flags + * IS mapped to special owner or special group. + */ + init_sec_ace(&dacl_aces[2], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + init_sec_ace(&dacl_aces[3], &sids[0], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&dacl_aces[4], &sids[1], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_OBJECT_INHERIT); + init_sec_ace(&dacl_aces[5], &sids[1], + SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, + SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, 1000, 1001); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 6); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->who.uid, 1003); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, 0); + assert_int_equal(nfs4_ace->aceFlags, + SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_DIRECTORY_INHERIT_ACE); + assert_int_equal(nfs4_ace->who.gid, 1004); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_WRITE_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_OWNER); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE); + assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_OWNER); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_FILE_INHERIT_ACE); + assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_GROUP); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); + assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE); + assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_GROUP); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + assert_null(smb_next_ace4(nfs4_ace_container)); + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1438,6 +1556,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_full_control_nfs4_to_dacl), cmocka_unit_test(test_dacl_to_nfs4_acedup_settings), cmocka_unit_test(test_dacl_to_nfs4_acedup_match), + cmocka_unit_test(test_dacl_to_nfs4_config_special), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 2de4919e8a33334cf7c10b9aa407f4c7cff4e53d Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 12:23:02 -0700 Subject: [PATCH 048/376] test_nfs4_acls: Add test for mapping from NFS4 to DACL in config mode special The mapping code between NFSv4 ACLs and security descriptors still has the deprecated config setting "nfs4:mode = special". This should not be used as it has security problems: All entries matching owner or group are mapped to "special owner" or "special group", which can change its meaning when being inherited to a new file or directory with different owner and owning group. This mode should eventually be removed, but as long as it still exists add testcases to verify the expected behavior. This patch adds the testcase for "nfs4:mode = special" when mapping from the NFS4 ACL to the DACL in the security descriptor. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 829c5ea99685c0629fd67ed0528897534ff35b36) --- source3/modules/test_nfs4_acls.c | 63 ++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index eda2fe56d32..341bf179ea9 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1537,6 +1537,68 @@ static void test_dacl_to_nfs4_config_special(void **state) TALLOC_FREE(frame); } +static void test_nfs4_to_dacl_config_special(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_special, + .do_chown = true, + .acedup = e_dontcare, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + /* + * In config mode special, this is not mapped to Creator Owner + */ + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_OWNER, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = SMB_ACE4_FILE_INHERIT_ACE, + .aceMask = SMB_ACE4_READ_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + /* + * In config mode special, this is not mapped to Creator Group + */ + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = SMB_ACE4_ID_SPECIAL, + .who.special_id = SMB_ACE4_WHO_GROUP, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = SMB_ACE4_DIRECTORY_INHERIT_ACE, + .aceMask = SMB_ACE4_WRITE_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], true, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 2); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, SEC_ACE_FLAG_OBJECT_INHERIT); + assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); + + assert_int_equal(dacl_aces[1].type, SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[1].flags, SEC_ACE_FLAG_CONTAINER_INHERIT); + assert_int_equal(dacl_aces[1].access_mask, SEC_FILE_WRITE_DATA); + assert_true(dom_sid_equal(&dacl_aces[1].trustee, &sids[1])); + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1557,6 +1619,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_dacl_to_nfs4_acedup_settings), cmocka_unit_test(test_dacl_to_nfs4_acedup_match), cmocka_unit_test(test_dacl_to_nfs4_config_special), + cmocka_unit_test(test_nfs4_to_dacl_config_special), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 7d73c37ae7bbc102dab469f5709b1a54de7a0a74 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 12:50:42 -0700 Subject: [PATCH 049/376] test_nfs4_acls: Add test for mapping from NFS4 ACL to DACL with IDMAP_TYPE_BOTH When id mappings use IDMAP_TYPE_BOTH, the NFSv4 ACL mapping code is not aware whether a particular entry is for a user or a group. The underlying assumption then is that is should not matter, as both the ACL mapping maps everything to NFSv4 ACL group entries and the user's token will contain gid entries for the groups. Add a testcase to verify that when mapping from NFSv4 ACL entries to DACLs with IDMAP_TYPE_BOTH, all entries are mapped as expected. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 86480410aec1d2331c65826a13f909492165a291) --- source3/modules/test_nfs4_acls.c | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 341bf179ea9..964af4ff057 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1599,6 +1599,72 @@ static void test_nfs4_to_dacl_config_special(void **state) TALLOC_FREE(frame); } +struct nfs_to_dacl_idmap_both { + uint32_t nfs4_flags; + uint32_t nfs4_id; + struct dom_sid *sid; +}; + +static void test_nfs4_to_dacl_idmap_type_both(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + struct nfs_to_dacl_idmap_both nfs_to_dacl_idmap_both[] = { + { 0, 1002, &sids[2] }, + { SMB_ACE4_IDENTIFIER_GROUP, 1002, &sids[2] }, + { 0, 1005, &sids[6] }, + { SMB_ACE4_IDENTIFIER_GROUP, 1005, &sids[6] }, + }; + + for (i = 0; i < ARRAY_SIZE(nfs_to_dacl_idmap_both); i++) { + struct SMB4ACL_T *nfs4_acl; + struct security_ace *dacl_aces; + SMB_ACE4PROP_T nfs4_ace; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = nfs_to_dacl_idmap_both[i].nfs4_flags, + .aceMask = SMB_ACE4_READ_DATA, + }; + + if (nfs_to_dacl_idmap_both[i].nfs4_flags & + SMB_ACE4_IDENTIFIER_GROUP) { + nfs4_ace.who.gid = nfs_to_dacl_idmap_both[i].nfs4_id; + } else { + nfs4_ace.who.uid = nfs_to_dacl_idmap_both[i].nfs4_id; + } + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[2], &sids[2], + false, &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 1); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, + SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, 0); + assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, + nfs_to_dacl_idmap_both[i].sid)); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1620,6 +1686,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_dacl_to_nfs4_acedup_match), cmocka_unit_test(test_dacl_to_nfs4_config_special), cmocka_unit_test(test_nfs4_to_dacl_config_special), + cmocka_unit_test(test_nfs4_to_dacl_idmap_type_both), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 0313f1552f9665ed485aa2c7224f491be8511eff Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 13:04:44 -0700 Subject: [PATCH 050/376] test_nfs4_acls: Add test for mapping from DACL to NFS4 ACL with IDMAP_TYPE_BOTH When id mappings use IDMAP_TYPE_BOTH, the NFSv4 ACL mapping code is not aware whether a particular entry is for a user or a group. The underlying assumption then is that is should not matter, as both the ACL mapping maps everything to NFSv4 ACL group entries and the user's token will contain gid entries for the groups. Add a testcase to verify that when mapping from DACLS to NFSv4 ACL entries with IDMAP_TYPE_BOTH, all entries are mapped as expected. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 38331b00521ef764893a74add01758f14567d901) --- source3/modules/test_nfs4_acls.c | 85 ++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 964af4ff057..d7152a0737a 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1665,6 +1665,90 @@ static void test_nfs4_to_dacl_idmap_type_both(void **state) TALLOC_FREE(frame); } +struct dacl_to_nfs4_idmap_both { + struct dom_sid *sid; + uint32_t dacl_flags; + uint32_t nfs4_flags; + uint32_t nfs4_ace_flags; + uint32_t nfs4_id; +}; + +/* + * IDMAP_TYPE_BOTH always creates group entries. + */ +static void test_dacl_to_nfs4_idmap_type_both(void **state) +{ + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + int i; + + struct dacl_to_nfs4_idmap_both dacl_to_nfs4_idmap_both[] = { + { &sids[2], 0, + SMB_ACE4_ID_SPECIAL, SMB_ACE4_IDENTIFIER_GROUP, SMB_ACE4_WHO_GROUP }, + { &sids[2], SEC_ACE_FLAG_OBJECT_INHERIT, + 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1002 }, + { &sids[6], 0, + 0, SMB_ACE4_IDENTIFIER_GROUP, 1005 }, + { &sids[6], SEC_ACE_FLAG_OBJECT_INHERIT, + 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1005 }, + }; + + for (i = 0; i < ARRAY_SIZE(dacl_to_nfs4_idmap_both); i++) { + struct SMB4ACL_T *nfs4_acl; + struct SMB4ACE_T *nfs4_ace_container; + SMB_ACE4PROP_T *nfs4_ace; + struct security_ace dacl_aces[1]; + struct security_acl *dacl; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_merge, + .map_full_control = true, + }; + + init_sec_ace(&dacl_aces[0], dacl_to_nfs4_idmap_both[i].sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_FILE_READ_DATA, + dacl_to_nfs4_idmap_both[i].dacl_flags); + dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, + ARRAY_SIZE(dacl_aces), dacl_aces); + assert_non_null(dacl); + + nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, + 1002, 1002); + + assert_non_null(nfs4_acl); + assert_int_equal(smbacl4_get_controlflags(nfs4_acl), + SEC_DESC_SELF_RELATIVE); + assert_int_equal(smb_get_naces(nfs4_acl), 1); + + nfs4_ace_container = smb_first_ace4(nfs4_acl); + assert_non_null(nfs4_ace_container); + assert_null(smb_next_ace4(nfs4_ace_container)); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, + dacl_to_nfs4_idmap_both[i].nfs4_flags); + assert_int_equal(nfs4_ace->aceFlags, + dacl_to_nfs4_idmap_both[i].nfs4_ace_flags); + if (nfs4_ace->flags & SMB_ACE4_ID_SPECIAL) { + assert_int_equal(nfs4_ace->who.special_id, + dacl_to_nfs4_idmap_both[i].nfs4_id); + } else if (nfs4_ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { + assert_int_equal(nfs4_ace->who.gid, + dacl_to_nfs4_idmap_both[i].nfs4_id); + } else { + assert_int_equal(nfs4_ace->who.uid, + dacl_to_nfs4_idmap_both[i].nfs4_id); + } + assert_int_equal(nfs4_ace->aceType, + SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + } + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1687,6 +1771,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_dacl_to_nfs4_config_special), cmocka_unit_test(test_nfs4_to_dacl_config_special), cmocka_unit_test(test_nfs4_to_dacl_idmap_type_both), + cmocka_unit_test(test_dacl_to_nfs4_idmap_type_both), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From 6d88ab39e8ed469a9279870d88b28c568ce3a687 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 26 Jun 2019 13:24:16 -0700 Subject: [PATCH 051/376] nfs4_acls: Use sids_to_unixids to lookup uid or gid This is the newer API to lookup id mappings and will make it easier to add to the IDMAP_TYPE_BOTH case. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit d9a2ff559e1ad953141b1118a9e370496f1f61fa) --- source3/modules/nfs4_acls.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 5543b3a7f58..4069c9310ed 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -21,6 +21,7 @@ #include "smbd/smbd.h" #include "nfs4_acls.h" #include "librpc/gen_ndr/ndr_security.h" +#include "librpc/gen_ndr/idmap.h" #include "../libcli/security/dom_sid.h" #include "../libcli/security/security.h" #include "dbwrap/dbwrap.h" @@ -719,14 +720,21 @@ static bool smbacl4_fill_ace4( return false; } } else { - uid_t uid; - gid_t gid; + struct unixid unixid; + bool ok; - if (sid_to_gid(&ace_nt->trustee, &gid)) { + ok = sids_to_unixids(&ace_nt->trustee, 1, &unixid); + if (!ok) { + DBG_WARNING("Could not convert %s to uid or gid.\n", + dom_sid_str_buf(&ace_nt->trustee, &buf)); + return false; + } + + if (unixid.type == ID_TYPE_GID || unixid.type == ID_TYPE_BOTH) { ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; - ace_v4->who.gid = gid; - } else if (sid_to_uid(&ace_nt->trustee, &uid)) { - ace_v4->who.uid = uid; + ace_v4->who.gid = unixid.id; + } else if (unixid.type == ID_TYPE_UID) { + ace_v4->who.uid = unixid.id; } else if (dom_sid_compare_domain(&ace_nt->trustee, &global_sid_Unix_NFS) == 0) { return false; -- 2.17.1 From b1b8e37881f5583f5b7770c46a8db4162e614884 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 15 Jul 2019 13:15:32 -0700 Subject: [PATCH 052/376] nfs4_acls: Use switch/case for checking idmap type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit f198a0867e71f248d4887ab0b6f2832123b16d11) --- source3/modules/nfs4_acls.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 4069c9310ed..f8861e9058b 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -730,18 +730,27 @@ static bool smbacl4_fill_ace4( return false; } - if (unixid.type == ID_TYPE_GID || unixid.type == ID_TYPE_BOTH) { + if (dom_sid_compare_domain(&ace_nt->trustee, + &global_sid_Unix_NFS) == 0) { + return false; + } + + switch (unixid.type) { + case ID_TYPE_BOTH: ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; ace_v4->who.gid = unixid.id; - } else if (unixid.type == ID_TYPE_UID) { + break; + case ID_TYPE_GID: + ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; + ace_v4->who.gid = unixid.id; + break; + case ID_TYPE_UID: ace_v4->who.uid = unixid.id; - } else if (dom_sid_compare_domain(&ace_nt->trustee, - &global_sid_Unix_NFS) == 0) { - return false; - } else { - DEBUG(1, ("nfs4_acls.c: could not " - "convert %s to uid or gid\n", - dom_sid_str_buf(&ace_nt->trustee, &buf))); + break; + case ID_TYPE_NOT_SPECIFIED: + default: + DBG_WARNING("Could not convert %s to uid or gid.\n", + dom_sid_str_buf(&ace_nt->trustee, &buf)); return false; } } -- 2.17.1 From e08f9b24097f8b5d08dcca3ee98017b114fcea99 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 25 Jun 2019 15:21:06 -0700 Subject: [PATCH 053/376] nfs4_acls: Use correct type when checking ownerGID uid and gid are members of the same union so this makes no difference, but for type correctness and readability use the gid to check for ownerGID. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 3b3d722ce579c19c7b08d06a3adea275537545dc) --- source3/modules/nfs4_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index f8861e9058b..b2ba4d1d701 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -856,7 +856,7 @@ static int smbacl4_substitute_simple( if (!(ace->flags & SMB_ACE4_ID_SPECIAL) && ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP && - ace->who.uid == ownerGID && + ace->who.gid == ownerGID && !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) && !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) && !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) { -- 2.17.1 From 6661fecf2676fc0ff30a86a2332be95fa76f89ed Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 26 Jun 2019 13:20:17 -0700 Subject: [PATCH 054/376] nfs4_acls: Add helper function for checking INHERIT flags. This avoids some code duplication. Do not make this static, as it will be used in a later patch. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmit Reviewed-by: Ralph Boehme (cherry picked from commit 336e8668c1cc3682cb3c198eb6dc49baf522a79a) --- source3/modules/nfs4_acls.c | 15 +++++++++------ source3/modules/nfs4_acls.h | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index b2ba4d1d701..bab73a5cb58 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -255,6 +255,13 @@ bool smbacl4_set_controlflags(struct SMB4ACL_T *acl, uint16_t controlflags) return true; } +bool nfs_ace_is_inherit(SMB_ACE4PROP_T *ace) +{ + return ace->aceFlags & (SMB_ACE4_INHERIT_ONLY_ACE| + SMB_ACE4_FILE_INHERIT_ACE| + SMB_ACE4_DIRECTORY_INHERIT_ACE); +} + static int smbacl4_GetFileOwner(struct connection_struct *conn, const struct smb_filename *smb_fname, SMB_STRUCT_STAT *psbuf) @@ -846,9 +853,7 @@ static int smbacl4_substitute_simple( if (!(ace->flags & SMB_ACE4_ID_SPECIAL) && !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) && ace->who.uid == ownerUID && - !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) && - !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) && - !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) { + !nfs_ace_is_inherit(ace)) { ace->flags |= SMB_ACE4_ID_SPECIAL; ace->who.special_id = SMB_ACE4_WHO_OWNER; DEBUG(10,("replaced with special owner ace\n")); @@ -857,9 +862,7 @@ static int smbacl4_substitute_simple( if (!(ace->flags & SMB_ACE4_ID_SPECIAL) && ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP && ace->who.gid == ownerGID && - !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) && - !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) && - !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) { + !nfs_ace_is_inherit(ace)) { ace->flags |= SMB_ACE4_ID_SPECIAL; ace->who.special_id = SMB_ACE4_WHO_GROUP; DEBUG(10,("replaced with special group ace\n")); diff --git a/source3/modules/nfs4_acls.h b/source3/modules/nfs4_acls.h index a73b3154f0f..d0cf2d0f1fb 100644 --- a/source3/modules/nfs4_acls.h +++ b/source3/modules/nfs4_acls.h @@ -143,6 +143,8 @@ uint16_t smbacl4_get_controlflags(struct SMB4ACL_T *theacl); bool smbacl4_set_controlflags(struct SMB4ACL_T *theacl, uint16_t controlflags); +bool nfs_ace_is_inherit(SMB_ACE4PROP_T *ace); + NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp, const struct smbacl4_vfs_params *pparams, uint32_t security_info, -- 2.17.1 From d5965e3a43f097a04d6ef14467f31b0c1d05a3b9 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 13:20:44 -0700 Subject: [PATCH 055/376] nfs4_acls: Add missing braces in smbacl4_win2nfs4 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit ba73d2363d93a376ba4947963c9de45a7e683f02) --- source3/modules/nfs4_acls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index bab73a5cb58..11cb80e9300 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -905,12 +905,14 @@ static struct SMB4ACL_T *smbacl4_win2nfs4( if (pparams->acedup!=e_dontcare) { if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl, - &ace_v4, &addNewACE, i)) + &ace_v4, &addNewACE, i)) { return NULL; + } } - if (addNewACE) + if (addNewACE) { smb_add_ace4(theacl, &ace_v4); + } } if (pparams->mode==e_simple) { -- 2.17.1 From 428579d3fde2241a6280fae704dfda030397ff9c Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 15 Jul 2019 14:43:01 -0700 Subject: [PATCH 056/376] nfs4_acls: Remove i argument from smbacl4_MergeIgnoreReject This is only used for logging of a rejected ACL, but does not provide additional useful information. Remove it to simplify the function a bit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 44790721e4f2c6ee6f46de7ac88123ce1a9f6e39) --- source3/modules/nfs4_acls.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 11cb80e9300..2317e0bc8b1 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -765,13 +765,10 @@ static bool smbacl4_fill_ace4( return true; /* OK */ } -static int smbacl4_MergeIgnoreReject( - enum smbacl4_acedup_enum acedup, - struct SMB4ACL_T *theacl, /* may modify it */ - SMB_ACE4PROP_T *ace, /* the "new" ACE */ - bool *paddNewACE, - int i -) +static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup, + struct SMB4ACL_T *theacl, + SMB_ACE4PROP_T *ace, + bool *paddNewACE) { int result = 0; SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace); @@ -788,7 +785,7 @@ static int smbacl4_MergeIgnoreReject( *paddNewACE = false; break; case e_reject: /* do an error */ - DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i)); + DBG_INFO("ACL rejected by duplicate nt ace.\n"); errno = EINVAL; /* SHOULD be set on any _real_ error */ result = -1; break; @@ -905,7 +902,7 @@ static struct SMB4ACL_T *smbacl4_win2nfs4( if (pparams->acedup!=e_dontcare) { if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl, - &ace_v4, &addNewACE, i)) { + &ace_v4, &addNewACE)) { return NULL; } } -- 2.17.1 From d806dba002c7ebe50e6b74fe2d43daadd0bbf05f Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 16 Jul 2019 15:20:25 -0700 Subject: [PATCH 057/376] nfs4_acls: Move smbacl4_MergeIgnoreReject function This static function will be called earlier in later patches. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 3499d97463110f042415d917160bc2743805a544) --- source3/modules/nfs4_acls.c | 61 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 2317e0bc8b1..cb407c6e032 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -654,6 +654,36 @@ static SMB_ACE4PROP_T *smbacl4_find_equal_special( return NULL; } +static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup, + struct SMB4ACL_T *theacl, + SMB_ACE4PROP_T *ace, + bool *paddNewACE) +{ + int result = 0; + SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace); + if (ace4found) + { + switch(acedup) + { + case e_merge: /* "merge" flags */ + *paddNewACE = false; + ace4found->aceFlags |= ace->aceFlags; + ace4found->aceMask |= ace->aceMask; + break; + case e_ignore: /* leave out this record */ + *paddNewACE = false; + break; + case e_reject: /* do an error */ + DBG_INFO("ACL rejected by duplicate nt ace.\n"); + errno = EINVAL; /* SHOULD be set on any _real_ error */ + result = -1; + break; + default: + break; + } + } + return result; +} static bool smbacl4_fill_ace4( bool is_directory, @@ -765,37 +795,6 @@ static bool smbacl4_fill_ace4( return true; /* OK */ } -static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup, - struct SMB4ACL_T *theacl, - SMB_ACE4PROP_T *ace, - bool *paddNewACE) -{ - int result = 0; - SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace); - if (ace4found) - { - switch(acedup) - { - case e_merge: /* "merge" flags */ - *paddNewACE = false; - ace4found->aceFlags |= ace->aceFlags; - ace4found->aceMask |= ace->aceMask; - break; - case e_ignore: /* leave out this record */ - *paddNewACE = false; - break; - case e_reject: /* do an error */ - DBG_INFO("ACL rejected by duplicate nt ace.\n"); - errno = EINVAL; /* SHOULD be set on any _real_ error */ - result = -1; - break; - default: - break; - } - } - return result; -} - static int smbacl4_substitute_special( struct SMB4ACL_T *acl, uid_t ownerUID, -- 2.17.1 From 693aa2dbfc84631be913a364dad57a12dae3c5ba Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 16 Jul 2019 15:30:36 -0700 Subject: [PATCH 058/376] nfs4_acls: Move adding of NFS4 ACE to ACL to smbacl4_fill_ace4 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit abb58b17599bd3f9a06037e208dcc5033c7fdd8b) --- source3/modules/nfs4_acls.c | 68 +++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index cb407c6e032..bab4dd0fd64 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -685,16 +685,41 @@ static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup, return result; } -static bool smbacl4_fill_ace4( +static int nfs4_acl_add_ace(enum smbacl4_acedup_enum acedup, + struct SMB4ACL_T *nfs4_acl, + SMB_ACE4PROP_T *nfs4_ace) +{ + bool add_ace = true; + + if (acedup != e_dontcare) { + int ret; + + ret = smbacl4_MergeIgnoreReject(acedup, nfs4_acl, + nfs4_ace, &add_ace); + if (ret == -1) { + return -1; + } + } + + if (add_ace) { + smb_add_ace4(nfs4_acl, nfs4_ace); + } + + return 0; +} + +static int smbacl4_fill_ace4( bool is_directory, const struct smbacl4_vfs_params *params, uid_t ownerUID, gid_t ownerGID, const struct security_ace *ace_nt, /* input */ - SMB_ACE4PROP_T *ace_v4 /* output */ + struct SMB4ACL_T *nfs4_acl ) { struct dom_sid_buf buf; + SMB_ACE4PROP_T nfs4_ace = { 0 }; + SMB_ACE4PROP_T *ace_v4 = &nfs4_ace; DEBUG(10, ("got ace for %s\n", dom_sid_str_buf(&ace_nt->trustee, &buf))); @@ -742,7 +767,7 @@ static bool smbacl4_fill_ace4( ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { - return false; + return 0; } } else if (params->mode!=e_special && dom_sid_equal(&ace_nt->trustee, @@ -754,7 +779,7 @@ static bool smbacl4_fill_ace4( ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { - return false; + return 0; } } else { struct unixid unixid; @@ -764,12 +789,12 @@ static bool smbacl4_fill_ace4( if (!ok) { DBG_WARNING("Could not convert %s to uid or gid.\n", dom_sid_str_buf(&ace_nt->trustee, &buf)); - return false; + return 0; } if (dom_sid_compare_domain(&ace_nt->trustee, &global_sid_Unix_NFS) == 0) { - return false; + return 0; } switch (unixid.type) { @@ -788,11 +813,11 @@ static bool smbacl4_fill_ace4( default: DBG_WARNING("Could not convert %s to uid or gid.\n", dom_sid_str_buf(&ace_nt->trustee, &buf)); - return false; + return 0; } } - return true; /* OK */ + return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace); } static int smbacl4_substitute_special( @@ -886,28 +911,13 @@ static struct SMB4ACL_T *smbacl4_win2nfs4( return NULL; for(i=0; inum_aces; i++) { - SMB_ACE4PROP_T ace_v4; - bool addNewACE = true; - - if (!smbacl4_fill_ace4(is_directory, pparams, - ownerUID, ownerGID, - dacl->aces + i, &ace_v4)) { - struct dom_sid_buf buf; - DEBUG(3, ("Could not fill ace for file, SID %s\n", - dom_sid_str_buf(&((dacl->aces+i)->trustee), - &buf))); - continue; - } - - if (pparams->acedup!=e_dontcare) { - if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl, - &ace_v4, &addNewACE)) { - return NULL; - } - } + int ret; - if (addNewACE) { - smb_add_ace4(theacl, &ace_v4); + ret = smbacl4_fill_ace4(is_directory, pparams, + ownerUID, ownerGID, + dacl->aces + i, theacl); + if (ret == -1) { + return NULL; } } -- 2.17.1 From b3aad3426a87d41e0fc51129a9ef2d22a4e86ab3 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 16 Jul 2019 15:50:36 -0700 Subject: [PATCH 059/376] nfs4_acls: Remove redundant logging from smbacl4_fill_ace4 Logging flags in case they do not match seems unnecessary. Other log messages should show the flags as well. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 7ab0003ffc098247c3ee3962d7061f2af5a2d00e) --- source3/modules/nfs4_acls.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index bab4dd0fd64..25bcc770095 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -746,14 +746,6 @@ static int smbacl4_fill_ace4( se_map_generic(&ace_v4->aceMask, &file_generic_mapping); - if (ace_v4->aceFlags!=ace_nt->flags) - DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", - ace_v4->aceFlags, ace_nt->flags)); - - if (ace_v4->aceMask!=ace_nt->access_mask) - DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n", - ace_v4->aceMask, ace_nt->access_mask)); - if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) { ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; ace_v4->flags |= SMB_ACE4_ID_SPECIAL; -- 2.17.1 From 01e913caf03078b06592f6b66b737223896b4385 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 16 Jul 2019 15:56:12 -0700 Subject: [PATCH 060/376] nfs4_acls: Remove redundant pointer variable The previous patch introduced a pointer to a local variable to reduce the amount of lines changed. Remove that pointer and adjust all usage accordingly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit aa4644193635d846c2e08e8c1e7b512e8009c2ef) --- source3/modules/nfs4_acls.c | 56 +++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 25bcc770095..d169377295a 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -719,58 +719,54 @@ static int smbacl4_fill_ace4( { struct dom_sid_buf buf; SMB_ACE4PROP_T nfs4_ace = { 0 }; - SMB_ACE4PROP_T *ace_v4 = &nfs4_ace; DEBUG(10, ("got ace for %s\n", dom_sid_str_buf(&ace_nt->trustee, &buf))); - ZERO_STRUCTP(ace_v4); - /* only ACCESS|DENY supported right now */ - ace_v4->aceType = ace_nt->type; + nfs4_ace.aceType = ace_nt->type; - ace_v4->aceFlags = map_windows_ace_flags_to_nfs4_ace_flags( - ace_nt->flags); + nfs4_ace.aceFlags = + map_windows_ace_flags_to_nfs4_ace_flags(ace_nt->flags); /* remove inheritance flags on files */ if (!is_directory) { DEBUG(10, ("Removing inheritance flags from a file\n")); - ace_v4->aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE| - SMB_ACE4_DIRECTORY_INHERIT_ACE| - SMB_ACE4_NO_PROPAGATE_INHERIT_ACE| - SMB_ACE4_INHERIT_ONLY_ACE); + nfs4_ace.aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE| + SMB_ACE4_DIRECTORY_INHERIT_ACE| + SMB_ACE4_NO_PROPAGATE_INHERIT_ACE| + SMB_ACE4_INHERIT_ONLY_ACE); } - ace_v4->aceMask = ace_nt->access_mask & - (SEC_STD_ALL | SEC_FILE_ALL); + nfs4_ace.aceMask = ace_nt->access_mask & (SEC_STD_ALL | SEC_FILE_ALL); - se_map_generic(&ace_v4->aceMask, &file_generic_mapping); + se_map_generic(&nfs4_ace.aceMask, &file_generic_mapping); if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) { - ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + nfs4_ace.who.special_id = SMB_ACE4_WHO_EVERYONE; + nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL; } else if (params->mode!=e_special && dom_sid_equal(&ace_nt->trustee, &global_sid_Creator_Owner)) { DEBUG(10, ("Map creator owner\n")); - ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + nfs4_ace.who.special_id = SMB_ACE4_WHO_OWNER; + nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL; /* A non inheriting creator owner entry has no effect. */ - ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; - if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) - && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { + nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; + if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) + && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { return 0; } } else if (params->mode!=e_special && dom_sid_equal(&ace_nt->trustee, &global_sid_Creator_Group)) { DEBUG(10, ("Map creator owner group\n")); - ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + nfs4_ace.who.special_id = SMB_ACE4_WHO_GROUP; + nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL; /* A non inheriting creator group entry has no effect. */ - ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; - if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) - && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { + nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; + if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) + && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { return 0; } } else { @@ -791,15 +787,15 @@ static int smbacl4_fill_ace4( switch (unixid.type) { case ID_TYPE_BOTH: - ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; - ace_v4->who.gid = unixid.id; + nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; + nfs4_ace.who.gid = unixid.id; break; case ID_TYPE_GID: - ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; - ace_v4->who.gid = unixid.id; + nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; + nfs4_ace.who.gid = unixid.id; break; case ID_TYPE_UID: - ace_v4->who.uid = unixid.id; + nfs4_ace.who.uid = unixid.id; break; case ID_TYPE_NOT_SPECIFIED: default: -- 2.17.1 From 8ac9c1f75f3f01370c9dba5d570f95c48e2029b4 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 17 Jul 2019 10:49:47 -0700 Subject: [PATCH 061/376] nfs4_acls: Add additional owner entry when mapping to NFS4 ACL with IDMAP_TYPE_BOTH With IDMAP_TYPE_BOTH, all entries have to be mapped to group entries. In order to have the file system reflect the owner permissions in the POSIX modebits, create a second entry for the user. This will be mapped to the "special owner" entry. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit b796119e2df38d1935064556934dd10da6f3d339) --- source3/modules/nfs4_acls.c | 37 +++++++++++++++++++++++++++++- source3/modules/test_nfs4_acls.c | 39 +++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index d169377295a..70d725eb937 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -719,6 +719,9 @@ static int smbacl4_fill_ace4( { struct dom_sid_buf buf; SMB_ACE4PROP_T nfs4_ace = { 0 }; + SMB_ACE4PROP_T nfs4_ace_2 = { 0 }; + bool add_ace2 = false; + int ret; DEBUG(10, ("got ace for %s\n", dom_sid_str_buf(&ace_nt->trustee, &buf))); @@ -789,6 +792,29 @@ static int smbacl4_fill_ace4( case ID_TYPE_BOTH: nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; nfs4_ace.who.gid = unixid.id; + + if (ownerUID == unixid.id && + !nfs_ace_is_inherit(&nfs4_ace)) + { + /* + * IDMAP_TYPE_BOTH for owner. Add + * additional user entry, which can be + * mapped to special:owner to reflect + * the permissions in the modebits. + * + * This only applies to non-inheriting + * entries as only these are replaced + * with SPECIAL_OWNER in nfs4:mode=simple. + */ + nfs4_ace_2 = (SMB_ACE4PROP_T) { + .who.uid = unixid.id, + .aceFlags = (nfs4_ace.aceFlags & + ~SMB_ACE4_IDENTIFIER_GROUP), + .aceMask = nfs4_ace.aceMask, + .aceType = nfs4_ace.aceType, + }; + add_ace2 = true; + } break; case ID_TYPE_GID: nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; @@ -805,7 +831,16 @@ static int smbacl4_fill_ace4( } } - return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace); + ret = nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace); + if (ret != 0) { + return -1; + } + + if (!add_ace2) { + return 0; + } + + return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace_2); } static int smbacl4_substitute_special( diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index d7152a0737a..170a397579a 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1671,6 +1671,7 @@ struct dacl_to_nfs4_idmap_both { uint32_t nfs4_flags; uint32_t nfs4_ace_flags; uint32_t nfs4_id; + int num_nfs4_aces; }; /* @@ -1684,13 +1685,17 @@ static void test_dacl_to_nfs4_idmap_type_both(void **state) struct dacl_to_nfs4_idmap_both dacl_to_nfs4_idmap_both[] = { { &sids[2], 0, - SMB_ACE4_ID_SPECIAL, SMB_ACE4_IDENTIFIER_GROUP, SMB_ACE4_WHO_GROUP }, + SMB_ACE4_ID_SPECIAL, SMB_ACE4_IDENTIFIER_GROUP, SMB_ACE4_WHO_GROUP, + 2 }, { &sids[2], SEC_ACE_FLAG_OBJECT_INHERIT, - 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1002 }, + 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1002, + 1 }, { &sids[6], 0, - 0, SMB_ACE4_IDENTIFIER_GROUP, 1005 }, + 0, SMB_ACE4_IDENTIFIER_GROUP, 1005, + 1 }, { &sids[6], SEC_ACE_FLAG_OBJECT_INHERIT, - 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1005 }, + 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1005, + 1 }, }; for (i = 0; i < ARRAY_SIZE(dacl_to_nfs4_idmap_both); i++) { @@ -1720,11 +1725,11 @@ static void test_dacl_to_nfs4_idmap_type_both(void **state) assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); - assert_int_equal(smb_get_naces(nfs4_acl), 1); + assert_int_equal(smb_get_naces(nfs4_acl), + dacl_to_nfs4_idmap_both[i].num_nfs4_aces); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); - assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, @@ -1744,6 +1749,28 @@ static void test_dacl_to_nfs4_idmap_type_both(void **state) assert_int_equal(nfs4_ace->aceType, SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + + if (dacl_to_nfs4_idmap_both[i].num_nfs4_aces == 2) { + nfs4_ace_container = smb_next_ace4(nfs4_ace_container); + assert_non_null(nfs4_ace_container); + + nfs4_ace = smb_get_ace4(nfs4_ace_container); + assert_int_equal(nfs4_ace->flags, + dacl_to_nfs4_idmap_both[i].nfs4_flags); + assert_int_equal(nfs4_ace->aceFlags, + dacl_to_nfs4_idmap_both[i].nfs4_ace_flags & + ~SMB_ACE4_IDENTIFIER_GROUP); + if (nfs4_ace->flags & SMB_ACE4_ID_SPECIAL) { + assert_int_equal(nfs4_ace->who.special_id, + SMB_ACE4_WHO_OWNER); + } else { + assert_int_equal(nfs4_ace->who.uid, + dacl_to_nfs4_idmap_both[i].nfs4_id); + } + assert_int_equal(nfs4_ace->aceType, + SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE); + assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); + } } TALLOC_FREE(frame); -- 2.17.1 From 7d40b00bac82d8cd185850aa1b8a13c5f79848d7 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 18 Jul 2019 11:49:29 -0700 Subject: [PATCH 062/376] nfs4_acls: Rename smbacl4_fill_ace4 function As this function now maps the ACE and also adds it to the NFSv4 ACE, change the name to better describe its behavior. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 169812943de23cf2752289c63331d786b0b063bd) --- source3/modules/nfs4_acls.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 70d725eb937..663fcba67aa 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -708,14 +708,12 @@ static int nfs4_acl_add_ace(enum smbacl4_acedup_enum acedup, return 0; } -static int smbacl4_fill_ace4( - bool is_directory, - const struct smbacl4_vfs_params *params, - uid_t ownerUID, - gid_t ownerGID, - const struct security_ace *ace_nt, /* input */ - struct SMB4ACL_T *nfs4_acl -) +static int nfs4_acl_add_sec_ace(bool is_directory, + const struct smbacl4_vfs_params *params, + uid_t ownerUID, + gid_t ownerGID, + const struct security_ace *ace_nt, + struct SMB4ACL_T *nfs4_acl) { struct dom_sid_buf buf; SMB_ACE4PROP_T nfs4_ace = { 0 }; @@ -936,9 +934,9 @@ static struct SMB4ACL_T *smbacl4_win2nfs4( for(i=0; inum_aces; i++) { int ret; - ret = smbacl4_fill_ace4(is_directory, pparams, - ownerUID, ownerGID, - dacl->aces + i, theacl); + ret = nfs4_acl_add_sec_ace(is_directory, pparams, + ownerUID, ownerGID, + dacl->aces + i, theacl); if (ret == -1) { return NULL; } -- 2.17.1 From 78d426fb0d4f9332e9c0a084993b5f2f5e0cdc40 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 2 Jul 2019 15:08:11 -0700 Subject: [PATCH 063/376] nfs4_acls: Remove duplicate entries when mapping from NFS4 ACL to DACL The previous patch added an additional entry for IDMAP_TYPE_BOTH. When mapping back to a DACL, there should be no additional entry. Add a loop that will check and remove entries that are exact duplicates. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 9c88602128592ddad537bf70cbe3c51f0b2cebe5) --- source3/modules/nfs4_acls.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 663fcba67aa..74b66a2c392 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -297,6 +297,35 @@ static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) return 0; } +static void check_for_duplicate_sec_ace(struct security_ace *nt_ace_list, + int *good_aces) +{ + struct security_ace *last = NULL; + int i; + + if (*good_aces < 2) { + return; + } + + last = &nt_ace_list[(*good_aces) - 1]; + + for (i = 0; i < (*good_aces) - 1; i++) { + struct security_ace *cur = &nt_ace_list[i]; + + if (cur->type == last->type && + cur->flags == last->flags && + cur->access_mask == last->access_mask && + dom_sid_equal(&cur->trustee, &last->trustee)) + { + struct dom_sid_buf sid_buf; + + DBG_INFO("Removing duplicate entry for SID %s.\n", + dom_sid_str_buf(&last->trustee, &sid_buf)); + (*good_aces)--; + } + } +} + static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, const struct smbacl4_vfs_params *params, struct SMB4ACL_T *acl, /* in */ @@ -438,6 +467,8 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, ace->aceType, mask, win_ace_flags); } + + check_for_duplicate_sec_ace(nt_ace_list, &good_aces); } nt_ace_list = talloc_realloc(mem_ctx, nt_ace_list, struct security_ace, -- 2.17.1 From 77052fbc65a375dc5a3dda4ac9d212b808ca802f Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 10 Jul 2019 13:14:32 -0700 Subject: [PATCH 064/376] nfs4_acls: Add test for merging duplicates when mapping from NFS4 ACL to DACL The previous patch introduced merging of duplicates on the mapping path from NFS4 ACL entries to DACL entries. Add a testcase to verify the expected behavior of this codepath. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 1a137a2f20c2f159c5feaef230a2b85bb9fb23b5) --- source3/modules/test_nfs4_acls.c | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c index 170a397579a..0b23bd1d02e 100644 --- a/source3/modules/test_nfs4_acls.c +++ b/source3/modules/test_nfs4_acls.c @@ -1776,6 +1776,84 @@ static void test_dacl_to_nfs4_idmap_type_both(void **state) TALLOC_FREE(frame); } +static void test_nfs4_to_dacl_remove_duplicate(void **state) +{ + + struct dom_sid *sids = *state; + TALLOC_CTX *frame = talloc_stackframe(); + struct SMB4ACL_T *nfs4_acl; + SMB_ACE4PROP_T nfs4_ace; + struct security_ace *dacl_aces; + int good_aces; + struct smbacl4_vfs_params params = { + .mode = e_simple, + .do_chown = true, + .acedup = e_dontcare, + .map_full_control = true, + }; + + nfs4_acl = smb_create_smb4acl(frame); + assert_non_null(nfs4_acl); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.uid = 1002, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = SMB_ACE4_INHERITED_ACE, + .aceMask = SMB_ACE4_WRITE_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.gid = 1002, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_INHERITED_ACE, + .aceMask = SMB_ACE4_WRITE_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.gid = 1002, + .aceType = SMB_ACE4_ACCESS_DENIED_ACE_TYPE, + .aceFlags = SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_INHERITED_ACE, + .aceMask = SMB_ACE4_WRITE_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + nfs4_ace = (SMB_ACE4PROP_T) { + .flags = 0, + .who.gid = 1002, + .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, + .aceFlags = SMB_ACE4_IDENTIFIER_GROUP| + SMB_ACE4_INHERITED_ACE, + .aceMask = SMB_ACE4_WRITE_DATA, + }; + assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); + + assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, + &sids[0], &sids[1], true, + &dacl_aces, &good_aces)); + + assert_int_equal(good_aces, 2); + assert_non_null(dacl_aces); + + assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); + assert_int_equal(dacl_aces[0].flags, SEC_ACE_FLAG_INHERITED_ACE); + assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_WRITE_DATA); + assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[2])); + + assert_int_equal(dacl_aces[1].type, SEC_ACE_TYPE_ACCESS_DENIED); + assert_int_equal(dacl_aces[1].flags, SEC_ACE_FLAG_INHERITED_ACE); + assert_int_equal(dacl_aces[1].access_mask, SEC_FILE_WRITE_DATA); + assert_true(dom_sid_equal(&dacl_aces[1].trustee, &sids[2])); + + TALLOC_FREE(frame); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1799,6 +1877,7 @@ int main(int argc, char **argv) cmocka_unit_test(test_nfs4_to_dacl_config_special), cmocka_unit_test(test_nfs4_to_dacl_idmap_type_both), cmocka_unit_test(test_dacl_to_nfs4_idmap_type_both), + cmocka_unit_test(test_nfs4_to_dacl_remove_duplicate), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.17.1 From d186689038c5f807b092f63d7f89fd6b6dd95241 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 17 Jul 2019 15:29:06 -0700 Subject: [PATCH 065/376] nfs4_acls: Use correct owner information for ACL after owner change After a chown, the cached stat data is obviously no longer valid. The code in smb_set_nt_acl_nfs4 checked the file correctly, but did only use a local buffer for the stat data. So later checks of the stat buffer under the fsp->fsp_name->st would still see the old information. Fix this by removing the local stat buffer and always update the one under fsp->fsp_name->st. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 86f7af84f04b06ed96b30f936ace92aa0937be06) --- source3/modules/nfs4_acls.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 74b66a2c392..eb76696948b 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -994,11 +994,11 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, struct SMB4ACL_T *theacl = NULL; bool result, is_directory; - SMB_STRUCT_STAT sbuf; bool set_acl_as_root = false; uid_t newUID = (uid_t)-1; gid_t newGID = (gid_t)-1; int saved_errno; + NTSTATUS status; TALLOC_CTX *frame = talloc_stackframe(); DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp))); @@ -1022,25 +1022,29 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, pparams = ¶ms; } - if (smbacl4_fGetFileOwner(fsp, &sbuf)) { + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); - return map_nt_error_from_unix(errno); + return status; } - is_directory = S_ISDIR(sbuf.st_ex_mode); + is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode); if (pparams->do_chown) { /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ - NTSTATUS status = unpack_nt_owners(fsp->conn, &newUID, &newGID, - security_info_sent, psd); + + uid_t old_uid = fsp->fsp_name->st.st_ex_uid; + uid_t old_gid = fsp->fsp_name->st.st_ex_uid; + status = unpack_nt_owners(fsp->conn, &newUID, &newGID, + security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { DEBUG(8, ("unpack_nt_owners failed")); TALLOC_FREE(frame); return status; } - if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) { - + if (((newUID != (uid_t)-1) && (old_uid != newUID)) || + ((newGID != (gid_t)-1) && (old_gid != newGID))) + { status = try_chown(fsp, newUID, newGID); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("chown %s, %u, %u failed. Error = " @@ -1055,11 +1059,14 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, DEBUG(10,("chown %s, %u, %u succeeded.\n", fsp_str_dbg(fsp), (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp->conn, - fsp->fsp_name, - &sbuf)){ + + /* + * Owner change, need to update stat info. + */ + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); - return map_nt_error_from_unix(errno); + return status; } /* If we successfully chowned, we know we must @@ -1077,7 +1084,8 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, } theacl = smbacl4_win2nfs4(frame, is_directory, psd->dacl, pparams, - sbuf.st_ex_uid, sbuf.st_ex_gid); + fsp->fsp_name->st.st_ex_uid, + fsp->fsp_name->st.st_ex_gid); if (!theacl) { TALLOC_FREE(frame); return map_nt_error_from_unix(errno); -- 2.17.1 From 7c90ecdb15cc6d572a37c2d435b6c7d86559d944 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 9 Jul 2019 12:04:35 -0700 Subject: [PATCH 066/376] vfs_gpfs: Remove merge_writeappend parameter All supported GPFS versions now support setting WRITE and APPEND in the ACLs independently. Remove this now unused parameter to simplify the code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 0aca678fcf1788a76cf0ff11399211c795aa7d2f) --- source3/modules/vfs_gpfs.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index 4b963edab11..72c06a6dcb1 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -708,29 +708,6 @@ static struct gpfs_acl *vfs_gpfs_smbacl2gpfsacl(TALLOC_CTX *mem_ctx, gace->aceType = aceprop->aceType; gace->aceFlags = aceprop->aceFlags; gace->aceMask = aceprop->aceMask; - - /* - * GPFS can't distinguish between WRITE and APPEND on - * files, so one being set without the other is an - * error. Sorry for the many ()'s :-) - */ - - if (!fsp->is_directory - && - ((((gace->aceMask & ACE4_MASK_WRITE) == 0) - && ((gace->aceMask & ACE4_MASK_APPEND) != 0)) - || - (((gace->aceMask & ACE4_MASK_WRITE) != 0) - && ((gace->aceMask & ACE4_MASK_APPEND) == 0))) - && - lp_parm_bool(fsp->conn->params->service, "gpfs", - "merge_writeappend", True)) { - DEBUG(2, ("vfs_gpfs.c: file [%s]: ACE contains " - "WRITE^APPEND, setting WRITE|APPEND\n", - fsp_str_dbg(fsp))); - gace->aceMask |= ACE4_MASK_WRITE|ACE4_MASK_APPEND; - } - gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0; if (aceprop->flags&SMB_ACE4_ID_SPECIAL) -- 2.17.1 From 90ddc22ea5552b7d3a2c4cc7cb1b75e3ef1e52f2 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 10 Jul 2019 11:06:19 -0700 Subject: [PATCH 067/376] docs: Remove gpfs:merge_writeappend from vfs_gpfs manpage BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit 8bd79ecc37376dbaa35606f9c2777653eb3d55e3) --- docs-xml/manpages/vfs_gpfs.8.xml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/docs-xml/manpages/vfs_gpfs.8.xml b/docs-xml/manpages/vfs_gpfs.8.xml index 2f3b4274e4b..fb1f5bb2237 100644 --- a/docs-xml/manpages/vfs_gpfs.8.xml +++ b/docs-xml/manpages/vfs_gpfs.8.xml @@ -204,26 +204,6 @@ - gpfs:merge_writeappend = [ yes | no ] - - - GPFS ACLs doesn't know about the 'APPEND' right. - This option lets Samba map the 'APPEND' right to 'WRITE'. - - - - - yes(default) - map 'APPEND' to 'WRITE'. - - - no - do not map 'APPEND' to 'WRITE'. - - - - - - - gpfs:acl = [ yes | no ] -- 2.17.1 From 39495b14cdd228c842666222952ad789e63977ef Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 9 Jul 2019 13:08:35 -0700 Subject: [PATCH 068/376] vfs_gpfs: Move mapping from generic NFSv ACL to GPFS ACL to separate function This is not functional change. It cleans up the code a bit and makes expanding this codepath in a later patch easier. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit fbf3a090a9ec94262b2924461cc1d6336af9919c) --- source3/modules/vfs_gpfs.c | 69 ++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index 72c06a6dcb1..d0dc1ddb173 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -672,6 +672,43 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle, return map_nt_error_from_unix(errno); } +static bool vfs_gpfs_nfs4_ace_to_gpfs_ace(SMB_ACE4PROP_T *nfs4_ace, + struct gpfs_ace_v4 *gace) +{ + gace->aceType = nfs4_ace->aceType; + gace->aceFlags = nfs4_ace->aceFlags; + gace->aceMask = nfs4_ace->aceMask; + + if (nfs4_ace->flags & SMB_ACE4_ID_SPECIAL) { + switch(nfs4_ace->who.special_id) { + case SMB_ACE4_WHO_EVERYONE: + gace->aceIFlags = ACE4_IFLAG_SPECIAL_ID; + gace->aceWho = ACE4_SPECIAL_EVERYONE; + break; + case SMB_ACE4_WHO_OWNER: + gace->aceIFlags = ACE4_IFLAG_SPECIAL_ID; + gace->aceWho = ACE4_SPECIAL_OWNER; + break; + case SMB_ACE4_WHO_GROUP: + gace->aceIFlags = ACE4_IFLAG_SPECIAL_ID; + gace->aceWho = ACE4_SPECIAL_GROUP; + break; + default: + DBG_WARNING("Unsupported special_id %d\n", + nfs4_ace->who.special_id); + return false; + } + + return true; + } + + gace->aceIFlags = 0; + gace->aceWho = (nfs4_ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) ? + nfs4_ace->who.gid : nfs4_ace->who.uid; + + return true; +} + static struct gpfs_acl *vfs_gpfs_smbacl2gpfsacl(TALLOC_CTX *mem_ctx, files_struct *fsp, struct SMB4ACL_T *smbacl, @@ -704,35 +741,11 @@ static struct gpfs_acl *vfs_gpfs_smbacl2gpfsacl(TALLOC_CTX *mem_ctx, for (smbace=smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) { struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, gacl->acl_nace); SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace); + bool add_ace; - gace->aceType = aceprop->aceType; - gace->aceFlags = aceprop->aceFlags; - gace->aceMask = aceprop->aceMask; - gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0; - - if (aceprop->flags&SMB_ACE4_ID_SPECIAL) - { - switch(aceprop->who.special_id) - { - case SMB_ACE4_WHO_EVERYONE: - gace->aceWho = ACE4_SPECIAL_EVERYONE; - break; - case SMB_ACE4_WHO_OWNER: - gace->aceWho = ACE4_SPECIAL_OWNER; - break; - case SMB_ACE4_WHO_GROUP: - gace->aceWho = ACE4_SPECIAL_GROUP; - break; - default: - DEBUG(8, ("unsupported special_id %d\n", aceprop->who.special_id)); - continue; /* don't add it !!! */ - } - } else { - /* just only for the type safety... */ - if (aceprop->aceFlags&SMB_ACE4_IDENTIFIER_GROUP) - gace->aceWho = aceprop->who.gid; - else - gace->aceWho = aceprop->who.uid; + add_ace = vfs_gpfs_nfs4_ace_to_gpfs_ace(aceprop, gace); + if (!add_ace) { + continue; } gacl->acl_nace++; -- 2.17.1 From d18896d19988b1096849c00a80dda42a727d5c4c Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 9 Jul 2019 13:39:55 -0700 Subject: [PATCH 069/376] vfs_gpfs: Implement special case for denying owner access to ACL In GPFS, it is not possible to deny ACL or attribute access through a SPECIAL_OWNER entry. The best that can be done is mapping this to a named user entry, as this one can at least be stored in an ACL. The same cannot be done for inheriting SPECIAL_OWNER entries, as these represent CREATOR OWNER entries, and the limitation of not being able to deny owner access to ACL or attributes remains. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14032 Signed-off-by: Christof Schmitt Reviewed-by: Ralph Boehme (cherry picked from commit c1770ed96fd3137f45d584ba9328333d5505e3af) --- source3/modules/vfs_gpfs.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index d0dc1ddb173..f0d5074d36b 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -673,7 +673,8 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle, } static bool vfs_gpfs_nfs4_ace_to_gpfs_ace(SMB_ACE4PROP_T *nfs4_ace, - struct gpfs_ace_v4 *gace) + struct gpfs_ace_v4 *gace, + uid_t owner_uid) { gace->aceType = nfs4_ace->aceType; gace->aceFlags = nfs4_ace->aceFlags; @@ -686,8 +687,35 @@ static bool vfs_gpfs_nfs4_ace_to_gpfs_ace(SMB_ACE4PROP_T *nfs4_ace, gace->aceWho = ACE4_SPECIAL_EVERYONE; break; case SMB_ACE4_WHO_OWNER: - gace->aceIFlags = ACE4_IFLAG_SPECIAL_ID; - gace->aceWho = ACE4_SPECIAL_OWNER; + /* + * With GPFS it is not possible to deny ACL or + * attribute access to the owner. Setting an + * ACL with such an entry is not possible. + * Denying ACL or attribute access for the + * owner through a named ACL entry can be + * stored in an ACL, it is just not effective. + * + * Map this case to a named entry to allow at + * least setting this ACL, which will be + * enforced by the smbd permission check. Do + * not do this for an inheriting OWNER entry, + * as this represents a CREATOR OWNER ACE. The + * remaining limitation is that CREATOR OWNER + * cannot deny ACL or attribute access. + */ + if (!nfs_ace_is_inherit(nfs4_ace) && + nfs4_ace->aceType == + SMB_ACE4_ACCESS_DENIED_ACE_TYPE && + nfs4_ace->aceMask & (SMB_ACE4_READ_ATTRIBUTES| + SMB_ACE4_WRITE_ATTRIBUTES| + SMB_ACE4_READ_ACL| + SMB_ACE4_WRITE_ACL)) { + gace->aceIFlags = 0; + gace->aceWho = owner_uid; + } else { + gace->aceIFlags = ACE4_IFLAG_SPECIAL_ID; + gace->aceWho = ACE4_SPECIAL_OWNER; + } break; case SMB_ACE4_WHO_GROUP: gace->aceIFlags = ACE4_IFLAG_SPECIAL_ID; @@ -743,7 +771,8 @@ static struct gpfs_acl *vfs_gpfs_smbacl2gpfsacl(TALLOC_CTX *mem_ctx, SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace); bool add_ace; - add_ace = vfs_gpfs_nfs4_ace_to_gpfs_ace(aceprop, gace); + add_ace = vfs_gpfs_nfs4_ace_to_gpfs_ace(aceprop, gace, + fsp->fsp_name->st.st_ex_uid); if (!add_ace) { continue; } -- 2.17.1 From be508cda25d97b825fef3d605938faa3726cde44 Mon Sep 17 00:00:00 2001 From: Aaron Haslett Date: Mon, 22 Jul 2019 15:29:03 +1200 Subject: [PATCH 070/376] downgradedatabase: comply with samba.tests.source In next commit we'll install the script, samba.tests.source picked up the lack of a copyright message and some whitespace errors, so this patch fixes that stuff first. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Aaron Haslett Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit c4aebb15001c830a46d5a6ad8ea11a6f9ea4fd04) --- source4/scripting/bin/sambadowngradedatabase | 26 +++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/source4/scripting/bin/sambadowngradedatabase b/source4/scripting/bin/sambadowngradedatabase index 9d1e2b8cc76..87a989bfd6a 100755 --- a/source4/scripting/bin/sambadowngradedatabase +++ b/source4/scripting/bin/sambadowngradedatabase @@ -1,4 +1,24 @@ -#!/usr/bin/env python3 +#!/usr/bin/python3 +# +# Unix SMB/CIFS implementation. +# Copyright (C) Andrew Bartlett 2019 +# +# Downgrade a database from 4.11 format to 4.7 format. 4.7 Format will +# run on any version of Samba AD, and Samba will repack/reconfigure the +# database if necessary. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . from __future__ import print_function import optparse import sys @@ -38,9 +58,9 @@ samdb = ldb.Ldb(url=url, options=["modules:"]) partitions = samdb.search(base="@PARTITION", - scope=ldb.SCOPE_BASE, + scope=ldb.SCOPE_BASE, attrs=["backendStore", "partition"]) - + backend = str(partitions[0].get('backendStore', 'tdb')) if backend == "mdb": -- 2.17.1 From 7a8f68f615034c696e90f86eb1670f4b100300fc Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Mon, 29 Jul 2019 13:35:08 +1200 Subject: [PATCH 071/376] tests: Avoid hardcoding relative filepath If we move the test file, the test will break. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit a8cdbe0b824f57f73eee09143148f009a9c58582) --- python/samba/tests/blackbox/downgradedatabase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/blackbox/downgradedatabase.py b/python/samba/tests/blackbox/downgradedatabase.py index a5e540c1354..4a8411b1f1a 100644 --- a/python/samba/tests/blackbox/downgradedatabase.py +++ b/python/samba/tests/blackbox/downgradedatabase.py @@ -23,8 +23,8 @@ import shutil from subprocess import check_output from samba.samdb import SamDB -COMMAND = os.path.join(os.path.dirname(__file__), - "../../../../../source4/scripting/bin/sambadowngradedatabase") +COMMAND = os.path.join(os.environ.get("SRCDIR_ABS"), + "source4/scripting/bin/sambadowngradedatabase") class DowngradeTestBase(BlackboxTestCase): -- 2.17.1 From a1b3796b5643d7d727964751efb19675d5ee42c7 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Mon, 29 Jul 2019 13:39:04 +1200 Subject: [PATCH 072/376] downgradedatabase: rename to samba_downgrade_db Just so that it's slightly less of a mouthful for users. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit fdaaee8d3aac77d91642a7d75d4bcd15d4df8657) --- python/samba/tests/blackbox/downgradedatabase.py | 2 +- selftest/knownfail.d/usage | 2 +- .../bin/{sambadowngradedatabase => samba_downgrade_db} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename source4/scripting/bin/{sambadowngradedatabase => samba_downgrade_db} (100%) diff --git a/python/samba/tests/blackbox/downgradedatabase.py b/python/samba/tests/blackbox/downgradedatabase.py index 4a8411b1f1a..3d230609efc 100644 --- a/python/samba/tests/blackbox/downgradedatabase.py +++ b/python/samba/tests/blackbox/downgradedatabase.py @@ -24,7 +24,7 @@ from subprocess import check_output from samba.samdb import SamDB COMMAND = os.path.join(os.environ.get("SRCDIR_ABS"), - "source4/scripting/bin/sambadowngradedatabase") + "source4/scripting/bin/samba_downgrade_db") class DowngradeTestBase(BlackboxTestCase): diff --git a/selftest/knownfail.d/usage b/selftest/knownfail.d/usage index 23d52c0b727..0a495858e8c 100644 --- a/selftest/knownfail.d/usage +++ b/selftest/knownfail.d/usage @@ -25,7 +25,7 @@ samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_rebuildextendedd samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_renamedc.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_repl_cleartext_pwd_py.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_rodcdns.none. -samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_sambadowngradedatabase.none. +samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_downgrade_db.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_gpupdate.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_gpupdate_.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_kcc.none. diff --git a/source4/scripting/bin/sambadowngradedatabase b/source4/scripting/bin/samba_downgrade_db similarity index 100% rename from source4/scripting/bin/sambadowngradedatabase rename to source4/scripting/bin/samba_downgrade_db -- 2.17.1 From 309ec3b63c5d9f441bcc922e62c2f6a2c2907f62 Mon Sep 17 00:00:00 2001 From: Aaron Haslett Date: Mon, 22 Jul 2019 13:35:21 +1200 Subject: [PATCH 073/376] downgradedatabase: Add man-page documentation A man-page is needed so that we can install this tool as part of the Samba package. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Aaron Haslett Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit c89df3862b17fad9c4648b5d9c6805120d732df8) --- docs-xml/manpages/samba_downgrade_db.8.xml | 95 ++++++++++++++++++++++ docs-xml/wscript_build | 1 + 2 files changed, 96 insertions(+) create mode 100644 docs-xml/manpages/samba_downgrade_db.8.xml diff --git a/docs-xml/manpages/samba_downgrade_db.8.xml b/docs-xml/manpages/samba_downgrade_db.8.xml new file mode 100644 index 00000000000..7b0c822cf21 --- /dev/null +++ b/docs-xml/manpages/samba_downgrade_db.8.xml @@ -0,0 +1,95 @@ + + + + + + samba_downgrade_db + 8 + Samba + User Commands + &doc.version; + + + + + samba_downgrade_db + Samba tool for downgrading AD databases + + + + + + samba_downgrade_db + -H + -s + + + + + DESCRIPTION + This tool is part of the samba + 8 suite. + + The format of the Samba Active Directory (AD) database changed in + version 4.8 and 4.11. When downgrading a Samba AD Domain Controller (DC) + to a release that is older than either of these versions (e.g. 4.11 to + 4.10), the AD database must be manually downgraded + before the Samba packages can be safely downgraded. + + + This tool downgrades a Samba sam.ldb database from the format + used in version &doc.version; to that of version 4.7. The v4.7 database + format can safely be read by any version of Samba. If necessary, later + versions of Samba will repack and reconfigure a v4.7-format database when + the samba executable is first started. + + Note that all Samba services must be stopped on the DC before running + this tool. Once the tool has run, do not restart samba or modify the + database before the Samba software package has been downgraded. + + + + + OPTIONS + + + + + -H [sam.ldb file] + + Link directly to a sam.ldb file instead of using path in system + smb.conf + + + + + -s [smb.conf file] + + Link directly to smb.conf file instead of system default (usually + in /usr/local/samba/etc/smb.conf) + + + + + + + + VERSION + + This man page is complete for version &doc.version; of the Samba + suite. + + + + AUTHOR + + The original Samba software and related utilities + were created by Andrew Tridgell. Samba is now developed + by the Samba Team as an Open Source project similar + to the way the Linux kernel is developed. + + The samba_downgrade_db tool was developed by the Samba team + at Catalyst IT Ltd. + + + diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build index 575fb702b46..3dad0a21313 100644 --- a/docs-xml/wscript_build +++ b/docs-xml/wscript_build @@ -31,6 +31,7 @@ manpages=''' manpages/samba-tool.8 manpages/samba.7 manpages/samba.8 + manpages/samba_downgrade_db.8 manpages/sharesec.1 manpages/smbcacls.1 manpages/smbclient.1 -- 2.17.1 From b3987205fe2770bd88ae5ee8e10a85cebf662ac0 Mon Sep 17 00:00:00 2001 From: Aaron Haslett Date: Mon, 22 Jul 2019 13:35:21 +1200 Subject: [PATCH 074/376] downgradedatabase: installing script Installing downgrade script so people don't need the source tree for it. Exception added in usage test because running the script without arguments is valid. (This avoids the need to knownfail it). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Aaron Haslett Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit 6dcf00ba0a470ba25aabae06b409ec95404c246f) --- python/samba/tests/usage.py | 2 ++ selftest/knownfail.d/usage | 1 - source4/scripting/bin/wscript_build | 3 ++- source4/scripting/wscript_build | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index ba18a3e0729..4b7bccde758 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -78,6 +78,8 @@ EXCLUDE_USAGE = { 'selftest/tap2subunit', 'script/show_test_time', 'source4/scripting/bin/subunitrun', + 'bin/samba_downgrade_db', + 'source4/scripting/bin/samba_downgrade_db', 'source3/selftest/tests.py', 'selftest/tests.py', 'python/samba/subunit/run.py', diff --git a/selftest/knownfail.d/usage b/selftest/knownfail.d/usage index 0a495858e8c..3e54f80a2de 100644 --- a/selftest/knownfail.d/usage +++ b/selftest/knownfail.d/usage @@ -25,7 +25,6 @@ samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_rebuildextendedd samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_renamedc.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_repl_cleartext_pwd_py.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_rodcdns.none. -samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_downgrade_db.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_gpupdate.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_gpupdate_.none. samba.tests.usage.samba.tests.usage.PythonScriptUsageTests.test_samba_kcc.none. diff --git a/source4/scripting/bin/wscript_build b/source4/scripting/bin/wscript_build index 42b37faa32a..87d23545487 100644 --- a/source4/scripting/bin/wscript_build +++ b/source4/scripting/bin/wscript_build @@ -7,6 +7,7 @@ if bld.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'): 'samba_kcc', 'samba_upgradeprovision', 'samba_upgradedns', - 'gen_output.py']: + 'gen_output.py', + 'samba_downgrade_db']: bld.SAMBA_SCRIPT(script, pattern=script, installdir='.') bld.SAMBA_SCRIPT('samba-gpupdate', pattern='samba-gpupdate', installdir='.') diff --git a/source4/scripting/wscript_build b/source4/scripting/wscript_build index df24e921cd9..31c395d3e4b 100644 --- a/source4/scripting/wscript_build +++ b/source4/scripting/wscript_build @@ -4,7 +4,7 @@ from samba_utils import MODE_755 sbin_files = '' if bld.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'): - sbin_files = 'bin/samba_dnsupdate bin/samba_spnupdate bin/samba_upgradedns bin/samba_kcc ' + sbin_files = 'bin/samba_downgrade_db bin/samba_dnsupdate bin/samba_spnupdate bin/samba_upgradedns bin/samba_kcc ' sbin_files += 'bin/samba-gpupdate' man_files = 'man/samba-gpupdate.8' -- 2.17.1 From 70726f2dfba3907ebc11b196aba61fe8358ac989 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Tue, 30 Jul 2019 16:40:55 +1200 Subject: [PATCH 075/376] ldb: Always log when the database pack format changes LDB_DEBUG_WARNING gets logged by Samba as level 2, whereas the default log level for Samba is 0. It's not really fair to the user to change the format of their database on disk and potentially not tell them. This patch adds a log with level zero (using a alias define, as this technically isn't a fatal problem). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit a2b0fc7c00360f37ed6819f21380294b70d4a195) --- lib/ldb/include/ldb.h | 3 +++ lib/ldb/ldb_key_value/ldb_kv_index.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h index f06d5e95528..3cba0f4d543 100644 --- a/lib/ldb/include/ldb.h +++ b/lib/ldb/include/ldb.h @@ -220,6 +220,9 @@ struct tevent_context; enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR, LDB_DEBUG_WARNING, LDB_DEBUG_TRACE}; +/* alias for something that's not a fatal error but we really want to log */ +#define LDB_DEBUG_ALWAYS_LOG LDB_DEBUG_FATAL + /** the user can optionally supply a debug function. The function is based on the vfprintf() style of interface, but with the addition diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index ef275b28013..5de316579d7 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -3571,7 +3571,7 @@ static int re_pack(struct ldb_kv_private *ldb_kv, * want to spam the log. */ if ((!ctx->normal_record_seen) && (!ldb_dn_is_special(msg->dn))) { - ldb_debug(ldb, LDB_DEBUG_WARNING, + ldb_debug(ldb, LDB_DEBUG_ALWAYS_LOG, "Repacking database with format %#010x", ldb_kv->pack_format_version); ctx->normal_record_seen = true; -- 2.17.1 From b99fff86ebb64e31fd3577164f55246705511c3b Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Tue, 30 Jul 2019 15:02:25 +1200 Subject: [PATCH 076/376] ldb: Move where we update the pack format version Store it on the repack context so that we can log a more informative message "Repacking from format x to format y". While this is not really a big deal currently, it could be worth recording for potential future scenarios (i.e. supporting three or more pack versions), where upgrades could potentially skip an intermediary pack format version. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit d427bd6c775d8117504e76eed42cd2c383512e34) --- lib/ldb/ldb_key_value/ldb_kv.c | 2 -- lib/ldb/ldb_key_value/ldb_kv.h | 1 + lib/ldb/ldb_key_value/ldb_kv_index.c | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ldb/ldb_key_value/ldb_kv.c b/lib/ldb/ldb_key_value/ldb_kv.c index f768fb5e1e4..4e7b8a116b3 100644 --- a/lib/ldb/ldb_key_value/ldb_kv.c +++ b/lib/ldb/ldb_key_value/ldb_kv.c @@ -315,8 +315,6 @@ static int ldb_kv_maybe_repack(struct ldb_kv_private *ldb_kv) { ldb_kv->target_pack_format_version) { int r; struct ldb_context *ldb = ldb_module_get_ctx(ldb_kv->module); - ldb_kv->pack_format_version = - ldb_kv->target_pack_format_version; r = ldb_kv_repack(ldb_kv->module); if (r != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_ERROR, diff --git a/lib/ldb/ldb_key_value/ldb_kv.h b/lib/ldb/ldb_key_value/ldb_kv.h index e627644ba34..f9dffae2dcf 100644 --- a/lib/ldb/ldb_key_value/ldb_kv.h +++ b/lib/ldb/ldb_key_value/ldb_kv.h @@ -175,6 +175,7 @@ struct ldb_kv_repack_context { int error; uint32_t count; bool normal_record_seen; + uint32_t old_version; }; diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index 5de316579d7..eb84a790e00 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -3595,10 +3595,13 @@ int ldb_kv_repack(struct ldb_module *module) struct ldb_kv_repack_context ctx; int ret; + ctx.old_version = ldb_kv->pack_format_version; ctx.count = 0; ctx.error = LDB_SUCCESS; ctx.normal_record_seen = false; + ldb_kv->pack_format_version = ldb_kv->target_pack_format_version; + /* Iterate all database records and repack them in the new format */ ret = ldb_kv->kv_ops->iterate(ldb_kv, re_pack, &ctx); if (ret < 0) { -- 2.17.1 From 6de3d8f7ce0f97810515b81f4da1a7cc1eb4a241 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Tue, 30 Jul 2019 15:15:40 +1200 Subject: [PATCH 077/376] ldb: Change pack format defines to enum The main reason is so that any future pack formats will continue incrementing this number in a sequential fashion. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit 38e3e7cd328edac302e95ac8839e858c4a225485) --- lib/ldb/include/ldb_module.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h index ab3d25c5c6e..8c1e5ee7936 100644 --- a/lib/ldb/include/ldb_module.h +++ b/lib/ldb/include/ldb_module.h @@ -559,12 +559,15 @@ int ldb_unpack_get_format(const struct ldb_val *data, #define LDB_UNPACK_DATA_FLAG_NO_ATTRS 0x0008 #define LDB_UNPACK_DATA_FLAG_READ_LOCKED 0x0010 -/* In-use packing formats */ -#define LDB_PACKING_FORMAT 0x26011967 -#define LDB_PACKING_FORMAT_V2 0x26011968 +enum ldb_pack_format { -/* Old packing formats */ -#define LDB_PACKING_FORMAT_NODN 0x26011966 + /* Old packing format (based on a somewhat arbitrary date) */ + LDB_PACKING_FORMAT_NODN = 0x26011966, + + /* In-use packing formats */ + LDB_PACKING_FORMAT, + LDB_PACKING_FORMAT_V2 +}; /** Forces a specific ldb handle to use the global event context. -- 2.17.1 From 1c2f1bd04abbedb3cfb31bb4a0ee4292c21dacc4 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Tue, 30 Jul 2019 16:40:55 +1200 Subject: [PATCH 078/376] ldb: Log pack format in user-friendly way The "format 0x26011968" log confused me (and I'm a developer). We can subtract the base offset from the pack format to get a more user-friendly number, e.g. v0 (not actually used), v1, v2, etc. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit 5fee9388422e259c2a56e4dccbf44d22ba426ca3) --- lib/ldb/ldb_key_value/ldb_kv_index.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index eb84a790e00..27454d3f734 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -3526,6 +3526,18 @@ static int re_index(struct ldb_kv_private *ldb_kv, return 0; } +/* + * Convert the 4-byte pack format version to a number that's slightly + * more intelligible to a user e.g. version 0, 1, 2, etc. + */ +static uint32_t displayable_pack_version(uint32_t version) { + if (version < LDB_PACKING_FORMAT_NODN) { + return version; /* unknown - can't convert */ + } + + return (version - LDB_PACKING_FORMAT_NODN); +} + static int re_pack(struct ldb_kv_private *ldb_kv, _UNUSED_ struct ldb_val key, struct ldb_val val, @@ -3572,8 +3584,9 @@ static int re_pack(struct ldb_kv_private *ldb_kv, */ if ((!ctx->normal_record_seen) && (!ldb_dn_is_special(msg->dn))) { ldb_debug(ldb, LDB_DEBUG_ALWAYS_LOG, - "Repacking database with format %#010x", - ldb_kv->pack_format_version); + "Repacking database from v%u to v%u format", + displayable_pack_version(ctx->old_version), + displayable_pack_version(ldb_kv->pack_format_version)); ctx->normal_record_seen = true; } -- 2.17.1 From 18fb5fb911d098701e4af732977310e48ed403a9 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Wed, 31 Jul 2019 10:33:49 +1200 Subject: [PATCH 079/376] ldb: Log the partition we're repacking Firstly, with Samba AD this looks a little weird because we log the same message 5 times (once for every partition). If we log that we're doing this to records in different partitions, hopefully someone with a little Samba knowledge can figure out what's going on. Secondly, the info about what partitions are actually changing might be useful. E.g. if we hit a fatal error repacking the 3rd partition, and the transaction doesn't abort properly, then it would be useful to know what partitions were repacked and which ones weren't. There doesn't appear to be a useful name for the partition (ldb_kv->kv_ops->name() doesn't seem any more intelligible to a user), so just log the first record that we update. We can use that to infer the partition database). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit ee6537c29e747206ee607493ce15d4532fb670c8) --- lib/ldb/ldb_key_value/ldb_kv_index.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index 27454d3f734..d955517ea10 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -3584,9 +3584,11 @@ static int re_pack(struct ldb_kv_private *ldb_kv, */ if ((!ctx->normal_record_seen) && (!ldb_dn_is_special(msg->dn))) { ldb_debug(ldb, LDB_DEBUG_ALWAYS_LOG, - "Repacking database from v%u to v%u format", + "Repacking database from v%u to v%u format " + "(first record %s)", displayable_pack_version(ctx->old_version), - displayable_pack_version(ldb_kv->pack_format_version)); + displayable_pack_version(ldb_kv->pack_format_version), + ldb_dn_get_linearized(msg->dn)); ctx->normal_record_seen = true; } -- 2.17.1 From d819a1c20503484b3624aeda426a37912a4ee692 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Wed, 31 Jul 2019 10:54:29 +1200 Subject: [PATCH 080/376] ldb: Free memory when repacking database The msg for each database record is allocated on the module context, but never freed. The module seems like it could be a long-running context (as the database would normally get repacked by the samba executable). Even if it's not a proper leak, it shouldn't hurt to cleanup the memory. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam Autobuild-User(master): Garming Sam Autobuild-Date(master): Tue Aug 20 04:57:10 UTC 2019 on sn-devel-184 (cherry picked from commit b6516dbd24df8c78ed909c7ef9058b0844abb917) --- lib/ldb/ldb_key_value/ldb_kv_index.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index d955517ea10..0853b28fe40 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -3599,6 +3599,7 @@ static int re_pack(struct ldb_kv_private *ldb_kv, ctx->count); } + talloc_free(msg); return 0; } -- 2.17.1 From 80bd467affbda1d962f4deb3caa8a42c6531425d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 23 Aug 2019 12:02:05 +1200 Subject: [PATCH 081/376] ldb: Release ldb 2.0.6 * log database repack so users know what is happening BUG: https://bugzilla.samba.org/show_bug.cgi?id=14059 Signed-off-by: Andrew Bartlett Reviewed-by: Garming Sam --- lib/ldb/ABI/ldb-2.0.6.sigs | 283 ++++++++++++++++++++++++++++++ lib/ldb/ABI/pyldb-util-2.0.6.sigs | 2 + lib/ldb/wscript | 2 +- 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 lib/ldb/ABI/ldb-2.0.6.sigs create mode 100644 lib/ldb/ABI/pyldb-util-2.0.6.sigs diff --git a/lib/ldb/ABI/ldb-2.0.6.sigs b/lib/ldb/ABI/ldb-2.0.6.sigs new file mode 100644 index 00000000000..5049dc64ce1 --- /dev/null +++ b/lib/ldb/ABI/ldb-2.0.6.sigs @@ -0,0 +1,283 @@ +ldb_add: int (struct ldb_context *, const struct ldb_message *) +ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *) +ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...) +ldb_attr_casefold: char *(TALLOC_CTX *, const char *) +ldb_attr_dn: int (const char *) +ldb_attr_in_list: int (const char * const *, const char *) +ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *) +ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *) +ldb_base64_decode: int (char *) +ldb_base64_encode: char *(TALLOC_CTX *, const char *, int) +ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *) +ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val) +ldb_binary_encode_string: char *(TALLOC_CTX *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t) +ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t) +ldb_check_critical_controls: int (struct ldb_control **) +ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **) +ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *) +ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *) +ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_debug_add: void (struct ldb_context *, const char *, ...) +ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level) +ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_delete: int (struct ldb_context *, struct ldb_dn *) +ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *) +ldb_dn_check_special: bool (struct ldb_dn *, const char *) +ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val) +ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *) +ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *) +ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *) +ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *) +ldb_dn_get_casefold: const char *(struct ldb_dn *) +ldb_dn_get_comp_num: int (struct ldb_dn *) +ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int) +ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int) +ldb_dn_get_extended_comp_num: int (struct ldb_dn *) +ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int) +ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_get_rdn_name: const char *(struct ldb_dn *) +ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *) +ldb_dn_has_extended: bool (struct ldb_dn *) +ldb_dn_is_null: bool (struct ldb_dn *) +ldb_dn_is_special: bool (struct ldb_dn *) +ldb_dn_is_valid: bool (struct ldb_dn *) +ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_minimise: bool (struct ldb_dn *) +ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...) +ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_extended_components: void (struct ldb_dn *) +ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val) +ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *) +ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *) +ldb_dn_validate: bool (struct ldb_dn *) +ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *) +ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int) +ldb_errstring: const char *(struct ldb_context *) +ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **) +ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_create_perms: unsigned int (struct ldb_context *) +ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_event_context: struct tevent_context *(struct ldb_context *) +ldb_get_flags: unsigned int (struct ldb_context *) +ldb_get_opaque: void *(struct ldb_context *, const char *) +ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *) +ldb_global_init: int (void) +ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *) +ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **) +ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *) +ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *) +ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **) +ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *) +ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *) +ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_map_add: int (struct ldb_module *, struct ldb_request *) +ldb_map_delete: int (struct ldb_module *, struct ldb_request *) +ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *) +ldb_map_modify: int (struct ldb_module *, struct ldb_request *) +ldb_map_rename: int (struct ldb_module *, struct ldb_request *) +ldb_map_search: int (struct ldb_module *, struct ldb_request *) +ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *) +ldb_match_msg_objectclass: int (const struct ldb_message *, const char *) +ldb_mod_register_control: int (struct ldb_module *, const char *) +ldb_modify: int (struct ldb_context *, const struct ldb_message *) +ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *) +ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +ldb_module_flags: uint32_t (struct ldb_context *) +ldb_module_get_ctx: struct ldb_context *(struct ldb_module *) +ldb_module_get_name: const char *(struct ldb_module *) +ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *) +ldb_module_get_private: void *(struct ldb_module *) +ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *) +ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +ldb_module_next: struct ldb_module *(struct ldb_module *) +ldb_module_popt_options: struct poptOption **(struct ldb_context *) +ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **) +ldb_module_send_referral: int (struct ldb_request *, char *) +ldb_module_set_next: void (struct ldb_module *, struct ldb_module *) +ldb_module_set_private: void (struct ldb_module *, void *) +ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_modules_load: int (const char *, const char *) +ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int) +ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **) +ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...) +ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *) +ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *) +ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *) +ldb_msg_add_string: int (struct ldb_message *, const char *, const char *) +ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **) +ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *) +ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *) +ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *) +ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **) +ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *) +ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *) +ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double) +ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t) +ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *) +ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int) +ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t) +ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t) +ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *) +ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *) +ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *) +ldb_msg_new: struct ldb_message *(TALLOC_CTX *) +ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **) +ldb_msg_remove_attr: void (struct ldb_message *, const char *) +ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *) +ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *) +ldb_msg_sort_elements: void (struct ldb_message *) +ldb_next_del_trans: int (struct ldb_module *) +ldb_next_end_trans: int (struct ldb_module *) +ldb_next_init: int (struct ldb_module *) +ldb_next_prepare_commit: int (struct ldb_module *) +ldb_next_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: int (struct ldb_module *) +ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_start_trans: int (struct ldb_module *) +ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_options_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *) +ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *) +ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *) +ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *) +ldb_register_hook: int (ldb_hook_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *) +ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *) +ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *) +ldb_req_get_custom_flags: uint32_t (struct ldb_request *) +ldb_req_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_trusted: void (struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t) +ldb_req_set_location: void (struct ldb_request *, const char *) +ldb_request: int (struct ldb_context *, struct ldb_request *) +ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_done: int (struct ldb_request *, int) +ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *) +ldb_request_get_status: int (struct ldb_request *) +ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***) +ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *) +ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *) +ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *) +ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *) +ldb_schema_attribute_remove: void (struct ldb_context *, const char *) +ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int) +ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *) +ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...) +ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *) +ldb_set_create_perms: void (struct ldb_context *, unsigned int) +ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *) +ldb_set_debug_stderr: int (struct ldb_context *) +ldb_set_default_dns: void (struct ldb_context *) +ldb_set_errstring: void (struct ldb_context *, const char *) +ldb_set_event_context: void (struct ldb_context *, struct tevent_context *) +ldb_set_flags: void (struct ldb_context *, unsigned int) +ldb_set_modules_dir: void (struct ldb_context *, const char *) +ldb_set_opaque: int (struct ldb_context *, const char *, void *) +ldb_set_require_private_event_context: void (struct ldb_context *) +ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int) +ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *) +ldb_set_utf8_default: void (struct ldb_context *) +ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t)) +ldb_setup_wellknown_attributes: int (struct ldb_context *) +ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *) +ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_strerror: const char *(int) +ldb_string_to_time: time_t (const char *) +ldb_string_utc_to_time: time_t (const char *) +ldb_timestring: char *(TALLOC_CTX *, time_t) +ldb_timestring_utc: char *(TALLOC_CTX *, time_t) +ldb_transaction_cancel: int (struct ldb_context *) +ldb_transaction_cancel_noerr: int (struct ldb_context *) +ldb_transaction_commit: int (struct ldb_context *) +ldb_transaction_prepare_commit: int (struct ldb_context *) +ldb_transaction_start: int (struct ldb_context *) +ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *) +ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *) +ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *) +ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_string_cmp: int (const struct ldb_val *, const char *) +ldb_val_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/lib/ldb/ABI/pyldb-util-2.0.6.sigs b/lib/ldb/ABI/pyldb-util-2.0.6.sigs new file mode 100644 index 00000000000..74d6719d2bc --- /dev/null +++ b/lib/ldb/ABI/pyldb-util-2.0.6.sigs @@ -0,0 +1,2 @@ +pyldb_Dn_FromDn: PyObject *(struct ldb_dn *) +pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **) diff --git a/lib/ldb/wscript b/lib/ldb/wscript index 61f6b664902..a63a6c2171f 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'ldb' -VERSION = '2.0.5' +VERSION = '2.0.6' import sys, os -- 2.17.1 From 756bea42e0c051580330680dd6350cefb102a21c Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 12 Aug 2019 16:11:13 +1000 Subject: [PATCH 082/376] ctdb-tools: Drop 'o' option from getopts command Commit 90de5e0594b9180226b9a13293afe31f18576b3d remove the processing for this option but forgot to remove it from the getopts command. Versions of ShellCheck >= 0.4.7 warn on this, so it is worth fixing. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14086 RN: Fix onnode test failure with ShellCheck >= 0.4.7 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 758962a0d435fa595e3917b860a8fd266d122550) --- ctdb/tools/onnode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctdb/tools/onnode b/ctdb/tools/onnode index e143ba2d4d4..d6595fff4aa 100755 --- a/ctdb/tools/onnode +++ b/ctdb/tools/onnode @@ -72,7 +72,7 @@ parse_options () { local opt - while getopts "cf:hno:pqvPi?" opt ; do + while getopts "cf:hnpqvPi?" opt ; do case "$opt" in c) current=true ;; f) ctdb_nodes_file="$OPTARG" ;; -- 2.17.1 From 900cc33accf07f5c80c941b7dc74e374185e2808 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 14 Aug 2019 10:06:00 +0200 Subject: [PATCH 083/376] vfs_default: use correct flag in vfswrap_fs_file_id Luckily using the wrong flag ST_EX_IFLAG_CALCULATED_ITIME currently results in the same semantics as using the correct ST_EX_IFLAG_CALCULATED_FILE_ID, as in vfs_default the non-calculated file_id is based a non-calculated itime. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14089 RN: vfs_default: use correct flag in vfswrap_fs_file_id Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 442a7c9ad8b020b2e88e41fea8a911d244023cb9) --- source3/modules/vfs_default.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 84c22bb1517..5095f65b746 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -2733,7 +2733,7 @@ static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle, { uint64_t file_id; - if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) { + if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) { return psbuf->st_ex_file_id; } -- 2.17.1 From 53f828969d0fde5cabd61e5a260a887c53fdc872 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 14 Aug 2019 10:11:15 +0200 Subject: [PATCH 084/376] vfs_glusterfs: initialize st_ex_file_id, st_ex_itime and st_ex_iflags BUG: https://bugzilla.samba.org/show_bug.cgi?id=14090 RN: vfs_glusterfs: initialize st_ex_file_id, st_ex_itime and st_ex_iflags Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Aug 16 01:07:23 UTC 2019 on sn-devel-184 (cherry picked from commit 3ee78cc9979a72ebbe65a16c60967a1735a0d208) --- source3/modules/vfs_glusterfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 95f32f9d0a6..56e03014fea 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -74,12 +74,16 @@ static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src) dst->st_ex_btime.tv_sec = src->st_mtime; dst->st_ex_blksize = src->st_blksize; dst->st_ex_blocks = src->st_blocks; + dst->st_ex_file_id = dst->st_ex_ino; + dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID; #ifdef STAT_HAVE_NSEC dst->st_ex_atime.tv_nsec = src->st_atime_nsec; dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec; dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec; dst->st_ex_btime.tv_nsec = src->st_mtime_nsec; #endif + dst->st_ex_itime = dst->st_ex_btime; + dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_ITIME; } /* pre-opened glfs_t */ -- 2.17.1 From c6d784debd8a9f9e576397a628de1e581aa7adbc Mon Sep 17 00:00:00 2001 From: Anoop C S Date: Mon, 5 Aug 2019 10:45:01 +0530 Subject: [PATCH 085/376] vfs_glusterfs: Enable profiling for file system operations BUG: https://bugzilla.samba.org/show_bug.cgi?id=14093 Signed-off-by: Anoop C S Reviewed-by: Guenther Deschner Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Aug 20 19:25:28 UTC 2019 on sn-devel-184 Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Mon Aug 26 08:51:55 UTC 2019 on sn-devel-184 --- source3/modules/vfs_glusterfs.c | 337 +++++++++++++++++++++++++++----- 1 file changed, 288 insertions(+), 49 deletions(-) diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 56e03014fea..483d28397f8 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -492,12 +492,16 @@ static DIR *vfs_gluster_opendir(struct vfs_handle_struct *handle, { glfs_fd_t *fd; + START_PROFILE(syscall_opendir); + fd = glfs_opendir(handle->data, smb_fname->base_name); if (fd == NULL) { DEBUG(0, ("glfs_opendir(%s) failed: %s\n", smb_fname->base_name, strerror(errno))); } + END_PROFILE(syscall_opendir); + return (DIR *) fd; } @@ -532,7 +536,13 @@ static DIR *vfs_gluster_fdopendir(struct vfs_handle_struct *handle, static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp) { - return glfs_closedir((void *)dirp); + int ret; + + START_PROFILE(syscall_closedir); + ret = glfs_closedir((void *)dirp); + END_PROFILE(syscall_closedir); + + return ret; } static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle, @@ -543,6 +553,7 @@ static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle, struct stat stat; struct dirent *dirent = 0; + START_PROFILE(syscall_readdir); if (sbuf != NULL) { ret = glfs_readdirplus_r((void *)dirp, &stat, (void *)direntbuf, &dirent); @@ -551,6 +562,7 @@ static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle, } if ((ret < 0) || (dirent == NULL)) { + END_PROFILE(syscall_readdir); return NULL; } @@ -558,36 +570,59 @@ static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle, smb_stat_ex_from_stat(sbuf, &stat); } + END_PROFILE(syscall_readdir); return dirent; } static long vfs_gluster_telldir(struct vfs_handle_struct *handle, DIR *dirp) { - return glfs_telldir((void *)dirp); + long ret; + + START_PROFILE(syscall_telldir); + ret = glfs_telldir((void *)dirp); + END_PROFILE(syscall_telldir); + + return ret; } static void vfs_gluster_seekdir(struct vfs_handle_struct *handle, DIR *dirp, long offset) { + START_PROFILE(syscall_seekdir); glfs_seekdir((void *)dirp, offset); + END_PROFILE(syscall_seekdir); } static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle, DIR *dirp) { + START_PROFILE(syscall_rewinddir); glfs_seekdir((void *)dirp, 0); + END_PROFILE(syscall_rewinddir); } static int vfs_gluster_mkdir(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, mode_t mode) { - return glfs_mkdir(handle->data, smb_fname->base_name, mode); + int ret; + + START_PROFILE(syscall_mkdir); + ret = glfs_mkdir(handle->data, smb_fname->base_name, mode); + END_PROFILE(syscall_mkdir); + + return ret; } static int vfs_gluster_rmdir(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname) { - return glfs_rmdir(handle->data, smb_fname->base_name); + int ret; + + START_PROFILE(syscall_rmdir); + ret = glfs_rmdir(handle->data, smb_fname->base_name); + END_PROFILE(syscall_rmdir); + + return ret; } static int vfs_gluster_open(struct vfs_handle_struct *handle, @@ -597,8 +632,11 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle, glfs_fd_t *glfd; glfs_fd_t **p_tmp; + START_PROFILE(syscall_open); + p_tmp = VFS_ADD_FSP_EXTENSION(handle, fsp, glfs_fd_t *, NULL); if (p_tmp == NULL) { + END_PROFILE(syscall_open); errno = ENOMEM; return -1; } @@ -613,12 +651,15 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle, } if (glfd == NULL) { + END_PROFILE(syscall_open); /* no extension destroy_fn, so no need to save errno */ VFS_REMOVE_FSP_EXTENSION(handle, fsp); return -1; } *p_tmp = glfd; + + END_PROFILE(syscall_open); /* An arbitrary value for error reporting, so you know its us. */ return 13371337; } @@ -626,31 +667,50 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle, static int vfs_gluster_close(struct vfs_handle_struct *handle, files_struct *fsp) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + int ret; + glfs_fd_t *glfd = NULL; + + START_PROFILE(syscall_close); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_close); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } VFS_REMOVE_FSP_EXTENSION(handle, fsp); - return glfs_close(glfd); + + ret = glfs_close(glfd); + END_PROFILE(syscall_close); + + return ret; } static ssize_t vfs_gluster_pread(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n, off_t offset) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + ssize_t ret; + glfs_fd_t *glfd = NULL; + + START_PROFILE_BYTES(syscall_pread, n); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE_BYTES(syscall_pread); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } #ifdef HAVE_GFAPI_VER_7_6 - return glfs_pread(glfd, data, n, offset, 0, NULL); + ret = glfs_pread(glfd, data, n, offset, 0, NULL); #else - return glfs_pread(glfd, data, n, offset, 0); + ret = glfs_pread(glfd, data, n, offset, 0); #endif + END_PROFILE_BYTES(syscall_pread); + + return ret; } struct glusterfs_aio_state; @@ -665,6 +725,7 @@ struct glusterfs_aio_state { bool cancelled; struct vfs_aio_state vfs_aio_state; struct timespec start; + SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes); }; static int aio_wrapper_destructor(struct glusterfs_aio_wrapper *wrap) @@ -706,6 +767,8 @@ static void aio_glusterfs_done(glfs_fd_t *fd, ssize_t ret, void *data) } state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start); + SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes); + /* * Write the state pointer to glusterfs_aio_state to the * pipe, so we can call tevent_req_done() from the main thread, @@ -878,6 +941,8 @@ static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct */ tevent_req_defer_callback(req, ev); + SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p, + state->profile_bytes, n); PROFILE_TIMESTAMP(&state->start); ret = glfs_pread_async(glfd, data, n, offset, 0, aio_glusterfs_done, state); @@ -927,6 +992,8 @@ static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct */ tevent_req_defer_callback(req, ev); + SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p, + state->profile_bytes, n); PROFILE_TIMESTAMP(&state->start); ret = glfs_pwrite_async(glfd, data, n, offset, 0, aio_glusterfs_done, state); @@ -972,29 +1039,47 @@ static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n, off_t offset) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + ssize_t ret; + glfs_fd_t *glfd = NULL; + + START_PROFILE_BYTES(syscall_pwrite, n); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE_BYTES(syscall_pwrite); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } #ifdef HAVE_GFAPI_VER_7_6 - return glfs_pwrite(glfd, data, n, offset, 0, NULL, NULL); + ret = glfs_pwrite(glfd, data, n, offset, 0, NULL, NULL); #else - return glfs_pwrite(glfd, data, n, offset, 0); + ret = glfs_pwrite(glfd, data, n, offset, 0); #endif + END_PROFILE_BYTES(syscall_pwrite); + + return ret; } static off_t vfs_gluster_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + off_t ret = 0; + glfs_fd_t *glfd = NULL; + + START_PROFILE(syscall_lseek); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_lseek); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } - return glfs_lseek(glfd, offset, whence); + ret = glfs_lseek(glfd, offset, whence); + END_PROFILE(syscall_lseek); + + return ret; } static ssize_t vfs_gluster_sendfile(struct vfs_handle_struct *handle, int tofd, @@ -1018,8 +1103,14 @@ static int vfs_gluster_rename(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { - return glfs_rename(handle->data, smb_fname_src->base_name, - smb_fname_dst->base_name); + int ret; + + START_PROFILE(syscall_rename); + ret = glfs_rename(handle->data, smb_fname_src->base_name, + smb_fname_dst->base_name); + END_PROFILE(syscall_rename); + + return ret; } static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct @@ -1058,6 +1149,8 @@ static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct */ tevent_req_defer_callback(req, ev); + SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p, + state->profile_bytes, 0); PROFILE_TIMESTAMP(&state->start); ret = glfs_fsync_async(glfd, aio_glusterfs_done, state); if (ret < 0) { @@ -1082,6 +1175,7 @@ static int vfs_gluster_stat(struct vfs_handle_struct *handle, struct stat st; int ret; + START_PROFILE(syscall_stat); ret = glfs_stat(handle->data, smb_fname->base_name, &st); if (ret == 0) { smb_stat_ex_from_stat(&smb_fname->st, &st); @@ -1090,6 +1184,8 @@ static int vfs_gluster_stat(struct vfs_handle_struct *handle, DEBUG(0, ("glfs_stat(%s) failed: %s\n", smb_fname->base_name, strerror(errno))); } + END_PROFILE(syscall_stat); + return ret; } @@ -1098,9 +1194,13 @@ static int vfs_gluster_fstat(struct vfs_handle_struct *handle, { struct stat st; int ret; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + glfs_fd_t *glfd = NULL; + + START_PROFILE(syscall_fstat); + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_fstat); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } @@ -1113,6 +1213,8 @@ static int vfs_gluster_fstat(struct vfs_handle_struct *handle, DEBUG(0, ("glfs_fstat(%d) failed: %s\n", fsp->fh->fd, strerror(errno))); } + END_PROFILE(syscall_fstat); + return ret; } @@ -1122,6 +1224,7 @@ static int vfs_gluster_lstat(struct vfs_handle_struct *handle, struct stat st; int ret; + START_PROFILE(syscall_lstat); ret = glfs_lstat(handle->data, smb_fname->base_name, &st); if (ret == 0) { smb_stat_ex_from_stat(&smb_fname->st, &st); @@ -1130,6 +1233,8 @@ static int vfs_gluster_lstat(struct vfs_handle_struct *handle, DEBUG(0, ("glfs_lstat(%s) failed: %s\n", smb_fname->base_name, strerror(errno))); } + END_PROFILE(syscall_lstat); + return ret; } @@ -1137,33 +1242,59 @@ static uint64_t vfs_gluster_get_alloc_size(struct vfs_handle_struct *handle, files_struct *fsp, const SMB_STRUCT_STAT *sbuf) { - return sbuf->st_ex_blocks * 512; + uint64_t ret; + + START_PROFILE(syscall_get_alloc_size); + ret = sbuf->st_ex_blocks * 512; + END_PROFILE(syscall_get_alloc_size); + + return ret; } static int vfs_gluster_unlink(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname) { - return glfs_unlink(handle->data, smb_fname->base_name); + int ret; + + START_PROFILE(syscall_unlink); + ret = glfs_unlink(handle->data, smb_fname->base_name); + END_PROFILE(syscall_unlink); + + return ret; } static int vfs_gluster_chmod(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, mode_t mode) { - return glfs_chmod(handle->data, smb_fname->base_name, mode); + int ret; + + START_PROFILE(syscall_chmod); + ret = glfs_chmod(handle->data, smb_fname->base_name, mode); + END_PROFILE(syscall_chmod); + + return ret; } static int vfs_gluster_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + int ret; + glfs_fd_t *glfd = NULL; + START_PROFILE(syscall_fchmod); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_fchmod); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } - return glfs_fchmod(glfd, mode); + ret = glfs_fchmod(glfd, mode); + END_PROFILE(syscall_fchmod); + + return ret; } static int vfs_gluster_chown(struct vfs_handle_struct *handle, @@ -1171,19 +1302,34 @@ static int vfs_gluster_chown(struct vfs_handle_struct *handle, uid_t uid, gid_t gid) { - return glfs_chown(handle->data, smb_fname->base_name, uid, gid); + int ret; + + START_PROFILE(syscall_chown); + ret = glfs_chown(handle->data, smb_fname->base_name, uid, gid); + END_PROFILE(syscall_chown); + + return ret; } static int vfs_gluster_fchown(struct vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + int ret; + glfs_fd_t *glfd = NULL; + + START_PROFILE(syscall_fchown); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_fchown); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } - return glfs_fchown(glfd, uid, gid); + ret = glfs_fchown(glfd, uid, gid); + END_PROFILE(syscall_fchown); + + return ret; } static int vfs_gluster_lchown(struct vfs_handle_struct *handle, @@ -1191,13 +1337,25 @@ static int vfs_gluster_lchown(struct vfs_handle_struct *handle, uid_t uid, gid_t gid) { - return glfs_lchown(handle->data, smb_fname->base_name, uid, gid); + int ret; + + START_PROFILE(syscall_lchown); + ret = glfs_lchown(handle->data, smb_fname->base_name, uid, gid); + END_PROFILE(syscall_lchown); + + return ret; } static int vfs_gluster_chdir(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname) { - return glfs_chdir(handle->data, smb_fname->base_name); + int ret; + + START_PROFILE(syscall_chdir); + ret = glfs_chdir(handle->data, smb_fname->base_name); + END_PROFILE(syscall_chdir); + + return ret; } static struct smb_filename *vfs_gluster_getwd(struct vfs_handle_struct *handle, @@ -1207,12 +1365,17 @@ static struct smb_filename *vfs_gluster_getwd(struct vfs_handle_struct *handle, char *ret; struct smb_filename *smb_fname = NULL; + START_PROFILE(syscall_getwd); + cwd = SMB_CALLOC_ARRAY(char, PATH_MAX); if (cwd == NULL) { + END_PROFILE(syscall_getwd); return NULL; } ret = glfs_getcwd(handle->data, cwd, PATH_MAX - 1); + END_PROFILE(syscall_getwd); + if (ret == NULL) { SAFE_FREE(cwd); return NULL; @@ -1230,8 +1393,11 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, struct smb_file_time *ft) { + int ret = -1; struct timespec times[2]; + START_PROFILE(syscall_ntimes); + if (null_timespec(ft->atime)) { times[0].tv_sec = smb_fname->st.st_ex_atime.tv_sec; times[0].tv_nsec = smb_fname->st.st_ex_atime.tv_nsec; @@ -1252,26 +1418,39 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle, &smb_fname->st.st_ex_atime) == 0) && (timespec_compare(×[1], &smb_fname->st.st_ex_mtime) == 0)) { + END_PROFILE(syscall_ntimes); return 0; } - return glfs_utimens(handle->data, smb_fname->base_name, times); + ret = glfs_utimens(handle->data, smb_fname->base_name, times); + END_PROFILE(syscall_ntimes); + + return ret; } static int vfs_gluster_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset) { - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + int ret; + glfs_fd_t *glfd = NULL; + + START_PROFILE(syscall_ftruncate); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_ftruncate); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } #ifdef HAVE_GFAPI_VER_7_6 - return glfs_ftruncate(glfd, offset, NULL, NULL); + ret = glfs_ftruncate(glfd, offset, NULL, NULL); #else - return glfs_ftruncate(glfd, offset); + ret = glfs_ftruncate(glfd, offset); #endif + END_PROFILE(syscall_ftruncate); + + return ret; } static int vfs_gluster_fallocate(struct vfs_handle_struct *handle, @@ -1279,10 +1458,16 @@ static int vfs_gluster_fallocate(struct vfs_handle_struct *handle, uint32_t mode, off_t offset, off_t len) { + int ret; #ifdef HAVE_GFAPI_VER_6 + glfs_fd_t *glfd = NULL; int keep_size, punch_hole; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + + START_PROFILE(syscall_fallocate); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_fallocate); DBG_ERR("Failed to fetch gluster fd\n"); return -1; } @@ -1292,19 +1477,22 @@ static int vfs_gluster_fallocate(struct vfs_handle_struct *handle, mode &= ~(VFS_FALLOCATE_FL_KEEP_SIZE|VFS_FALLOCATE_FL_PUNCH_HOLE); if (mode != 0) { + END_PROFILE(syscall_fallocate); errno = ENOTSUP; return -1; } if (punch_hole) { - return glfs_discard(glfd, offset, len); + ret = glfs_discard(glfd, offset, len); } - return glfs_fallocate(glfd, keep_size, offset, len); + ret = glfs_fallocate(glfd, keep_size, offset, len); + END_PROFILE(syscall_fallocate); #else errno = ENOTSUP; - return -1; + ret = -1; #endif + return ret; } static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handle, @@ -1313,9 +1501,13 @@ static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handl { char *result = NULL; struct smb_filename *result_fname = NULL; - char *resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1); + char *resolved_path = NULL; + START_PROFILE(syscall_realpath); + + resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1); if (resolved_path == NULL) { + END_PROFILE(syscall_realpath); errno = ENOMEM; return NULL; } @@ -1328,6 +1520,8 @@ static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handl } SAFE_FREE(resolved_path); + END_PROFILE(syscall_realpath); + return result_fname; } @@ -1337,10 +1531,16 @@ static bool vfs_gluster_lock(struct vfs_handle_struct *handle, { struct flock flock = { 0, }; int ret; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + glfs_fd_t *glfd = NULL; + bool ok = false; + + START_PROFILE(syscall_fcntl_lock); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { DBG_ERR("Failed to fetch gluster fd\n"); - return false; + ok = false; + goto out; } flock.l_type = type; @@ -1355,17 +1555,25 @@ static bool vfs_gluster_lock(struct vfs_handle_struct *handle, /* lock query, true if someone else has locked */ if ((ret != -1) && (flock.l_type != F_UNLCK) && - (flock.l_pid != 0) && (flock.l_pid != getpid())) - return true; + (flock.l_pid != 0) && (flock.l_pid != getpid())) { + ok = true; + goto out; + } /* not me */ - return false; + ok = false; + goto out; } if (ret == -1) { - return false; + ok = false; + goto out; } - return true; + ok = true; +out: + END_PROFILE(syscall_fcntl_lock); + + return ok; } static int vfs_gluster_kernel_flock(struct vfs_handle_struct *handle, @@ -1389,8 +1597,13 @@ static bool vfs_gluster_getlock(struct vfs_handle_struct *handle, { struct flock flock = { 0, }; int ret; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + glfs_fd_t *glfd = NULL; + + START_PROFILE(syscall_fcntl_getlock); + + glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { + END_PROFILE(syscall_fcntl_getlock); DBG_ERR("Failed to fetch gluster fd\n"); return false; } @@ -1404,6 +1617,7 @@ static bool vfs_gluster_getlock(struct vfs_handle_struct *handle, ret = glfs_posix_lock(glfd, F_GETLK, &flock); if (ret == -1) { + END_PROFILE(syscall_fcntl_getlock); return false; } @@ -1411,6 +1625,7 @@ static bool vfs_gluster_getlock(struct vfs_handle_struct *handle, *poffset = flock.l_start; *pcount = flock.l_len; *ppid = flock.l_pid; + END_PROFILE(syscall_fcntl_getlock); return true; } @@ -1419,9 +1634,15 @@ static int vfs_gluster_symlink(struct vfs_handle_struct *handle, const char *link_target, const struct smb_filename *new_smb_fname) { - return glfs_symlink(handle->data, + int ret; + + START_PROFILE(syscall_symlink); + ret = glfs_symlink(handle->data, link_target, new_smb_fname->base_name); + END_PROFILE(syscall_symlink); + + return ret; } static int vfs_gluster_readlink(struct vfs_handle_struct *handle, @@ -1429,16 +1650,28 @@ static int vfs_gluster_readlink(struct vfs_handle_struct *handle, char *buf, size_t bufsiz) { - return glfs_readlink(handle->data, smb_fname->base_name, buf, bufsiz); + int ret; + + START_PROFILE(syscall_readlink); + ret = glfs_readlink(handle->data, smb_fname->base_name, buf, bufsiz); + END_PROFILE(syscall_readlink); + + return ret; } static int vfs_gluster_link(struct vfs_handle_struct *handle, const struct smb_filename *old_smb_fname, const struct smb_filename *new_smb_fname) { - return glfs_link(handle->data, + int ret; + + START_PROFILE(syscall_link); + ret = glfs_link(handle->data, old_smb_fname->base_name, new_smb_fname->base_name); + END_PROFILE(syscall_link); + + return ret; } static int vfs_gluster_mknod(struct vfs_handle_struct *handle, @@ -1446,7 +1679,13 @@ static int vfs_gluster_mknod(struct vfs_handle_struct *handle, mode_t mode, SMB_DEV_T dev) { - return glfs_mknod(handle->data, smb_fname->base_name, mode, dev); + int ret; + + START_PROFILE(syscall_mknod); + ret = glfs_mknod(handle->data, smb_fname->base_name, mode, dev); + END_PROFILE(syscall_mknod); + + return ret; } static int vfs_gluster_chflags(struct vfs_handle_struct *handle, @@ -1505,7 +1744,7 @@ static ssize_t vfs_gluster_getxattr(struct vfs_handle_struct *handle, size_t size) { return glfs_getxattr(handle->data, smb_fname->base_name, - name, value, size); + name, value, size); } static ssize_t vfs_gluster_fgetxattr(struct vfs_handle_struct *handle, -- 2.17.1 From d8ba147db50feeeedbeb738a2be24c28e3790a45 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 18 May 2019 11:28:54 +0200 Subject: [PATCH 086/376] vfs:glusterfs_fuse: ensure fileids are constant across nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of adding a new gluster-specific mode to the fileid module, this patches provides a fileid algorithm as part of the glusterfs_fuse vfs module. This can not be configured further, simply adding the glusterfs_fuse vfs module to the vfs objects configuration will enable the new fileid mode. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13972 Signed-off-by: Michael Adam Signed-off-by: Guenther Deschner Autobuild-User(master): Günther Deschner Autobuild-Date(master): Sat Jul 13 22:54:56 UTC 2019 on sn-devel-184 (cherry picked from commit 5522aa1a4c34ee1a1e81db73cf41594bb10bd989) --- docs-xml/manpages/vfs_glusterfs_fuse.8.xml | 8 + source3/modules/vfs_glusterfs_fuse.c | 193 ++++++++++++++++++++- 2 files changed, 200 insertions(+), 1 deletion(-) diff --git a/docs-xml/manpages/vfs_glusterfs_fuse.8.xml b/docs-xml/manpages/vfs_glusterfs_fuse.8.xml index b9f7f42c6f2..f2aa624353e 100644 --- a/docs-xml/manpages/vfs_glusterfs_fuse.8.xml +++ b/docs-xml/manpages/vfs_glusterfs_fuse.8.xml @@ -48,6 +48,14 @@ case of an exisiting filename. + + Furthermore, this module implements a substitute file-id + mechanism. The default file-id mechanism is not working + correctly for gluster fuse mount re-exports, so in order to + avoid data loss, users exporting gluster fuse mounts with + Samba should enable this module. + + This module can be combined with other modules, but it should be the last module in the vfs objects diff --git a/source3/modules/vfs_glusterfs_fuse.c b/source3/modules/vfs_glusterfs_fuse.c index 51515aa0df4..c621f9abf8e 100644 --- a/source3/modules/vfs_glusterfs_fuse.c +++ b/source3/modules/vfs_glusterfs_fuse.c @@ -59,10 +59,201 @@ static int vfs_gluster_fuse_get_real_filename(struct vfs_handle_struct *handle, return 0; } +struct device_mapping_entry { + SMB_DEV_T device; /* the local device, for reference */ + uint64_t mapped_device; /* the mapped device */ +}; + +struct vfs_glusterfs_fuse_handle_data { + unsigned num_mapped_devices; + struct device_mapping_entry *mapped_devices; +}; + +/* a 64 bit hash, based on the one in tdb, copied from vfs_fileied */ +static uint64_t vfs_glusterfs_fuse_uint64_hash(const uint8_t *s, size_t len) +{ + uint64_t value; /* Used to compute the hash value. */ + uint32_t i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AFLL * len, i=0; i < len; i++) + value = (value + (((uint64_t)s[i]) << (i*5 % 24))); + + return (1103515243LL * value + 12345LL); +} + +static void vfs_glusterfs_fuse_load_devices( + struct vfs_glusterfs_fuse_handle_data *data) +{ + FILE *f; + struct mntent *m; + + data->num_mapped_devices = 0; + TALLOC_FREE(data->mapped_devices); + + f = setmntent("/etc/mtab", "r"); + if (!f) { + return; + } + + while ((m = getmntent(f))) { + struct stat st; + char *p; + uint64_t mapped_device; + + if (stat(m->mnt_dir, &st) != 0) { + /* TODO: log? */ + continue; + } + + /* strip the host part off of the fsname */ + p = strrchr(m->mnt_fsname, ':'); + if (p == NULL) { + p = m->mnt_fsname; + } else { + /* TODO: consider the case of '' ? */ + p++; + } + + mapped_device = vfs_glusterfs_fuse_uint64_hash( + (const uint8_t *)p, + strlen(p)); + + data->mapped_devices = talloc_realloc(data, + data->mapped_devices, + struct device_mapping_entry, + data->num_mapped_devices + 1); + if (data->mapped_devices == NULL) { + goto nomem; + } + + data->mapped_devices[data->num_mapped_devices].device = + st.st_dev; + data->mapped_devices[data->num_mapped_devices].mapped_device = + mapped_device; + + data->num_mapped_devices++; + } + + endmntent(f); + return; + +nomem: + data->num_mapped_devices = 0; + TALLOC_FREE(data->mapped_devices); + + endmntent(f); + return; +} + +static int vfs_glusterfs_fuse_map_device_cached( + struct vfs_glusterfs_fuse_handle_data *data, + SMB_DEV_T device, + uint64_t *mapped_device) +{ + unsigned i; + + for (i = 0; i < data->num_mapped_devices; i++) { + if (data->mapped_devices[i].device == device) { + *mapped_device = data->mapped_devices[i].mapped_device; + return 0; + } + } + + return -1; +} + +static int vfs_glusterfs_fuse_map_device( + struct vfs_glusterfs_fuse_handle_data *data, + SMB_DEV_T device, + uint64_t *mapped_device) +{ + int ret; + + ret = vfs_glusterfs_fuse_map_device_cached(data, device, mapped_device); + if (ret == 0) { + return 0; + } + + vfs_glusterfs_fuse_load_devices(data); + + ret = vfs_glusterfs_fuse_map_device_cached(data, device, mapped_device); + + return ret; +} + +static struct file_id vfs_glusterfs_fuse_file_id_create( + struct vfs_handle_struct *handle, + const SMB_STRUCT_STAT *sbuf) +{ + struct vfs_glusterfs_fuse_handle_data *data; + struct file_id id; + uint64_t mapped_device; + int ret; + + ZERO_STRUCT(id); + + id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf); + + SMB_VFS_HANDLE_GET_DATA(handle, data, + struct vfs_glusterfs_fuse_handle_data, + return id); + + ret = vfs_glusterfs_fuse_map_device(data, sbuf->st_ex_dev, + &mapped_device); + if (ret == 0) { + id.devid = mapped_device; + } else { + DBG_WARNING("Failed to map device [%jx], falling back to " + "standard file_id [%jx]", + (uintmax_t)sbuf->st_ex_dev, + (uintmax_t)id.devid); + } + + DBG_DEBUG("Returning dev [%jx] inode [%jx]\n", + (uintmax_t)id.devid, (uintmax_t)id.inode); + + return id; +} + +static int vfs_glusterfs_fuse_connect(struct vfs_handle_struct *handle, + const char *service, const char *user) +{ + struct vfs_glusterfs_fuse_handle_data *data; + int ret = SMB_VFS_NEXT_CONNECT(handle, service, user); + + if (ret < 0) { + return ret; + } + + data = talloc_zero(handle->conn, struct vfs_glusterfs_fuse_handle_data); + if (data == NULL) { + DBG_ERR("talloc_zero() failed.\n"); + SMB_VFS_NEXT_DISCONNECT(handle); + return -1; + } + + /* + * Fill the cache in the tree connect, so that the first file/dir access + * has chances of being fast... + */ + vfs_glusterfs_fuse_load_devices(data); + + SMB_VFS_HANDLE_SET_DATA(handle, data, NULL, + struct vfs_glusterfs_fuse_handle_data, + return -1); + + DBG_DEBUG("vfs_glusterfs_fuse_connect(): connected to service[%s]\n", + service); + + return 0; +} + struct vfs_fn_pointers glusterfs_fuse_fns = { - /* File Operations */ + .connect_fn = vfs_glusterfs_fuse_connect, .get_real_filename_fn = vfs_gluster_fuse_get_real_filename, + .file_id_create_fn = vfs_glusterfs_fuse_file_id_create, }; static_decl_vfs; -- 2.17.1 From 53b0fd2216dfd93ae0379f48e712294137e9b5b6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 1 Aug 2019 00:47:29 +0200 Subject: [PATCH 087/376] vfs:glusterfs_fuse: build only if we have setmntent() FreeBSD and other platforms that don't have setmntent() and friends can not compile this module. This patch lets changes the build to only compile this module if the setmntent() function is found. This is the a follow-up fix to the actual fix for bug #13972. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13972 Signed-off-by: Michael Adam Reviewed-by: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Thu Aug 1 09:49:04 UTC 2019 on sn-devel-184 (cherry picked from commit f258cfaa1d07af6ac6e996006f6e59955cfe34ce) --- source3/wscript | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source3/wscript b/source3/wscript index ff72a173a4b..4a3e75605e7 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1713,7 +1713,6 @@ main() { vfs_media_harmony vfs_unityed_media vfs_fruit vfs_shell_snap vfs_commit vfs_worm vfs_crossrename vfs_linux_xfs_sgid vfs_time_audit vfs_offline vfs_virusfilter - vfs_glusterfs_fuse ''')) default_shared_modules.extend(TO_LIST('auth_script idmap_tdb2 idmap_script')) # these have broken dependencies @@ -1775,6 +1774,9 @@ main() { if conf.CONFIG_SET('HAVE_GLUSTERFS'): default_shared_modules.extend(TO_LIST('vfs_glusterfs')) + if conf.CONFIG_SET('HAVE_SETMNTENT'): + default_shared_modules.extend(TO_LIST('vfs_glusterfs_fuse')) + if conf.CONFIG_SET('HAVE_VXFS'): default_shared_modules.extend(TO_LIST('vfs_vxfs')) -- 2.17.1 From 0b4a99c22f5e72d2bc6e2770b070e964866db148 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Thu, 8 Aug 2019 16:20:44 +1000 Subject: [PATCH 088/376] ctdb-daemon: Add function ctdb_ip_to_node() This is the core logic from ctdb_ip_to_pnn(), so re-implement that that function using ctdb_ip_to_node(). Something similar (ctdb_ip_to_nodeid()) was recently removed in commit 010c1d77cd7e192b1fff39b7b91fccbdbbf4a786 because it wasn't required. Now there is a use case. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 3acb8e9d1c854b577d6be282257269df83055d31) --- ctdb/include/ctdb_private.h | 2 ++ ctdb/server/ctdb_server.c | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 2bcc7c94156..1e9619faddf 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -831,6 +831,8 @@ void ctdb_stop_recoverd(struct ctdb_context *ctdb); int ctdb_set_transport(struct ctdb_context *ctdb, const char *transport); +struct ctdb_node *ctdb_ip_to_node(struct ctdb_context *ctdb, + const ctdb_sock_addr *nodeip); uint32_t ctdb_ip_to_pnn(struct ctdb_context *ctdb, const ctdb_sock_addr *nodeip); diff --git a/ctdb/server/ctdb_server.c b/ctdb/server/ctdb_server.c index dcd761a2961..9724d1fe0a8 100644 --- a/ctdb/server/ctdb_server.c +++ b/ctdb/server/ctdb_server.c @@ -45,9 +45,9 @@ int ctdb_set_transport(struct ctdb_context *ctdb, const char *transport) return 0; } -/* Return the PNN for nodeip, CTDB_UNKNOWN_PNN if nodeip is invalid */ -uint32_t ctdb_ip_to_pnn(struct ctdb_context *ctdb, - const ctdb_sock_addr *nodeip) +/* Return the node structure for nodeip, NULL if nodeip is invalid */ +struct ctdb_node *ctdb_ip_to_node(struct ctdb_context *ctdb, + const ctdb_sock_addr *nodeip) { unsigned int nodeid; @@ -56,11 +56,25 @@ uint32_t ctdb_ip_to_pnn(struct ctdb_context *ctdb, continue; } if (ctdb_same_ip(&ctdb->nodes[nodeid]->address, nodeip)) { - return ctdb->nodes[nodeid]->pnn; + return ctdb->nodes[nodeid]; } } - return CTDB_UNKNOWN_PNN; + return NULL; +} + +/* Return the PNN for nodeip, CTDB_UNKNOWN_PNN if nodeip is invalid */ +uint32_t ctdb_ip_to_pnn(struct ctdb_context *ctdb, + const ctdb_sock_addr *nodeip) +{ + struct ctdb_node *node; + + node = ctdb_ip_to_node(ctdb, nodeip); + if (node == NULL) { + return CTDB_UNKNOWN_PNN; + } + + return node->pnn; } /* Load a nodes list file into a nodes array */ -- 2.17.1 From 4cf26ff2ec350db6b3ad5fa08dea602b3b842baf Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Fri, 9 Aug 2019 15:06:34 +1000 Subject: [PATCH 089/376] ctdb-tcp: Rename fd -> out_fd in_fd is coming soon. Fix coding style violations in the affected and adjacent lines. Modernise some debug macros and make them more consistent (e.g. drop logging of errno when strerror(errno) is already logged. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit c06620169fc178ea6db2631f03edf008285d8cf2) --- ctdb/tcp/ctdb_tcp.h | 2 +- ctdb/tcp/tcp_connect.c | 97 +++++++++++++++++++++++++----------------- ctdb/tcp/tcp_init.c | 22 ++++++---- 3 files changed, 72 insertions(+), 49 deletions(-) diff --git a/ctdb/tcp/ctdb_tcp.h b/ctdb/tcp/ctdb_tcp.h index 0a998c94da4..acd343fb8f3 100644 --- a/ctdb/tcp/ctdb_tcp.h +++ b/ctdb/tcp/ctdb_tcp.h @@ -39,7 +39,7 @@ struct ctdb_incoming { state associated with one tcp node */ struct ctdb_tcp_node { - int fd; + int out_fd; struct ctdb_queue *out_queue; struct tevent_fd *connect_fde; struct tevent_timer *connect_te; diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index d757abdf26c..4253f3bef7c 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -50,9 +50,9 @@ void ctdb_tcp_stop_connection(struct ctdb_node *node) talloc_free(tnode->connect_fde); tnode->connect_fde = NULL; tnode->connect_te = NULL; - if (tnode->fd != -1) { - close(tnode->fd); - tnode->fd = -1; + if (tnode->out_fd != -1) { + close(tnode->out_fd); + tnode->out_fd = -1; } } @@ -93,12 +93,13 @@ static void ctdb_node_connect_write(struct tevent_context *ev, int error = 0; socklen_t len = sizeof(error); int one = 1; + int ret; talloc_free(tnode->connect_te); tnode->connect_te = NULL; - if (getsockopt(tnode->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0 || - error != 0) { + ret = getsockopt(tnode->out_fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (ret != 0 || error != 0) { ctdb_tcp_stop_connection(node); tnode->connect_te = tevent_add_timer(ctdb->ev, tnode, timeval_current_ofs(1, 0), @@ -109,19 +110,28 @@ static void ctdb_node_connect_write(struct tevent_context *ev, talloc_free(tnode->connect_fde); tnode->connect_fde = NULL; - if (setsockopt(tnode->fd,IPPROTO_TCP,TCP_NODELAY,(char *)&one,sizeof(one)) == -1) { - DEBUG(DEBUG_WARNING, ("Failed to set TCP_NODELAY on fd - %s\n", - strerror(errno))); + ret = setsockopt(tnode->out_fd, + IPPROTO_TCP, + TCP_NODELAY, + (char *)&one, + sizeof(one)); + if (ret == -1) { + DBG_WARNING("Failed to set TCP_NODELAY on fd - %s\n", + strerror(errno)); } - if (setsockopt(tnode->fd,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one)) == -1) { - DEBUG(DEBUG_WARNING, ("Failed to set KEEPALIVE on fd - %s\n", - strerror(errno))); + ret = setsockopt(tnode->out_fd, + SOL_SOCKET, + SO_KEEPALIVE,(char *)&one, + sizeof(one)); + if (ret == -1) { + DBG_WARNING("Failed to set KEEPALIVE on fd - %s\n", + strerror(errno)); } - ctdb_queue_set_fd(tnode->out_queue, tnode->fd); + ctdb_queue_set_fd(tnode->out_queue, tnode->out_fd); /* the queue subsystem now owns this fd */ - tnode->fd = -1; + tnode->out_fd = -1; /* tell the ctdb layer we are connected */ node->ctdb->upcalls->node_connected(node); @@ -149,26 +159,24 @@ void ctdb_tcp_node_connect(struct tevent_context *ev, struct tevent_timer *te, sock_out = node->address; - tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - if (tnode->fd == -1) { - DEBUG(DEBUG_ERR, (__location__ " Failed to create socket\n")); + tnode->out_fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + if (tnode->out_fd == -1) { + DBG_ERR("Failed to create socket\n"); return; } - ret = set_blocking(tnode->fd, false); + ret = set_blocking(tnode->out_fd, false); if (ret != 0) { - DEBUG(DEBUG_ERR, - (__location__ - " failed to set socket non-blocking (%s)\n", - strerror(errno))); - close(tnode->fd); - tnode->fd = -1; + DBG_ERR("Failed to set socket non-blocking (%s)\n", + strerror(errno)); + close(tnode->out_fd); + tnode->out_fd = -1; return; } - set_close_on_exec(tnode->fd); + set_close_on_exec(tnode->out_fd); - DEBUG(DEBUG_DEBUG, (__location__ " Created TCP SOCKET FD:%d\n", tnode->fd)); + DBG_DEBUG("Created TCP SOCKET FD:%d\n", tnode->out_fd); /* Bind our side of the socketpair to the same address we use to listen * on incoming CTDB traffic. @@ -197,39 +205,48 @@ void ctdb_tcp_node_connect(struct tevent_context *ev, struct tevent_timer *te, default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock_in.sa.sa_family)); - close(tnode->fd); - tnode->fd = -1; + close(tnode->out_fd); + tnode->out_fd = -1; return; } - if (bind(tnode->fd, (struct sockaddr *)&sock_in, sockin_size) == -1) { - DEBUG(DEBUG_ERR, (__location__ " Failed to bind socket %s(%d)\n", - strerror(errno), errno)); - close(tnode->fd); - tnode->fd = -1; + ret = bind(tnode->out_fd, (struct sockaddr *)&sock_in, sockin_size); + if (ret == -1) { + DBG_ERR("Failed to bind socket (%s)\n", strerror(errno)); + close(tnode->out_fd); + tnode->out_fd = -1; return; } - if (connect(tnode->fd, (struct sockaddr *)&sock_out, sockout_size) != 0 && - errno != EINPROGRESS) { + ret = connect(tnode->out_fd, + (struct sockaddr *)&sock_out, + sockout_size); + if (ret != 0 && errno != EINPROGRESS) { ctdb_tcp_stop_connection(node); - tnode->connect_te = tevent_add_timer(ctdb->ev, tnode, + tnode->connect_te = tevent_add_timer(ctdb->ev, + tnode, timeval_current_ofs(1, 0), - ctdb_tcp_node_connect, node); + ctdb_tcp_node_connect, + node); return; } /* non-blocking connect - wait for write event */ - tnode->connect_fde = tevent_add_fd(node->ctdb->ev, tnode, tnode->fd, + tnode->connect_fde = tevent_add_fd(node->ctdb->ev, + tnode, + tnode->out_fd, TEVENT_FD_WRITE|TEVENT_FD_READ, - ctdb_node_connect_write, node); + ctdb_node_connect_write, + node); /* don't give it long to connect - retry in one second. This ensures that we find a node is up quickly (tcp normally backs off a syn reply delay by quite a lot) */ - tnode->connect_te = tevent_add_timer(ctdb->ev, tnode, + tnode->connect_te = tevent_add_timer(ctdb->ev, + tnode, timeval_current_ofs(1, 0), - ctdb_tcp_node_connect, node); + ctdb_tcp_node_connect, + node); } /* diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index 87d628aba93..6b1299f32b5 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -38,16 +38,16 @@ static int tnode_destructor(struct ctdb_tcp_node *tnode) { // struct ctdb_node *node = talloc_find_parent_bytype(tnode, struct ctdb_node); - if (tnode->fd != -1) { - close(tnode->fd); - tnode->fd = -1; + if (tnode->out_fd != -1) { + close(tnode->out_fd); + tnode->out_fd = -1; } return 0; } /* - initialise tcp portion of a ctdb node + initialise tcp portion of a ctdb node */ static int ctdb_tcp_add_node(struct ctdb_node *node) { @@ -55,13 +55,19 @@ static int ctdb_tcp_add_node(struct ctdb_node *node) tnode = talloc_zero(node, struct ctdb_tcp_node); CTDB_NO_MEMORY(node->ctdb, tnode); - tnode->fd = -1; + tnode->out_fd = -1; node->private_data = tnode; talloc_set_destructor(tnode, tnode_destructor); - tnode->out_queue = ctdb_queue_setup(node->ctdb, node, tnode->fd, CTDB_TCP_ALIGNMENT, - ctdb_tcp_tnode_cb, node, "to-node-%s", node->name); - + tnode->out_queue = ctdb_queue_setup(node->ctdb, + node, + tnode->out_fd, + CTDB_TCP_ALIGNMENT, + ctdb_tcp_tnode_cb, + node, + "to-node-%s", + node->name); + return 0; } -- 2.17.1 From bf39d0cff16cd240ceddb3cb88183ad61e667ac2 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Fri, 9 Aug 2019 15:29:36 +1000 Subject: [PATCH 090/376] ctdb-tcp: Move incoming fd and queue into struct ctdb_tcp_node This makes it easy to track both incoming and outgoing connectivity states. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit c68b6f96f26664459187ab2fbd56767fb31767e0) --- ctdb/tcp/ctdb_tcp.h | 14 ++++----- ctdb/tcp/tcp_connect.c | 64 +++++++++++++++++++++++++++--------------- ctdb/tcp/tcp_init.c | 8 ++++++ ctdb/tcp/tcp_io.c | 9 ++++-- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/ctdb/tcp/ctdb_tcp.h b/ctdb/tcp/ctdb_tcp.h index acd343fb8f3..9a615fc6393 100644 --- a/ctdb/tcp/ctdb_tcp.h +++ b/ctdb/tcp/ctdb_tcp.h @@ -26,23 +26,19 @@ struct ctdb_tcp { int listen_fd; }; -/* - state associated with an incoming connection -*/ -struct ctdb_incoming { - struct ctdb_context *ctdb; - int fd; - struct ctdb_queue *queue; -}; - /* state associated with one tcp node */ struct ctdb_tcp_node { int out_fd; struct ctdb_queue *out_queue; + struct tevent_fd *connect_fde; struct tevent_timer *connect_te; + + struct ctdb_context *ctdb; + int in_fd; + struct ctdb_queue *in_queue; }; diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 4253f3bef7c..866454f3d29 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -262,8 +262,8 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, ctdb_sock_addr addr; socklen_t len; int fd; - uint32_t pnn; - struct ctdb_incoming *in; + struct ctdb_node *node; + struct ctdb_tcp_node *tnode; int one = 1; int ret; @@ -273,41 +273,61 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, if (fd == -1) return; smb_set_close_on_exec(fd); - pnn = ctdb_ip_to_pnn(ctdb, &addr); - - if (pnn == CTDB_UNKNOWN_PNN) { + node = ctdb_ip_to_node(ctdb, &addr); + if (node == NULL) { D_ERR("Refused connection from unknown node %s\n", ctdb_addr_to_str(&addr)); close(fd); return; } - in = talloc_zero(ctcp, struct ctdb_incoming); - in->fd = fd; - in->ctdb = ctdb; + tnode = talloc_get_type_abort(node->private_data, + struct ctdb_tcp_node); + if (tnode == NULL) { + /* This can't happen - see ctdb_tcp_initialise() */ + DBG_ERR("INTERNAL ERROR setting up connection from node %s\n", + ctdb_addr_to_str(&addr)); + close(fd); + return; + } - ret = set_blocking(in->fd, false); + ret = set_blocking(fd, false); if (ret != 0) { - DEBUG(DEBUG_ERR, - (__location__ - " failed to set socket non-blocking (%s)\n", - strerror(errno))); - close(in->fd); - in->fd = -1; + DBG_ERR("Failed to set socket non-blocking (%s)\n", + strerror(errno)); + close(fd); return; } - set_close_on_exec(in->fd); + set_close_on_exec(fd); - DEBUG(DEBUG_DEBUG, (__location__ " Created SOCKET FD:%d to incoming ctdb connection\n", fd)); + DBG_DEBUG("Created SOCKET FD:%d to incoming ctdb connection\n", fd); - if (setsockopt(in->fd,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one)) == -1) { - DEBUG(DEBUG_WARNING, ("Failed to set KEEPALIVE on fd - %s\n", - strerror(errno))); + ret = setsockopt(fd, + SOL_SOCKET, + SO_KEEPALIVE, + (char *)&one, + sizeof(one)); + if (ret == -1) { + DBG_WARNING("Failed to set KEEPALIVE on fd - %s\n", + strerror(errno)); + } + + tnode->in_queue = ctdb_queue_setup(ctdb, + tnode, + fd, + CTDB_TCP_ALIGNMENT, + ctdb_tcp_read_cb, + tnode, + "ctdbd-%s", + ctdb_addr_to_str(&addr)); + if (tnode->in_queue == NULL) { + DBG_ERR("Failed to set up incoming queue\n"); + close(fd); + return; } - in->queue = ctdb_queue_setup(ctdb, in, in->fd, CTDB_TCP_ALIGNMENT, - ctdb_tcp_read_cb, in, "ctdbd-%s", ctdb_addr_to_str(&addr)); + tnode->in_fd = fd; } diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index 6b1299f32b5..d4b42b0d0f2 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -43,6 +43,11 @@ static int tnode_destructor(struct ctdb_tcp_node *tnode) tnode->out_fd = -1; } + if (tnode->in_fd != -1) { + close(tnode->in_fd); + tnode->in_fd = -1; + } + return 0; } @@ -56,6 +61,9 @@ static int ctdb_tcp_add_node(struct ctdb_node *node) CTDB_NO_MEMORY(node->ctdb, tnode); tnode->out_fd = -1; + tnode->in_fd = -1; + tnode->ctdb = node->ctdb; + node->private_data = tnode; talloc_set_destructor(tnode, tnode_destructor); diff --git a/ctdb/tcp/tcp_io.c b/ctdb/tcp/tcp_io.c index 0eb8e25eea3..be4558b16ea 100644 --- a/ctdb/tcp/tcp_io.c +++ b/ctdb/tcp/tcp_io.c @@ -37,7 +37,8 @@ */ void ctdb_tcp_read_cb(uint8_t *data, size_t cnt, void *args) { - struct ctdb_incoming *in = talloc_get_type(args, struct ctdb_incoming); + struct ctdb_tcp_node *tnode = talloc_get_type_abort( + args, struct ctdb_tcp_node); struct ctdb_req_header *hdr = (struct ctdb_req_header *)data; if (data == NULL) { @@ -69,11 +70,13 @@ void ctdb_tcp_read_cb(uint8_t *data, size_t cnt, void *args) } /* tell the ctdb layer above that we have a packet */ - in->ctdb->upcalls->recv_pkt(in->ctdb, data, cnt); + tnode->ctdb->upcalls->recv_pkt(tnode->ctdb, data, cnt); return; failed: - TALLOC_FREE(in); + TALLOC_FREE(tnode->in_queue); + close(tnode->in_fd); + tnode->in_fd = -1; TALLOC_FREE(data); } -- 2.17.1 From 1ef2ffbab865b80c90a69b5899285c0b7409c26d Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Thu, 15 Aug 2019 15:45:16 +1000 Subject: [PATCH 091/376] ctdb-tcp: Use TALLOC_FREE() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit d80d9edb4dc107b15a35a39e5c966a3eaed6453a) --- ctdb/tcp/tcp_connect.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 866454f3d29..16d75481050 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -46,10 +46,8 @@ void ctdb_tcp_stop_connection(struct ctdb_node *node) node->private_data, struct ctdb_tcp_node); ctdb_queue_set_fd(tnode->out_queue, -1); - talloc_free(tnode->connect_te); - talloc_free(tnode->connect_fde); - tnode->connect_fde = NULL; - tnode->connect_te = NULL; + TALLOC_FREE(tnode->connect_te); + TALLOC_FREE(tnode->connect_fde); if (tnode->out_fd != -1) { close(tnode->out_fd); tnode->out_fd = -1; -- 2.17.1 From 6668733c306896a779c707acdd9912efcf52c0da Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Thu, 15 Aug 2019 15:57:31 +1000 Subject: [PATCH 092/376] ctdb-tcp: Create outbound queue when the connection becomes writable Since commit ddd97553f0a8bfaada178ec4a7460d76fa21f079 ctdb_queue_send() doesn't queue a packet if the connection isn't yet established (i.e. when fd == -1). So, don't bother creating the outbound queue during initialisation but create it when the connection becomes writable. Now the presence of the queue indicates that the outbound connection is up. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 7f4854d9643a096a6d8a354fcd27b7c6ed24a75e) --- ctdb/tcp/tcp_connect.c | 23 ++++++++++++++++++++--- ctdb/tcp/tcp_init.c | 9 --------- ctdb/tcp/tcp_io.c | 5 +++++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 16d75481050..4374242015c 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -44,8 +44,8 @@ void ctdb_tcp_stop_connection(struct ctdb_node *node) { struct ctdb_tcp_node *tnode = talloc_get_type( node->private_data, struct ctdb_tcp_node); - - ctdb_queue_set_fd(tnode->out_queue, -1); + + TALLOC_FREE(tnode->out_queue); TALLOC_FREE(tnode->connect_te); TALLOC_FREE(tnode->connect_fde); if (tnode->out_fd != -1) { @@ -126,7 +126,24 @@ static void ctdb_node_connect_write(struct tevent_context *ev, strerror(errno)); } - ctdb_queue_set_fd(tnode->out_queue, tnode->out_fd); + tnode->out_queue = ctdb_queue_setup(node->ctdb, + tnode, + tnode->out_fd, + CTDB_TCP_ALIGNMENT, + ctdb_tcp_tnode_cb, + node, + "to-node-%s", + node->name); + if (tnode->out_queue == NULL) { + DBG_ERR("Failed to set up outgoing queue\n"); + ctdb_tcp_stop_connection(node); + tnode->connect_te = tevent_add_timer(ctdb->ev, + tnode, + timeval_current_ofs(1, 0), + ctdb_tcp_node_connect, + node); + return; + } /* the queue subsystem now owns this fd */ tnode->out_fd = -1; diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index d4b42b0d0f2..a9cb9b36a01 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -67,15 +67,6 @@ static int ctdb_tcp_add_node(struct ctdb_node *node) node->private_data = tnode; talloc_set_destructor(tnode, tnode_destructor); - tnode->out_queue = ctdb_queue_setup(node->ctdb, - node, - tnode->out_fd, - CTDB_TCP_ALIGNMENT, - ctdb_tcp_tnode_cb, - node, - "to-node-%s", - node->name); - return 0; } diff --git a/ctdb/tcp/tcp_io.c b/ctdb/tcp/tcp_io.c index be4558b16ea..e33ed44048e 100644 --- a/ctdb/tcp/tcp_io.c +++ b/ctdb/tcp/tcp_io.c @@ -87,5 +87,10 @@ int ctdb_tcp_queue_pkt(struct ctdb_node *node, uint8_t *data, uint32_t length) { struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data, struct ctdb_tcp_node); + if (tnode->out_queue == NULL) { + DBG_DEBUG("No outgoing connection, dropping packet\n"); + return 0; + } + return ctdb_queue_send(tnode->out_queue, data, length); } -- 2.17.1 From adb19f17cd1a778a6ee58d7f4658b9f27ea087de Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Fri, 9 Aug 2019 15:33:05 +1000 Subject: [PATCH 093/376] ctdb-tcp: Only mark a node connected if both directions are up Nodes are currently marked as up if the outgoing connection is established. However, if the incoming connection is not yet established then this node could send a request where the replying node can not queue its reply. Wait until both directions are up before marking a node as connected. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 8c98c10f242bc722beffc711e85c0e4f2e74cd57) --- ctdb/tcp/tcp_connect.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 4374242015c..fd635b9abf2 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -148,8 +148,14 @@ static void ctdb_node_connect_write(struct tevent_context *ev, /* the queue subsystem now owns this fd */ tnode->out_fd = -1; - /* tell the ctdb layer we are connected */ - node->ctdb->upcalls->node_connected(node); + /* + * Mark the node to which this connection has been established + * as connected, but only if the corresponding listening + * socket is also connected + */ + if (tnode->in_fd != -1) { + node->ctdb->upcalls->node_connected(node); + } } @@ -343,7 +349,15 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, } tnode->in_fd = fd; -} + + /* + * Mark the connecting node as connected, but only if the + * corresponding outbound connected is also up + */ + if (tnode->out_queue != NULL) { + node->ctdb->upcalls->node_connected(node); + } + } /* -- 2.17.1 From 240ad91944d617d33b85aaeeed2a57ecf1ce9c67 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 13 Aug 2019 17:08:43 +1000 Subject: [PATCH 094/376] ctdb-tcp: Mark node as disconnected if incoming connection goes away To make it easy to pass the node data to the upcall, the private data for ctdb_tcp_read_cb() needs to be changed from tnode to node. RN: Avoid marking a node as connected before it can receive packets BUG: https://bugzilla.samba.org/show_bug.cgi?id=14084 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Martin Schwenke Autobuild-Date(master): Fri Aug 16 22:50:35 UTC 2019 on sn-devel-184 (cherry picked from commit 73c850eda4209b688a169aeeb20c453b738cbb35) --- ctdb/tcp/tcp_connect.c | 2 +- ctdb/tcp/tcp_io.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index fd635b9abf2..6123380ca9f 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -339,7 +339,7 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, fd, CTDB_TCP_ALIGNMENT, ctdb_tcp_read_cb, - tnode, + node, "ctdbd-%s", ctdb_addr_to_str(&addr)); if (tnode->in_queue == NULL) { diff --git a/ctdb/tcp/tcp_io.c b/ctdb/tcp/tcp_io.c index e33ed44048e..e8ebff887e1 100644 --- a/ctdb/tcp/tcp_io.c +++ b/ctdb/tcp/tcp_io.c @@ -37,8 +37,9 @@ */ void ctdb_tcp_read_cb(uint8_t *data, size_t cnt, void *args) { + struct ctdb_node *node = talloc_get_type_abort(args, struct ctdb_node); struct ctdb_tcp_node *tnode = talloc_get_type_abort( - args, struct ctdb_tcp_node); + node->private_data, struct ctdb_tcp_node); struct ctdb_req_header *hdr = (struct ctdb_req_header *)data; if (data == NULL) { @@ -77,6 +78,8 @@ failed: TALLOC_FREE(tnode->in_queue); close(tnode->in_fd); tnode->in_fd = -1; + node->ctdb->upcalls->node_dead(node); + TALLOC_FREE(data); } -- 2.17.1 From 093973899580c2fd1a95d067ff695388b7bdc4f8 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 19 Aug 2019 21:47:03 +1000 Subject: [PATCH 095/376] ctdb-daemon: Factor out new function ctdb_node_become_inactive() This is a superset of ctdb_local_node_got_banned() so will replace that function, and will also be used in the NODE_STOP control. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14087 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit a42bcaabb63722411bee52b80cbfc795593defbc) --- ctdb/include/ctdb_private.h | 2 ++ ctdb/server/ctdb_recover.c | 43 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 1e9619faddf..d9d13fad358 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -819,6 +819,8 @@ int32_t ctdb_control_recd_ping(struct ctdb_context *ctdb); int32_t ctdb_control_set_recmaster(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata); +void ctdb_node_become_inactive(struct ctdb_context *ctdb); + int32_t ctdb_control_stop_node(struct ctdb_context *ctdb); int32_t ctdb_control_continue_node(struct ctdb_context *ctdb); diff --git a/ctdb/server/ctdb_recover.c b/ctdb/server/ctdb_recover.c index 343728839c1..df60a4cb9c0 100644 --- a/ctdb/server/ctdb_recover.c +++ b/ctdb/server/ctdb_recover.c @@ -1420,6 +1420,49 @@ int32_t ctdb_control_set_recmaster(struct ctdb_context *ctdb, uint32_t opcode, T return 0; } +void ctdb_node_become_inactive(struct ctdb_context *ctdb) +{ + struct ctdb_db_context *ctdb_db; + + D_WARNING("Making node INACTIVE\n"); + + /* + * Do not service database calls - reset generation to invalid + * so this node ignores any REQ/REPLY CALL/DMASTER + */ + ctdb->vnn_map->generation = INVALID_GENERATION; + for (ctdb_db = ctdb->db_list; ctdb_db != NULL; ctdb_db = ctdb_db->next) { + ctdb_db->generation = INVALID_GENERATION; + } + + /* + * Although this bypasses the control, the only thing missing + * is the deferred drop of all public IPs, which isn't + * necessary because they are dropped below + */ + if (ctdb->recovery_mode != CTDB_RECOVERY_ACTIVE) { + D_NOTICE("Recovery mode set to ACTIVE\n"); + ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE; + } + + /* + * Initiate database freeze - this will be scheduled for + * immediate execution and will be in progress long before the + * calling control returns + */ + ctdb_daemon_send_control(ctdb, + ctdb->pnn, + 0, + CTDB_CONTROL_FREEZE, + 0, + CTDB_CTRL_FLAG_NOREPLY, + tdb_null, + NULL, + NULL); + + D_NOTICE("Dropping all public IP addresses\n"); + ctdb_release_all_ips(ctdb); +} int32_t ctdb_control_stop_node(struct ctdb_context *ctdb) { -- 2.17.1 From a93c591a11a9b19f4f5df87c76e3b2f3f7404339 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 19 Aug 2019 21:52:57 +1000 Subject: [PATCH 096/376] ctdb-daemon: Switch banning code to use ctdb_node_become_inactive() There's no reason to avoid immediately setting recovery mode to active and initiating freeze of databases. This effectively reverts the following commits: d8f3b490bbb691c9916eed0df5b980c1aef23c85 b4357a79d916b1f8ade8fa78563fbef0ce670aa9 The latter is now implemented using a control, resulting in looser coupling. See also the following commit: f8141e91a693912ea1107a49320e83702a80757a BUG: https://bugzilla.samba.org/show_bug.cgi?id=14087 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 0f5f7b7cf4e970f3f36c5e0b3d09e710fe90801a) --- ctdb/server/ctdb_banning.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctdb/server/ctdb_banning.c b/ctdb/server/ctdb_banning.c index 9cd163645a1..11794dc5b0b 100644 --- a/ctdb/server/ctdb_banning.c +++ b/ctdb/server/ctdb_banning.c @@ -129,7 +129,7 @@ int32_t ctdb_control_set_ban_state(struct ctdb_context *ctdb, TDB_DATA indata) ctdb_ban_node_event, ctdb); if (!already_banned) { - ctdb_local_node_got_banned(ctdb); + ctdb_node_become_inactive(ctdb); } return 0; } -- 2.17.1 From f454db8d960bce78e492cdec344257a2ee094514 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 20 Aug 2019 11:29:42 +1000 Subject: [PATCH 097/376] ctdb-daemon: Drop unused function ctdb_local_node_got_banned() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14087 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 91ac4c13d8472955d1f04bd775ec4b3ff8bf1b61) --- ctdb/include/ctdb_private.h | 1 - ctdb/server/ctdb_banning.c | 24 ------------------------ 2 files changed, 25 deletions(-) diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index d9d13fad358..1f168dae2b8 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -481,7 +481,6 @@ int ctdb_ibw_init(struct ctdb_context *ctdb); /* from ctdb_banning.c */ -void ctdb_local_node_got_banned(struct ctdb_context *ctdb); int32_t ctdb_control_set_ban_state(struct ctdb_context *ctdb, TDB_DATA indata); int32_t ctdb_control_get_ban_state(struct ctdb_context *ctdb, TDB_DATA *outdata); void ctdb_ban_self(struct ctdb_context *ctdb); diff --git a/ctdb/server/ctdb_banning.c b/ctdb/server/ctdb_banning.c index 11794dc5b0b..3c711575e8c 100644 --- a/ctdb/server/ctdb_banning.c +++ b/ctdb/server/ctdb_banning.c @@ -57,30 +57,6 @@ static void ctdb_ban_node_event(struct tevent_context *ev, } } -void ctdb_local_node_got_banned(struct ctdb_context *ctdb) -{ - struct ctdb_db_context *ctdb_db; - - DEBUG(DEBUG_NOTICE, ("This node has been banned - releasing all public " - "IPs and setting the generation to INVALID.\n")); - - /* Reset the generation id to 1 to make us ignore any - REQ/REPLY CALL/DMASTER someone sends to us. - We are now banned so we shouldnt service database calls - anymore. - */ - ctdb->vnn_map->generation = INVALID_GENERATION; - for (ctdb_db = ctdb->db_list; ctdb_db != NULL; ctdb_db = ctdb_db->next) { - ctdb_db->generation = INVALID_GENERATION; - } - - /* Recovery daemon will set the recovery mode ACTIVE and freeze - * databases. - */ - - ctdb_release_all_ips(ctdb); -} - int32_t ctdb_control_set_ban_state(struct ctdb_context *ctdb, TDB_DATA indata) { struct ctdb_ban_state *bantime = (struct ctdb_ban_state *)indata.dptr; -- 2.17.1 From a9d0e0b7bae9005d56222e5952f9fec66cb8f491 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 19 Aug 2019 21:48:04 +1000 Subject: [PATCH 098/376] ctdb-daemon: Make node inactive in the NODE_STOP control Currently some of this is supported by a periodic check in the recovery daemon's main_loop(), which notices the flag change, sets recovery mode active and freezes databases. If STOP_NODE returns immediately then the associated recovery can complete and the node can be continued before databases are actually frozen. Instead, immediately do all of the things that make a node inactive. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14087 RN: Stop "ctdb stop" from completing before freezing databases Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Tue Aug 20 08:32:27 UTC 2019 on sn-devel-184 (cherry picked from commit e9f2e205ee89f4f3d6302cc11b4d0eb2efaf0f53) --- ctdb/server/ctdb_recover.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ctdb/server/ctdb_recover.c b/ctdb/server/ctdb_recover.c index df60a4cb9c0..1654c6d3978 100644 --- a/ctdb/server/ctdb_recover.c +++ b/ctdb/server/ctdb_recover.c @@ -1469,6 +1469,8 @@ int32_t ctdb_control_stop_node(struct ctdb_context *ctdb) DEBUG(DEBUG_ERR, ("Stopping node\n")); ctdb->nodes[ctdb->pnn]->flags |= NODE_FLAGS_STOPPED; + ctdb_node_become_inactive(ctdb); + return 0; } -- 2.17.1 From d61fac0cbe4abe1f90da6aea695690ccdb757765 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 17 Aug 2019 06:59:33 +1200 Subject: [PATCH 099/376] docs: Deprecate "rndc command" for Samba 4.11 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14092 Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider (cherry picked from commit 561e0986ac96c842239b4e8c6509e05c836707b7) --- docs-xml/smbdotconf/domain/rndccommand.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs-xml/smbdotconf/domain/rndccommand.xml b/docs-xml/smbdotconf/domain/rndccommand.xml index d9ac4ea6737..c9a1526c0cd 100644 --- a/docs-xml/smbdotconf/domain/rndccommand.xml +++ b/docs-xml/smbdotconf/domain/rndccommand.xml @@ -1,10 +1,17 @@ + This option is deprecated with Samba 4.11 and will be removed + in future. + This option specifies the path to the name server control utility. + This option is only useful when Samba as an AD DC is + configured with BIND9_FLATFILE for DNS. + The rndc utility should be a part of the bind installation. -- 2.17.1 From aa3ad5c451f38659c1131b20756ad81a903654cb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 23 Aug 2019 21:13:22 +1200 Subject: [PATCH 100/376] WHATSNEW: BIND9_FLATFILE / rndc command deprecated Signed-off-by: Andrew Bartlett Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Aug 28 10:48:10 UTC 2019 on sn-devel-184 --- WHATSNEW.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 6a0cc9d72fd..c273117c72f 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -68,6 +68,20 @@ in the following years. If you have a strong requirement for SMB1 (except for supporting old Linux Kernels), please file a bug at https://bugzilla.samba.org and let us know about the details. +BIND9_FLATFILE deprecated +------------------------- + +The BIND9_FLATFILE DNS backend is deprecated in this release and will +be removed in the future. This was only practically useful on a single +domain controller or under expert care and supervision. + +This release therefore deprecates the "rndc command" smb.conf +parameter, which is used to support this configuration. After writing +out a list of DCs permitted to make changes to the DNS Zone "rndc +command" is called with reload to tell the 'named' server if a DC was +added/removed to to the domain. + + NEW FEATURES/CHANGES ==================== @@ -342,6 +356,7 @@ smb.conf changes web port Removed fruit:zero_file_id Changed default False debug encryption New: dump encryption keys False + rndc command Deprecated KNOWN ISSUES -- 2.17.1 From bcfb7749869241a6a85fedca551ae6a4a4dec4fc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Jul 2019 12:10:35 -0700 Subject: [PATCH 101/376] CVE-2019-10197: smbd: separate out impersonation debug info into a new function. Will be called on elsewhere on successful impersonation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14035 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme Reviewed-by: Stefan Metzmacher --- source3/smbd/uid.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index a4bcb747d37..ce8e8d92131 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -279,6 +279,28 @@ static bool check_user_ok(connection_struct *conn, return(True); } +static void print_impersonation_info(connection_struct *conn) +{ + struct smb_filename *cwdfname = NULL; + + if (!CHECK_DEBUGLVL(DBGLVL_INFO)) { + return; + } + + cwdfname = vfs_GetWd(talloc_tos(), conn); + if (cwdfname == NULL) { + return; + } + + DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n", + (int)getuid(), + (int)geteuid(), + (int)getgid(), + (int)getegid(), + cwdfname->base_name); + TALLOC_FREE(cwdfname); +} + /**************************************************************************** Become the user of a connection number without changing the security context stack, but modify the current_user entries. @@ -415,20 +437,7 @@ static bool change_to_user_internal(connection_struct *conn, current_user.done_chdir = true; } - if (CHECK_DEBUGLVL(DBGLVL_INFO)) { - struct smb_filename *cwdfname = vfs_GetWd(talloc_tos(), conn); - if (cwdfname == NULL) { - return false; - } - DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n", - (int)getuid(), - (int)geteuid(), - (int)getgid(), - (int)getegid(), - cwdfname->base_name); - TALLOC_FREE(cwdfname); - } - + print_impersonation_info(conn); return true; } -- 2.17.1 From ae9bdef5c8a2dea2efca6295799a42ba01c3b98d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jul 2019 17:01:29 +0200 Subject: [PATCH 102/376] CVE-2019-10197: smbd: make sure that change_to_user_internal() always resets current_user.done_chdir We should not leave current_user.done_chdir as true if we didn't call chdir_current_service() with success. This caused problems in when calling vfs_ChDir() in pop_conn_ctx() when chdir_current_service() worked once on one share but later failed on another share. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14035 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- source3/smbd/uid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ce8e8d92131..77a81f60298 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -427,6 +427,7 @@ static bool change_to_user_internal(connection_struct *conn, current_user.conn = conn; current_user.vuid = vuid; current_user.need_chdir = conn->tcon_done; + current_user.done_chdir = false; if (current_user.need_chdir) { ok = chdir_current_service(conn); -- 2.17.1 From d690f6f3c4d82a5ff887df40e2a60a1828eb87eb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 18 Jun 2019 14:04:08 +0200 Subject: [PATCH 103/376] CVE-2019-10197: smbd: make sure we reset current_user.{need,done}_chdir in become_root() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14035 Signed-off-by: Stefan Metzmacher --- source3/smbd/uid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 77a81f60298..50868ba8572 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -624,6 +624,9 @@ void smbd_become_root(void) } push_conn_ctx(); set_root_sec_ctx(); + + current_user.need_chdir = false; + current_user.done_chdir = false; } /* Unbecome the root user */ -- 2.17.1 From 7b39df0f1449024c8b9f2954a63f0b265c4269e8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Jul 2019 17:16:59 +0200 Subject: [PATCH 104/376] CVE-2019-10197: selftest: make fsrvp_share its own independent subdirectory The next patch will otherwise break the fsrvp related tests. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14035 Signed-off-by: Stefan Metzmacher --- selftest/target/Samba3.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 5c327cab543..4cc2938e8fd 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1449,6 +1449,9 @@ sub provision($$$$$$$$$) my $widelinks_linkdir="$shrdir/widelinks_foo"; push(@dirs,$widelinks_linkdir); + my $fsrvp_shrdir="$shrdir/fsrvp"; + push(@dirs,$fsrvp_shrdir); + my $shadow_tstdir="$shrdir/shadow"; push(@dirs,$shadow_tstdir); my $shadow_mntdir="$shadow_tstdir/mount"; @@ -2024,14 +2027,14 @@ sub provision($$$$$$$$$) guest ok = yes [fsrvp_share] - path = $shrdir + path = $fsrvp_shrdir comment = fake shapshots using rsync vfs objects = shell_snap shadow_copy2 shell_snap:check path command = $fake_snap_pl --check shell_snap:create command = $fake_snap_pl --create shell_snap:delete command = $fake_snap_pl --delete # a relative path here fails, the snapshot dir is no longer found - shadow:snapdir = $shrdir/.snapshots + shadow:snapdir = $fsrvp_shrdir/.snapshots [shadow1] path = $shadow_shrdir -- 2.17.1 From a6ff560aa134fb4fa5ceaba83d29aae0bc398f4d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 16 Jul 2019 15:40:38 +0200 Subject: [PATCH 105/376] CVE-2019-10197: test_smbclient_s3.sh: add regression test for the no permission on share root problem BUG: https://bugzilla.samba.org/show_bug.cgi?id=14035 Signed-off-by: Stefan Metzmacher --- selftest/knownfail.d/CVE-2019-10197 | 1 + selftest/target/Samba3.pm | 12 +++++++++ source3/script/tests/test_smbclient_s3.sh | 30 +++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 selftest/knownfail.d/CVE-2019-10197 diff --git a/selftest/knownfail.d/CVE-2019-10197 b/selftest/knownfail.d/CVE-2019-10197 new file mode 100644 index 00000000000..f7056bbf3ad --- /dev/null +++ b/selftest/knownfail.d/CVE-2019-10197 @@ -0,0 +1 @@ +^samba3.blackbox.smbclient_s3.*.noperm.share.regression diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 4cc2938e8fd..9638bb44f08 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1425,6 +1425,9 @@ sub provision($$$$$$$$$) my $ro_shrdir="$shrdir/root-tmp"; push(@dirs,$ro_shrdir); + my $noperm_shrdir="$shrdir/noperm-tmp"; + push(@dirs,$noperm_shrdir); + my $msdfs_shrdir="$shrdir/msdfsshare"; push(@dirs,$msdfs_shrdir); @@ -1495,6 +1498,11 @@ sub provision($$$$$$$$$) chmod 0755, $piddir; + ## + ## Create a directory without permissions to enter + ## + chmod 0000, $noperm_shrdir; + ## ## create ro and msdfs share layout ## @@ -1818,6 +1826,10 @@ sub provision($$$$$$$$$) [ro-tmp] path = $ro_shrdir guest ok = yes +[noperm] + path = $noperm_shrdir + wide links = yes + guest ok = yes [write-list-tmp] path = $shrdir read only = yes diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh index bf033ccd2fb..0bae1d78fac 100755 --- a/source3/script/tests/test_smbclient_s3.sh +++ b/source3/script/tests/test_smbclient_s3.sh @@ -1329,6 +1329,32 @@ EOF fi } +# +# Regression test for CVE-2019-10197 +# we should always get ACCESS_DENIED +# +test_noperm_share_regression() +{ + cmd='$SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/noperm -I $SERVER_IP $LOCAL_ADDARGS -c "ls;ls" 2>&1' + eval echo "$cmd" + out=`eval $cmd` + ret=$? + if [ $ret -eq 0 ] ; then + echo "$out" + echo "failed accessing no perm share should not work" + return 1 + fi + + num=`echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' | wc -l` + if [ "$num" -ne "2" ] ; then + echo "$out" + echo "failed num[$num] - two NT_STATUS_ACCESS_DENIED lines expected" + return 1 + fi + + return 0 +} + # Test smbclient deltree command test_deltree() { @@ -1857,6 +1883,10 @@ testit "follow local symlinks" \ test_local_symlinks || \ failed=`expr $failed + 1` +testit "noperm share regression" \ + test_noperm_share_regression || \ + failed=`expr $failed + 1` + testit "smbclient deltree command" \ test_deltree || \ failed=`expr $failed + 1` -- 2.17.1 From efd6d670997eff81c94b1ece3814b1da2c3705cb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jul 2019 17:02:15 +0200 Subject: [PATCH 106/376] CVE-2019-10197: smbd: split change_to_user_impersonate() out of change_to_user_internal() This makes sure we always call chdir_current_service() even when we still impersonated the user. Which is important in order to run the SMB* request within the correct working directory and only if the user has permissions to enter that directory. It makes sure we always update conn->lastused_count in chdir_current_service() for each request. Note that vfs_ChDir() (called from chdir_current_service()) maintains its own cache and avoids calling SMB_VFS_CHDIR() if possible. It means we still avoid syscalls if we get a multiple requests for the same session/tcon tuple. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14035 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- selftest/knownfail.d/CVE-2019-10197 | 1 - source3/smbd/uid.c | 21 +++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) delete mode 100644 selftest/knownfail.d/CVE-2019-10197 diff --git a/selftest/knownfail.d/CVE-2019-10197 b/selftest/knownfail.d/CVE-2019-10197 deleted file mode 100644 index f7056bbf3ad..00000000000 --- a/selftest/knownfail.d/CVE-2019-10197 +++ /dev/null @@ -1 +0,0 @@ -^samba3.blackbox.smbclient_s3.*.noperm.share.regression diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 50868ba8572..5c39baade5c 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -306,9 +306,9 @@ static void print_impersonation_info(connection_struct *conn) stack, but modify the current_user entries. ****************************************************************************/ -static bool change_to_user_internal(connection_struct *conn, - const struct auth_session_info *session_info, - uint64_t vuid) +static bool change_to_user_impersonate(connection_struct *conn, + const struct auth_session_info *session_info, + uint64_t vuid) { int snum; gid_t gid; @@ -321,7 +321,6 @@ static bool change_to_user_internal(connection_struct *conn, if ((current_user.conn == conn) && (current_user.vuid == vuid) && - (current_user.need_chdir == conn->tcon_done) && (current_user.ut.uid == session_info->unix_token->uid)) { DBG_INFO("Skipping user change - already user\n"); @@ -426,6 +425,20 @@ static bool change_to_user_internal(connection_struct *conn, current_user.conn = conn; current_user.vuid = vuid; + return true; +} + +static bool change_to_user_internal(connection_struct *conn, + const struct auth_session_info *session_info, + uint64_t vuid) +{ + bool ok; + + ok = change_to_user_impersonate(conn, session_info, vuid); + if (!ok) { + return false; + } + current_user.need_chdir = conn->tcon_done; current_user.done_chdir = false; -- 2.17.1 From f04985fe9b54824fb61683c67065da2fdb8f2e1a Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 3 Sep 2019 13:12:16 +0200 Subject: [PATCH 107/376] WHATSNEW: Add release notes for Samba 4.11.0rc3. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index c273117c72f..eece43fcd9e 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,7 +1,7 @@ Release Announcements ===================== -This is the second release candidate of Samba 4.11. This is *not* +This is the third release candidate of Samba 4.11. This is *not* intended for production environments and is designed for testing purposes only. Please report any defects via the Samba bug reporting system at https://bugzilla.samba.org/. @@ -359,6 +359,51 @@ smb.conf changes rndc command Deprecated +CHANGES SINCE 4.11.0rc2 +======================= + +o Michael Adam + * BUG 13972: Different Device Id for GlusterFS FUSE mount is causing data + loss in CTDB cluster. + +o Jeremy Allison + * BUG 14035: CVE-2019-10197: Permissions check deny can allow user to escape + from the share. + +o Andrew Bartlett + * BUG 14059: ldb: Release ldb 2.0.6 (log database repack so users know what + is happening). + * BUG 14092: docs: Deprecate "rndc command" for Samba 4.11. + +o Tim Beale + * BUG 14059: ldb: Free memory when repacking database. + +o Ralph Boehme + * BUG 14089: vfs_default: Use correct flag in vfswrap_fs_file_id. + * BUG 14090: vfs_glusterfs: Initialize st_ex_file_id, st_ex_itime and + st_ex_iflags. + +o Anoop C S + * BUG 14093: vfs_glusterfs: Enable profiling for file system operations. + +o Aaron Haslett + * BUG 14059: Backport sambadowngradedatabase for v4.11. + +o Stefan Metzmacher + * BUG 14035: CVE-2019-10197: Permissions check deny can allow user to escape + from the share. + +o Christof Schmitt + * BUG 14032: vfs_gpfs: Implement special case for denying owner access to + ACL. + +o Martin Schwenke + * BUG 14084: Avoid marking a node as connected before it can receive packets. + * BUG 14086: Fix onnode test failure with ShellCheck >= 0.4.7. + * BUG 14087: ctdb-daemon: Stop "ctdb stop" from completing before freezing + databases. + + KNOWN ISSUES ============ -- 2.17.1 From c1d9e02d06a158f637475ffeca7a6c3f2fb1d773 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 3 Sep 2019 13:12:53 +0200 Subject: [PATCH 108/376] VERSION: Disable GIT_SNAPSHOT for the 4.11.0rc3 release. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 67ae2000ebf..a8742ca9e50 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=3 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 96961348432cd1171b99ea2d8e64d4bc9d897f72 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 3 Sep 2019 13:13:47 +0200 Subject: [PATCH 109/376] VERSION: Bump verison up to 4.11.0rc4... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index a8742ca9e50..ae98c26560f 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=3 +SAMBA_VERSION_RC_RELEASE=4 ######################################################## # To mark SVN snapshots this should be set to 'yes' # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=3 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From a279b8883469b524b18e61c30621fe0dd999e054 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 29 Jul 2019 15:31:55 +1000 Subject: [PATCH 110/376] ctdb-tests: Reformat node_has_status() Re-indent and drop non-POSIX left-parenthesis from case labels. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 52227d19735a3305ad633672c70385f443f222f0) --- ctdb/tests/scripts/integration.bash | 94 +++++++++++++++-------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/ctdb/tests/scripts/integration.bash b/ctdb/tests/scripts/integration.bash index 30725c48e53..e2f238d93d4 100644 --- a/ctdb/tests/scripts/integration.bash +++ b/ctdb/tests/scripts/integration.bash @@ -311,53 +311,55 @@ wait_until_ready () # This function is becoming nicely overloaded. Soon it will collapse! :-) node_has_status () { - local pnn="$1" - local status="$2" - - local bits fpat mpat rpat - case "$status" in - (unhealthy) bits="?|?|?|1|*" ;; - (healthy) bits="?|?|?|0|*" ;; - (disconnected) bits="1|*" ;; - (connected) bits="0|*" ;; - (banned) bits="?|1|*" ;; - (unbanned) bits="?|0|*" ;; - (disabled) bits="?|?|1|*" ;; - (enabled) bits="?|?|0|*" ;; - (stopped) bits="?|?|?|?|1|*" ;; - (notstopped) bits="?|?|?|?|0|*" ;; - (frozen) fpat='^[[:space:]]+frozen[[:space:]]+1$' ;; - (unfrozen) fpat='^[[:space:]]+frozen[[:space:]]+0$' ;; - (recovered) rpat='^Recovery mode:RECOVERY \(1\)$' ;; - (notlmaster) rpat="^hash:.* lmaster:${pnn}\$" ;; + local pnn="$1" + local status="$2" + + local bits fpat mpat rpat + case "$status" in + unhealthy) bits="?|?|?|1|*" ;; + healthy) bits="?|?|?|0|*" ;; + disconnected) bits="1|*" ;; + connected) bits="0|*" ;; + banned) bits="?|1|*" ;; + unbanned) bits="?|0|*" ;; + disabled) bits="?|?|1|*" ;; + enabled) bits="?|?|0|*" ;; + stopped) bits="?|?|?|?|1|*" ;; + notstopped) bits="?|?|?|?|0|*" ;; + frozen) fpat='^[[:space:]]+frozen[[:space:]]+1$' ;; + unfrozen) fpat='^[[:space:]]+frozen[[:space:]]+0$' ;; + recovered) rpat='^Recovery mode:RECOVERY \(1\)$' ;; + notlmaster) rpat="^hash:.* lmaster:${pnn}\$" ;; *) - echo "node_has_status: unknown status \"$status\"" - return 1 - esac - - if [ -n "$bits" ] ; then - local out x line - - out=$($CTDB -X status 2>&1) || return 1 - - { - read x - while read line ; do - # This needs to be done in 2 steps to avoid false matches. - local line_bits="${line#|${pnn}|*|}" - [ "$line_bits" = "$line" ] && continue - [ "${line_bits#${bits}}" != "$line_bits" ] && return 0 - done - return 1 - } <<<"$out" # Yay bash! - elif [ -n "$fpat" ] ; then - $CTDB statistics -n "$pnn" | egrep -q "$fpat" - elif [ -n "$rpat" ] ; then - ! $CTDB status -n "$pnn" | egrep -q "$rpat" - else - echo 'node_has_status: unknown mode, neither $bits nor $fpat is set' - return 1 - fi + echo "node_has_status: unknown status \"$status\"" + return 1 + esac + + if [ -n "$bits" ] ; then + local out x line + + out=$($CTDB -X status 2>&1) || return 1 + + { + read x + while read line ; do + # This needs to be done in 2 steps to + # avoid false matches. + local line_bits="${line#|${pnn}|*|}" + [ "$line_bits" = "$line" ] && continue + [ "${line_bits#${bits}}" != "$line_bits" ] && \ + return 0 + done + return 1 + } <<<"$out" # Yay bash! + elif [ -n "$fpat" ] ; then + $CTDB statistics -n "$pnn" | egrep -q "$fpat" + elif [ -n "$rpat" ] ; then + ! $CTDB status -n "$pnn" | egrep -q "$rpat" + else + echo 'node_has_status: unknown mode, neither $bits nor $fpat is set' + return 1 + fi } wait_until_node_has_status () -- 2.17.1 From 6efb59affb25594828e4cc68a30ea41e71f0b124 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 29 Jul 2019 15:40:16 +1000 Subject: [PATCH 111/376] ctdb-tests: Drop unused node statuses frozen/unfrozen Silently drop unused local variable mpat. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 9b09a87326af28877301ad27bcec5bb13744e2b6) --- ctdb/tests/scripts/integration.bash | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ctdb/tests/scripts/integration.bash b/ctdb/tests/scripts/integration.bash index e2f238d93d4..60323e33a97 100644 --- a/ctdb/tests/scripts/integration.bash +++ b/ctdb/tests/scripts/integration.bash @@ -314,7 +314,7 @@ node_has_status () local pnn="$1" local status="$2" - local bits fpat mpat rpat + local bits rpat case "$status" in unhealthy) bits="?|?|?|1|*" ;; healthy) bits="?|?|?|0|*" ;; @@ -326,8 +326,6 @@ node_has_status () enabled) bits="?|?|0|*" ;; stopped) bits="?|?|?|?|1|*" ;; notstopped) bits="?|?|?|?|0|*" ;; - frozen) fpat='^[[:space:]]+frozen[[:space:]]+1$' ;; - unfrozen) fpat='^[[:space:]]+frozen[[:space:]]+0$' ;; recovered) rpat='^Recovery mode:RECOVERY \(1\)$' ;; notlmaster) rpat="^hash:.* lmaster:${pnn}\$" ;; *) @@ -352,12 +350,10 @@ node_has_status () done return 1 } <<<"$out" # Yay bash! - elif [ -n "$fpat" ] ; then - $CTDB statistics -n "$pnn" | egrep -q "$fpat" elif [ -n "$rpat" ] ; then ! $CTDB status -n "$pnn" | egrep -q "$rpat" else - echo 'node_has_status: unknown mode, neither $bits nor $fpat is set' + echo 'node_has_status: unknown mode, neither $bits nor $rpat is set' return 1 fi } -- 2.17.1 From e876b1e85627db8be59bcbcede7154a55f640b00 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 29 Jul 2019 15:45:41 +1000 Subject: [PATCH 112/376] ctdb-tests: Inline handling of recovered and notlmaster statuses BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit bb59073515ee5f7886b5d9a20d7b2805857c2708) --- ctdb/tests/scripts/integration.bash | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ctdb/tests/scripts/integration.bash b/ctdb/tests/scripts/integration.bash index 60323e33a97..d8411edc588 100644 --- a/ctdb/tests/scripts/integration.bash +++ b/ctdb/tests/scripts/integration.bash @@ -314,7 +314,7 @@ node_has_status () local pnn="$1" local status="$2" - local bits rpat + local bits case "$status" in unhealthy) bits="?|?|?|1|*" ;; healthy) bits="?|?|?|0|*" ;; @@ -326,8 +326,16 @@ node_has_status () enabled) bits="?|?|0|*" ;; stopped) bits="?|?|?|?|1|*" ;; notstopped) bits="?|?|?|?|0|*" ;; - recovered) rpat='^Recovery mode:RECOVERY \(1\)$' ;; - notlmaster) rpat="^hash:.* lmaster:${pnn}\$" ;; + recovered) + ! $CTDB status -n "$pnn" | \ + grep -Eq '^Recovery mode:RECOVERY \(1\)$' + return + ;; + notlmaster) + ! $CTDB status -n "$pnn" | \ + grep -Eq "^hash:.* lmaster:${pnn}\$" + return + ;; *) echo "node_has_status: unknown status \"$status\"" return 1 @@ -350,10 +358,8 @@ node_has_status () done return 1 } <<<"$out" # Yay bash! - elif [ -n "$rpat" ] ; then - ! $CTDB status -n "$pnn" | egrep -q "$rpat" else - echo 'node_has_status: unknown mode, neither $bits nor $rpat is set' + echo 'node_has_status: unknown mode, $bits not set' return 1 fi } -- 2.17.1 From 7e004230708001878e6b278aab32b6854289dc6a Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 29 Jul 2019 16:43:09 +1000 Subject: [PATCH 113/376] ctdb-tests: Handle special cases first and return All the other cases involve matching bits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit bff1a3a548a2cace997b767d78bb824438664cb7) --- ctdb/tests/scripts/integration.bash | 59 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/ctdb/tests/scripts/integration.bash b/ctdb/tests/scripts/integration.bash index d8411edc588..3fb6f9ade5e 100644 --- a/ctdb/tests/scripts/integration.bash +++ b/ctdb/tests/scripts/integration.bash @@ -314,6 +314,19 @@ node_has_status () local pnn="$1" local status="$2" + case "$status" in + recovered) + ! $CTDB status -n "$pnn" | \ + grep -Eq '^Recovery mode:RECOVERY \(1\)$' + return + ;; + notlmaster) + ! $CTDB status -n "$pnn" | \ + grep -Eq "^hash:.* lmaster:${pnn}\$" + return + ;; + esac + local bits case "$status" in unhealthy) bits="?|?|?|1|*" ;; @@ -326,42 +339,26 @@ node_has_status () enabled) bits="?|?|0|*" ;; stopped) bits="?|?|?|?|1|*" ;; notstopped) bits="?|?|?|?|0|*" ;; - recovered) - ! $CTDB status -n "$pnn" | \ - grep -Eq '^Recovery mode:RECOVERY \(1\)$' - return - ;; - notlmaster) - ! $CTDB status -n "$pnn" | \ - grep -Eq "^hash:.* lmaster:${pnn}\$" - return - ;; *) echo "node_has_status: unknown status \"$status\"" return 1 esac - - if [ -n "$bits" ] ; then - local out x line - - out=$($CTDB -X status 2>&1) || return 1 - - { - read x - while read line ; do - # This needs to be done in 2 steps to - # avoid false matches. - local line_bits="${line#|${pnn}|*|}" - [ "$line_bits" = "$line" ] && continue - [ "${line_bits#${bits}}" != "$line_bits" ] && \ - return 0 - done - return 1 - } <<<"$out" # Yay bash! - else - echo 'node_has_status: unknown mode, $bits not set' + local out x line + + out=$($CTDB -X status 2>&1) || return 1 + + { + read x + while read line ; do + # This needs to be done in 2 steps to + # avoid false matches. + local line_bits="${line#|${pnn}|*|}" + [ "$line_bits" = "$line" ] && continue + [ "${line_bits#${bits}}" != "$line_bits" ] && \ + return 0 + done return 1 - fi + } <<<"$out" # Yay bash! } wait_until_node_has_status () -- 2.17.1 From 4a5c554508b14be280bddb7c16688868c980abf0 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 29 Jul 2019 16:45:07 +1000 Subject: [PATCH 114/376] ctdb-tests: Don't retrieve the VNN map from target node for notlmaster Use the VNN map from the node running node_has_status(). This means that wait_until_node_has_status 1 notlmaster 10 0 will run "ctdb status" on node 0 and check (for up to 10 seconds) if node 1 is in the VNN map. If the LMASTER capability has been dropped on node 1 then the above will wait for the VNN map to be updated on node 0. This will happen as part of the recovery that is triggered by the change of LMASTER capability. The next command will then only be able to attach to $TESTDB after the recovery is complete thus guaranteeing a sane state for the test to continue. This stops simple/79_volatile_db_traverse.sh from going into recovery during the traverse or at some other inconvenient time. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 53daeb2f878af1634a26e05cb86d87e2faf20173) --- ctdb/tests/scripts/integration.bash | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ctdb/tests/scripts/integration.bash b/ctdb/tests/scripts/integration.bash index 3fb6f9ade5e..a4d45fb9ac2 100644 --- a/ctdb/tests/scripts/integration.bash +++ b/ctdb/tests/scripts/integration.bash @@ -321,8 +321,7 @@ node_has_status () return ;; notlmaster) - ! $CTDB status -n "$pnn" | \ - grep -Eq "^hash:.* lmaster:${pnn}\$" + ! $CTDB status | grep -Eq "^hash:.* lmaster:${pnn}\$" return ;; esac -- 2.17.1 From a03443efef6488a5b2dc74962f77070c0c8ecb06 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Wed, 21 Aug 2019 14:35:09 +1000 Subject: [PATCH 115/376] ctdb-recoverd: Only check for LMASTER nodes in the VNN map BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 5d655ac6f2ff82f8f1c89b06870d600a1a3c7a8a) --- ctdb/server/ctdb_recoverd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ctdb/server/ctdb_recoverd.c b/ctdb/server/ctdb_recoverd.c index 652bf9ce4ea..a190d0c9985 100644 --- a/ctdb/server/ctdb_recoverd.c +++ b/ctdb/server/ctdb_recoverd.c @@ -2989,13 +2989,19 @@ static void main_loop(struct ctdb_context *ctdb, struct ctdb_recoverd *rec, return; } - /* verify that all active nodes in the nodemap also exist in - the vnnmap. + /* + * Verify that all active lmaster nodes in the nodemap also + * exist in the vnnmap */ for (j=0; jnum; j++) { if (nodemap->nodes[j].flags & NODE_FLAGS_INACTIVE) { continue; } + if (! ctdb_node_has_capabilities(rec->caps, + ctdb->nodes[j]->pnn, + CTDB_CAP_LMASTER)) { + continue; + } if (nodemap->nodes[j].pnn == pnn) { continue; } @@ -3006,8 +3012,8 @@ static void main_loop(struct ctdb_context *ctdb, struct ctdb_recoverd *rec, } } if (i == vnnmap->size) { - DEBUG(DEBUG_ERR, (__location__ " Node %u is active in the nodemap but did not exist in the vnnmap\n", - nodemap->nodes[j].pnn)); + D_ERR("Active LMASTER node %u is not in the vnnmap\n", + nodemap->nodes[j].pnn); ctdb_set_culprit(rec, nodemap->nodes[j].pnn); do_recovery(rec, mem_ctx, pnn, nodemap, vnnmap); return; -- 2.17.1 From 9063f5dde3f9fc43037539e4424944400c00ddb5 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 29 Jul 2019 17:22:50 +1000 Subject: [PATCH 116/376] ctdb-tests: Strengthen volatile DB traverse test Check the record count more often, from multiple nodes. Add a case with multiple records. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit ca4df06080709adf0cbebc95b0a70b4090dad5ba) --- ctdb/tests/simple/79_volatile_db_traverse.sh | 67 +++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/ctdb/tests/simple/79_volatile_db_traverse.sh b/ctdb/tests/simple/79_volatile_db_traverse.sh index af7e962f579..7f3007d5105 100755 --- a/ctdb/tests/simple/79_volatile_db_traverse.sh +++ b/ctdb/tests/simple/79_volatile_db_traverse.sh @@ -42,11 +42,56 @@ try_command_on_node 0 $CTDB writekey "$TESTDB" "foo" "bar0" echo "write foo=bar1 on node 1" try_command_on_node 1 $CTDB writekey "$TESTDB" "foo" "bar1" -echo "do traverse on node 0" -try_command_on_node -v 0 $CTDB catdb "$TESTDB" +echo -echo "do traverse on node 1" -try_command_on_node -v 1 $CTDB catdb "$TESTDB" +check_db_num_records () +{ + local node="$1" + local db="$2" + local n="$3" + + echo "Checking on node ${node} to ensure ${db} has ${n} records..." + try_command_on_node "$node" "${CTDB} catdb ${db}" + + num=$(sed -n -e 's|^Dumped \(.*\) records$|\1|p' "$outfile") + if [ "$num" = "$n" ] ; then + echo "OK: Number of records=${num}" + echo + else + echo "BAD: There were ${num} (!= ${n}) records" + cat "$outfile" + exit 1 + fi +} + +check_db_num_records 0 "$TESTDB" 1 +check_db_num_records 1 "$TESTDB" 1 + +cat < Date: Tue, 13 Aug 2019 14:45:33 +1000 Subject: [PATCH 117/376] ctdb-tests: Clear deleted record via recovery instead of vacuuming This test has been flapping because sometimes the record is not vacuumed within the expected time period, perhaps even because the check for the record can interfere with vacuuming. However, instead of waiting for vacuuming the record can be cleared by doing a recovery. This should be much more reliable. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 RN: Fix flapping CTDB tests Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Martin Schwenke Autobuild-Date(master): Wed Aug 21 13:06:57 UTC 2019 on sn-devel-184 (cherry picked from commit 71ad473ba805abe23bbe6c1a1290612e448e73f3) --- .../simple/69_recovery_resurrect_deleted.sh | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/ctdb/tests/simple/69_recovery_resurrect_deleted.sh b/ctdb/tests/simple/69_recovery_resurrect_deleted.sh index 8126c49b83c..f6c72c59f2a 100755 --- a/ctdb/tests/simple/69_recovery_resurrect_deleted.sh +++ b/ctdb/tests/simple/69_recovery_resurrect_deleted.sh @@ -54,18 +54,11 @@ database_has_zero_records () return 0 } -echo "Get vacuum interval" -try_command_on_node -v $second $CTDB getvar VacuumInterval -vacuum_interval="${out#* = }" - -echo "Wait until vacuuming deletes the record on active nodes" -# Why 4? Steps are: -# 1. Original node processes delete queue, asks lmaster to fetch -# 2. lmaster recoverd fetches -# 3. lmaster processes delete queue -# If vacuuming is just missed then need an extra interval -t=$((vacuum_interval * 4)) -wait_until "${t}/10" database_has_zero_records +echo "Trigger a recovery" +try_command_on_node "$second" $CTDB recover + +echo "Checking that database has 0 records" +database_has_zero_records echo "Continue node ${first}" try_command_on_node $first $CTDB continue -- 2.17.1 From 8b680d309798d91e4658a358831e957aaffa480b Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 27 Aug 2019 12:13:51 +1000 Subject: [PATCH 118/376] ctdb-recoverd: Fix typo in previous fix BUG: https://bugzilla.samba.org/show_bug.cgi?id=14085 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Tue Aug 27 15:29:11 UTC 2019 on sn-devel-184 (cherry picked from commit 8190993d99284162bd8699780248bb2edfec2673) --- ctdb/server/ctdb_recoverd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctdb/server/ctdb_recoverd.c b/ctdb/server/ctdb_recoverd.c index a190d0c9985..3d5b727715a 100644 --- a/ctdb/server/ctdb_recoverd.c +++ b/ctdb/server/ctdb_recoverd.c @@ -2998,7 +2998,7 @@ static void main_loop(struct ctdb_context *ctdb, struct ctdb_recoverd *rec, continue; } if (! ctdb_node_has_capabilities(rec->caps, - ctdb->nodes[j]->pnn, + nodemap->nodes[j].pnn, CTDB_CAP_LMASTER)) { continue; } -- 2.17.1 From 0e96b2cb506f278562fe21b0b8d47da276b939c6 Mon Sep 17 00:00:00 2001 From: Poornima G Date: Wed, 24 Jul 2019 15:15:33 +0530 Subject: [PATCH 119/376] vfs_glusterfs: Use pthreadpool for scheduling aio operations BUG: https://bugzilla.samba.org/show_bug.cgi?id=14098 Signed-off-by: Poornima G Reviewed-by: Guenther Deschner Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Aug 23 18:40:08 UTC 2019 on sn-devel-184 (cherry picked from commit d8863dd8cb74bb0534457ca930a71e77c367d994) --- source3/modules/vfs_glusterfs.c | 562 +++++++++++++++++--------------- 1 file changed, 294 insertions(+), 268 deletions(-) diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 483d28397f8..afb34b4b47c 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -45,14 +45,11 @@ #include "lib/util/sys_rw.h" #include "smbprofile.h" #include "modules/posixacl_xattr.h" +#include "lib/pthreadpool/pthreadpool_tevent.h" #define DEFAULT_VOLFILE_SERVER "localhost" #define GLUSTER_NAME_MAX 255 -static int read_fd = -1; -static int write_fd = -1; -static struct tevent_fd *aio_read_event = NULL; - /** * Helper to convert struct stat to struct stat_ex. */ @@ -713,326 +710,283 @@ static ssize_t vfs_gluster_pread(struct vfs_handle_struct *handle, return ret; } -struct glusterfs_aio_state; - -struct glusterfs_aio_wrapper { - struct glusterfs_aio_state *state; -}; - -struct glusterfs_aio_state { +struct vfs_gluster_pread_state { ssize_t ret; - struct tevent_req *req; - bool cancelled; + glfs_fd_t *fd; + void *buf; + size_t count; + off_t offset; + struct vfs_aio_state vfs_aio_state; - struct timespec start; SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes); }; -static int aio_wrapper_destructor(struct glusterfs_aio_wrapper *wrap) -{ - if (wrap->state != NULL) { - wrap->state->cancelled = true; - } - - return 0; -} +static void vfs_gluster_pread_do(void *private_data); +static void vfs_gluster_pread_done(struct tevent_req *subreq); +static int vfs_gluster_pread_state_destructor(struct vfs_gluster_pread_state *state); -/* - * This function is the callback that will be called on glusterfs - * threads once the async IO submitted is complete. To notify - * Samba of the completion we use a pipe based queue. - */ -#ifdef HAVE_GFAPI_VER_7_6 -static void aio_glusterfs_done(glfs_fd_t *fd, ssize_t ret, - struct glfs_stat *prestat, - struct glfs_stat *poststat, - void *data) -#else -static void aio_glusterfs_done(glfs_fd_t *fd, ssize_t ret, void *data) -#endif +static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct + *handle, TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + files_struct *fsp, + void *data, size_t n, + off_t offset) { - struct glusterfs_aio_state *state = NULL; - int sts = 0; - struct timespec end; - - state = (struct glusterfs_aio_state *)data; + struct vfs_gluster_pread_state *state; + struct tevent_req *req, *subreq; - PROFILE_TIMESTAMP(&end); + glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + if (glfd == NULL) { + DBG_ERR("Failed to fetch gluster fd\n"); + return NULL; + } - if (ret < 0) { - state->ret = -1; - state->vfs_aio_state.error = errno; - } else { - state->ret = ret; + req = tevent_req_create(mem_ctx, &state, struct vfs_gluster_pread_state); + if (req == NULL) { + return NULL; } - state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start); - SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes); + state->ret = -1; + state->fd = glfd; + state->buf = data; + state->count = n; + state->offset = offset; - /* - * Write the state pointer to glusterfs_aio_state to the - * pipe, so we can call tevent_req_done() from the main thread, - * because tevent_req_done() is not designed to be executed in - * the multithread environment, so tevent_req_done() must be - * executed from the smbd main thread. - * - * write(2) on pipes with sizes under _POSIX_PIPE_BUF - * in size is atomic, without this, the use op pipes in this - * code would not work. - * - * sys_write is a thin enough wrapper around write(2) - * that we can trust it here. - */ + SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p, + state->profile_bytes, n); + SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes); - sts = sys_write(write_fd, &state, sizeof(struct glusterfs_aio_state *)); - if (sts < 0) { - DEBUG(0,("\nWrite to pipe failed (%s)", strerror(errno))); + subreq = pthreadpool_tevent_job_send( + state, ev, handle->conn->sconn->pool, + vfs_gluster_pread_do, state); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, vfs_gluster_pread_done, req); + + talloc_set_destructor(state, vfs_gluster_pread_state_destructor); - return; + return req; } -/* - * Read each req off the pipe and process it. - */ -static void aio_tevent_fd_done(struct tevent_context *event_ctx, - struct tevent_fd *fde, - uint16_t flags, void *data) +static void vfs_gluster_pread_do(void *private_data) { - struct tevent_req *req = NULL; - struct glusterfs_aio_state *state = NULL; - int sts = 0; + struct vfs_gluster_pread_state *state = talloc_get_type_abort( + private_data, struct vfs_gluster_pread_state); + struct timespec start_time; + struct timespec end_time; - /* - * read(2) on pipes is atomic if the needed data is available - * in the pipe, per SUS and POSIX. Because we always write - * to the pipe in sizeof(struct tevent_req *) chunks, we can - * always read in those chunks, atomically. - * - * sys_read is a thin enough wrapper around read(2) that we - * can trust it here. - */ + SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes); - sts = sys_read(read_fd, &state, sizeof(struct glusterfs_aio_state *)); + PROFILE_TIMESTAMP(&start_time); - if (sts < 0) { - DEBUG(0,("\nRead from pipe failed (%s)", strerror(errno))); - } + do { +#ifdef HAVE_GFAPI_VER_7_6 + state->ret = glfs_pread(state->fd, state->buf, state->count, + state->offset, 0, NULL); +#else + state->ret = glfs_pread(state->fd, state->buf, state->count, + state->offset, 0); +#endif + } while ((state->ret == -1) && (errno == EINTR)); - /* if we've cancelled the op, there is no req, so just clean up. */ - if (state->cancelled == true) { - TALLOC_FREE(state); - return; + if (state->ret == -1) { + state->vfs_aio_state.error = errno; } - req = state->req; + PROFILE_TIMESTAMP(&end_time); - if (req) { - tevent_req_done(req); - } - return; + state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time); + + SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes); } -static bool init_gluster_aio(struct vfs_handle_struct *handle) +static int vfs_gluster_pread_state_destructor(struct vfs_gluster_pread_state *state) { - int fds[2]; - int ret = -1; + return -1; +} - if (read_fd != -1) { +static void vfs_gluster_pread_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct vfs_gluster_pread_state *state = tevent_req_data( + req, struct vfs_gluster_pread_state); + int ret; + + ret = pthreadpool_tevent_job_recv(subreq); + TALLOC_FREE(subreq); + SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes); + talloc_set_destructor(state, NULL); + if (ret != 0) { + if (ret != EAGAIN) { + tevent_req_error(req, ret); + return; + } /* - * Already initialized. + * If we get EAGAIN from pthreadpool_tevent_job_recv() this + * means the lower level pthreadpool failed to create a new + * thread. Fallback to sync processing in that case to allow + * some progress for the client. */ - return true; - } - - ret = pipe(fds); - if (ret == -1) { - goto fail; - } - - read_fd = fds[0]; - write_fd = fds[1]; - - aio_read_event = tevent_add_fd(handle->conn->sconn->ev_ctx, - NULL, - read_fd, - TEVENT_FD_READ, - aio_tevent_fd_done, - NULL); - if (aio_read_event == NULL) { - goto fail; + vfs_gluster_pread_do(state); } - return true; -fail: - TALLOC_FREE(aio_read_event); - if (read_fd != -1) { - close(read_fd); - close(write_fd); - read_fd = -1; - write_fd = -1; - } - return false; + tevent_req_done(req); } -static struct glusterfs_aio_state *aio_state_create(TALLOC_CTX *mem_ctx) +static ssize_t vfs_gluster_pread_recv(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) { - struct tevent_req *req = NULL; - struct glusterfs_aio_state *state = NULL; - struct glusterfs_aio_wrapper *wrapper = NULL; + struct vfs_gluster_pread_state *state = tevent_req_data( + req, struct vfs_gluster_pread_state); - req = tevent_req_create(mem_ctx, &wrapper, struct glusterfs_aio_wrapper); - - if (req == NULL) { - return NULL; + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { + return -1; } - state = talloc_zero(NULL, struct glusterfs_aio_state); - - if (state == NULL) { - TALLOC_FREE(req); - return NULL; - } + *vfs_aio_state = state->vfs_aio_state; + return state->ret; +} - talloc_set_destructor(wrapper, aio_wrapper_destructor); - state->cancelled = false; - state->req = req; +struct vfs_gluster_pwrite_state { + ssize_t ret; + glfs_fd_t *fd; + const void *buf; + size_t count; + off_t offset; - wrapper->state = state; + struct vfs_aio_state vfs_aio_state; + SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes); +}; - return state; -} +static void vfs_gluster_pwrite_do(void *private_data); +static void vfs_gluster_pwrite_done(struct tevent_req *subreq); +static int vfs_gluster_pwrite_state_destructor(struct vfs_gluster_pwrite_state *state); -static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct +static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, files_struct *fsp, - void *data, size_t n, + const void *data, size_t n, off_t offset) { - struct glusterfs_aio_state *state = NULL; - struct tevent_req *req = NULL; - int ret = 0; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + struct tevent_req *req, *subreq; + struct vfs_gluster_pwrite_state *state; + glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { DBG_ERR("Failed to fetch gluster fd\n"); return NULL; } - state = aio_state_create(mem_ctx); - - if (state == NULL) { + req = tevent_req_create(mem_ctx, &state, struct vfs_gluster_pwrite_state); + if (req == NULL) { return NULL; } - req = state->req; + state->ret = -1; + state->fd = glfd; + state->buf = data; + state->count = n; + state->offset = offset; - if (!init_gluster_aio(handle)) { - tevent_req_error(req, EIO); - return tevent_req_post(req, ev); - } - - /* - * aio_glusterfs_done and aio_tevent_fd_done() - * use the raw tevent context. We need to use - * tevent_req_defer_callback() in order to - * use the event context we're started with. - */ - tevent_req_defer_callback(req, ev); - - SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p, + SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p, state->profile_bytes, n); - PROFILE_TIMESTAMP(&state->start); - ret = glfs_pread_async(glfd, data, n, offset, 0, aio_glusterfs_done, - state); - if (ret < 0) { - tevent_req_error(req, -ret); + SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes); + + subreq = pthreadpool_tevent_job_send( + state, ev, handle->conn->sconn->pool, + vfs_gluster_pwrite_do, state); + if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, vfs_gluster_pwrite_done, req); + + talloc_set_destructor(state, vfs_gluster_pwrite_state_destructor); return req; } -static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct - *handle, TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - files_struct *fsp, - const void *data, size_t n, - off_t offset) +static void vfs_gluster_pwrite_do(void *private_data) { - struct glusterfs_aio_state *state = NULL; - struct tevent_req *req = NULL; - int ret = 0; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); - - if (glfd == NULL) { - DBG_ERR("Failed to fetch gluster fd\n"); - return NULL; - } + struct vfs_gluster_pwrite_state *state = talloc_get_type_abort( + private_data, struct vfs_gluster_pwrite_state); + struct timespec start_time; + struct timespec end_time; - state = aio_state_create(mem_ctx); + SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes); - if (state == NULL) { - return NULL; - } + PROFILE_TIMESTAMP(&start_time); - req = state->req; + do { +#ifdef HAVE_GFAPI_VER_7_6 + state->ret = glfs_pwrite(state->fd, state->buf, state->count, + state->offset, 0, NULL, NULL); +#else + state->ret = glfs_pwrite(state->fd, state->buf, state->count, + state->offset, 0); +#endif + } while ((state->ret == -1) && (errno == EINTR)); - if (!init_gluster_aio(handle)) { - tevent_req_error(req, EIO); - return tevent_req_post(req, ev); + if (state->ret == -1) { + state->vfs_aio_state.error = errno; } - /* - * aio_glusterfs_done and aio_tevent_fd_done() - * use the raw tevent context. We need to use - * tevent_req_defer_callback() in order to - * use the event context we're started with. - */ - tevent_req_defer_callback(req, ev); + PROFILE_TIMESTAMP(&end_time); - SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p, - state->profile_bytes, n); - PROFILE_TIMESTAMP(&state->start); - ret = glfs_pwrite_async(glfd, data, n, offset, 0, aio_glusterfs_done, - state); - if (ret < 0) { - tevent_req_error(req, -ret); - return tevent_req_post(req, ev); - } + state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time); - return req; + SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes); } -static ssize_t vfs_gluster_recv(struct tevent_req *req, - struct vfs_aio_state *vfs_aio_state) +static int vfs_gluster_pwrite_state_destructor(struct vfs_gluster_pwrite_state *state) { - struct glusterfs_aio_wrapper *wrapper = NULL; - int ret = 0; + return -1; +} - wrapper = tevent_req_data(req, struct glusterfs_aio_wrapper); +static void vfs_gluster_pwrite_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct vfs_gluster_pwrite_state *state = tevent_req_data( + req, struct vfs_gluster_pwrite_state); + int ret; - if (wrapper == NULL) { - return -1; + ret = pthreadpool_tevent_job_recv(subreq); + TALLOC_FREE(subreq); + SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes); + talloc_set_destructor(state, NULL); + if (ret != 0) { + if (ret != EAGAIN) { + tevent_req_error(req, ret); + return; + } + /* + * If we get EAGAIN from pthreadpool_tevent_job_recv() this + * means the lower level pthreadpool failed to create a new + * thread. Fallback to sync processing in that case to allow + * some progress for the client. + */ + vfs_gluster_pwrite_do(state); } - if (wrapper->state == NULL) { - return -1; - } + tevent_req_done(req); +} + +static ssize_t vfs_gluster_pwrite_recv(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) +{ + struct vfs_gluster_pwrite_state *state = tevent_req_data( + req, struct vfs_gluster_pwrite_state); if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { return -1; } - *vfs_aio_state = wrapper->state->vfs_aio_state; - ret = wrapper->state->ret; + *vfs_aio_state = state->vfs_aio_state; - /* Clean up the state, it is in a NULL context. */ - - TALLOC_FREE(wrapper->state); - - return ret; + return state->ret; } static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle, @@ -1113,60 +1067,132 @@ static int vfs_gluster_rename(struct vfs_handle_struct *handle, return ret; } +struct vfs_gluster_fsync_state { + ssize_t ret; + glfs_fd_t *fd; + + struct vfs_aio_state vfs_aio_state; + SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes); +}; + +static void vfs_gluster_fsync_do(void *private_data); +static void vfs_gluster_fsync_done(struct tevent_req *subreq); +static int vfs_gluster_fsync_state_destructor(struct vfs_gluster_fsync_state *state); + static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, files_struct *fsp) { - struct tevent_req *req = NULL; - struct glusterfs_aio_state *state = NULL; - int ret = 0; - glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); + struct tevent_req *req, *subreq; + struct vfs_gluster_fsync_state *state; + glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp); if (glfd == NULL) { DBG_ERR("Failed to fetch gluster fd\n"); return NULL; } - state = aio_state_create(mem_ctx); - - if (state == NULL) { + req = tevent_req_create(mem_ctx, &state, struct vfs_gluster_fsync_state); + if (req == NULL) { return NULL; } - req = state->req; + state->ret = -1; + state->fd = glfd; - if (!init_gluster_aio(handle)) { - tevent_req_error(req, EIO); + SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p, + state->profile_bytes, 0); + SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes); + + subreq = pthreadpool_tevent_job_send( + state, ev, handle->conn->sconn->pool, vfs_gluster_fsync_do, state); + if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, vfs_gluster_fsync_done, req); - /* - * aio_glusterfs_done and aio_tevent_fd_done() - * use the raw tevent context. We need to use - * tevent_req_defer_callback() in order to - * use the event context we're started with. - */ - tevent_req_defer_callback(req, ev); + talloc_set_destructor(state, vfs_gluster_fsync_state_destructor); - SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p, - state->profile_bytes, 0); - PROFILE_TIMESTAMP(&state->start); - ret = glfs_fsync_async(glfd, aio_glusterfs_done, state); - if (ret < 0) { - tevent_req_error(req, -ret); - return tevent_req_post(req, ev); - } return req; } +static void vfs_gluster_fsync_do(void *private_data) +{ + struct vfs_gluster_fsync_state *state = talloc_get_type_abort( + private_data, struct vfs_gluster_fsync_state); + struct timespec start_time; + struct timespec end_time; + + SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes); + + PROFILE_TIMESTAMP(&start_time); + + do { +#ifdef HAVE_GFAPI_VER_7_6 + state->ret = glfs_fsync(state->fd, NULL, NULL); +#else + state->ret = glfs_fsync(state->fd); +#endif + } while ((state->ret == -1) && (errno == EINTR)); + + if (state->ret == -1) { + state->vfs_aio_state.error = errno; + } + + PROFILE_TIMESTAMP(&end_time); + + state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time); + + SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes); +} + +static int vfs_gluster_fsync_state_destructor(struct vfs_gluster_fsync_state *state) +{ + return -1; +} + +static void vfs_gluster_fsync_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct vfs_gluster_fsync_state *state = tevent_req_data( + req, struct vfs_gluster_fsync_state); + int ret; + + ret = pthreadpool_tevent_job_recv(subreq); + TALLOC_FREE(subreq); + SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes); + talloc_set_destructor(state, NULL); + if (ret != 0) { + if (ret != EAGAIN) { + tevent_req_error(req, ret); + return; + } + /* + * If we get EAGAIN from pthreadpool_tevent_job_recv() this + * means the lower level pthreadpool failed to create a new + * thread. Fallback to sync processing in that case to allow + * some progress for the client. + */ + vfs_gluster_fsync_do(state); + } + + tevent_req_done(req); +} + static int vfs_gluster_fsync_recv(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state) { - /* - * Use implicit conversion ssize_t->int - */ - return vfs_gluster_recv(req, vfs_aio_state); + struct vfs_gluster_fsync_state *state = tevent_req_data( + req, struct vfs_gluster_fsync_state); + + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { + return -1; + } + + *vfs_aio_state = state->vfs_aio_state; + return state->ret; } static int vfs_gluster_stat(struct vfs_handle_struct *handle, @@ -1862,10 +1888,10 @@ static struct vfs_fn_pointers glusterfs_fns = { .close_fn = vfs_gluster_close, .pread_fn = vfs_gluster_pread, .pread_send_fn = vfs_gluster_pread_send, - .pread_recv_fn = vfs_gluster_recv, + .pread_recv_fn = vfs_gluster_pread_recv, .pwrite_fn = vfs_gluster_pwrite, .pwrite_send_fn = vfs_gluster_pwrite_send, - .pwrite_recv_fn = vfs_gluster_recv, + .pwrite_recv_fn = vfs_gluster_pwrite_recv, .lseek_fn = vfs_gluster_lseek, .sendfile_fn = vfs_gluster_sendfile, .recvfile_fn = vfs_gluster_recvfile, -- 2.17.1 From 0358b3f9bc1e557a639ec63670d8c29c135e54f5 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Sat, 6 Jul 2019 23:24:43 +1200 Subject: [PATCH 120/376] ldb: do not allow adding a DN as a base to itself If you try to add a dn to itself, it expands as it goes. The resulting loop cannot end well. It looks like this in Python: dn = ldb.Dn(ldb.Ldb(), 'CN=y,DC=x') dn.add_base(dn) Signed-off-by: Douglas Bagnall Reviewed-by: Gary Lockyer (cherry picked from commit 19a13cbe0681b3996c33f7449f69b0fb0dc5d640) --- lib/ldb/common/ldb_dn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index 2e98f391467..eccb4a0ce4b 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -1357,6 +1357,10 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base) return false; } + if (dn == base) { + return false; /* or we will visit infinity */ + } + if (dn->components) { unsigned int i; -- 2.17.1 From 7cf6afba65641f48a5e2c326464fd97fd9f4173c Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 8 Mar 2019 12:12:00 +1300 Subject: [PATCH 121/376] ldb_dn: free dn components on explode failure Signed-off-by: Douglas Bagnall Reviewed-by: Noel Power (cherry picked from commit b136f153b83d80a91ec9d5350fdf08412d881964) --- lib/ldb/common/ldb_dn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index eccb4a0ce4b..23a817edf65 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -340,7 +340,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) /* Components data space is allocated here once */ data = talloc_array(dn->components, char, strlen(parse_dn) + 1); if (!data) { - return false; + goto failed; } p = parse_dn; -- 2.17.1 From 57f00784ffac527a0f9b830339bba24784f2e294 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 31 Jul 2019 10:27:37 +0200 Subject: [PATCH 122/376] ldb: Fix mem-leak if talloc_realloc fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of a failing talloc_realloc(), the only reference to the originally allocated memory is overwritten. Instead use a temp var until success is verified. Signed-off-by: Swen Schillig Reviewed-by: Christof Schmitt Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Andrew Bartlett (cherry picked from commit 99b4791cfe423b19f1f21d5f9fb42157336019f1) --- lib/ldb/common/ldb_dn.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index 23a817edf65..9b2fa966e11 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -376,6 +376,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) } if (in_ex_value && *p == '>') { + struct ldb_dn_ext_component *ext_comp = NULL; const struct ldb_dn_extended_syntax *ext_syntax; struct ldb_val ex_val = { .data = (uint8_t *)ex_value, @@ -388,15 +389,19 @@ static bool ldb_dn_explode(struct ldb_dn *dn) /* Process name and ex_value */ - dn->ext_components = talloc_realloc(dn, - dn->ext_components, - struct ldb_dn_ext_component, - dn->ext_comp_num + 1); - if ( ! dn->ext_components) { + ext_comp = talloc_realloc( + dn, + dn->ext_components, + struct ldb_dn_ext_component, + dn->ext_comp_num + 1); + + if (ext_comp == NULL) { /* ouch ! */ goto failed; } + dn->ext_components = ext_comp; + ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name); if (!ext_syntax) { /* We don't know about this type of extended DN */ -- 2.17.1 From 9c677a274d49026105c72c5b4767b1d88eff77fa Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 26 Aug 2019 13:04:07 +1200 Subject: [PATCH 123/376] ldb: Correct Pigeonhole principle validation in ldb_filter_attrs() Thankfully this only fails if the DB is corrupt and has a duplicate record. The test was at the wrong end of the loop, and was for the wrong boundary condition. A write after the end of the array would occour before the condition was hit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13695 Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit b1eec5b196e3d5a5716a5c74cf669ceaa5c0301f) --- lib/ldb/common/ldb_pack.c | 31 +- lib/ldb/tests/ldb_filter_attrs_test.c | 986 ++++++++++++++++++++++++++ lib/ldb/wscript | 5 + 3 files changed, 1013 insertions(+), 9 deletions(-) create mode 100644 lib/ldb/tests/ldb_filter_attrs_test.c diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c index 9d87a10b9f1..1d67622b69e 100644 --- a/lib/ldb/common/ldb_pack.c +++ b/lib/ldb/common/ldb_pack.c @@ -1163,7 +1163,10 @@ int ldb_filter_attrs(struct ldb_context *ldb, } else if (i == 0) { return 0; - /* Otherwise we are copying at most as many element as we have attributes */ + /* + * Otherwise we are copying at most as many elements as we + * have attributes + */ } else { elements_size = i; } @@ -1177,7 +1180,12 @@ int ldb_filter_attrs(struct ldb_context *ldb, for (i = 0; i < msg->num_elements; i++) { struct ldb_message_element *el = &msg->elements[i]; - struct ldb_message_element *el2 = &filtered_msg->elements[num_elements]; + + /* + * el2 is assigned after the Pigeonhole principle + * check below for clarity + */ + struct ldb_message_element *el2 = NULL; unsigned int j; if (keep_all == false) { @@ -1193,6 +1201,18 @@ int ldb_filter_attrs(struct ldb_context *ldb, continue; } } + + /* + * Pigeonhole principle: we can't have more elements + * than the number of attributes if they are unique in + * the DB. + */ + if (num_elements >= elements_size) { + goto failed; + } + + el2 = &filtered_msg->elements[num_elements]; + *el2 = *el; el2->name = talloc_strdup(filtered_msg->elements, el->name); @@ -1211,13 +1231,6 @@ int ldb_filter_attrs(struct ldb_context *ldb, } } num_elements++; - - /* Pidginhole principle: we can't have more elements - * than the number of attributes if they are unique in - * the DB */ - if (num_elements > elements_size) { - goto failed; - } } filtered_msg->num_elements = num_elements; diff --git a/lib/ldb/tests/ldb_filter_attrs_test.c b/lib/ldb/tests/ldb_filter_attrs_test.c new file mode 100644 index 00000000000..d04775879ac --- /dev/null +++ b/lib/ldb/tests/ldb_filter_attrs_test.c @@ -0,0 +1,986 @@ +/* + * Tests exercising the ldb_filter_attrs(). + * + * + * Copyright (C) Catalyst.NET Ltd 2017 + * Copyright (C) Andrew Bartlett 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + */ +#include +#include +#include +#include +#include + +#include "../include/ldb.h" +#include "../include/ldb_module.h" + +struct ldbtest_ctx { + struct tevent_context *ev; + struct ldb_context *ldb; +}; + +/* + * NOTE WELL: + * + * This test checks the current behaviour of the function, however + * this is not in a public ABI and many of the tested behaviours are + * not ideal. If the behaviour is deliberatly improved, this test + * should be updated without worry to the new better behaviour. + * + * In particular the test is particularly to ensure the current + * behaviour is memory-safe. + */ + +static int setup(void **state) +{ + struct ldbtest_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct ldbtest_ctx); + assert_non_null(test_ctx); + + test_ctx->ev = tevent_context_init(test_ctx); + assert_non_null(test_ctx->ev); + + test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev); + assert_non_null(test_ctx->ldb); + + *state = test_ctx; + return 0; +} + +static int teardown(void **state) +{ + talloc_free(*state); + return 0; +} + + +/* + * Test against a record with only one attribute, matching the one in + * the list + */ +static void test_filter_attrs_one_attr_matched(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"foo", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + assert_int_equal(filtered_msg->num_elements, 1); + assert_string_equal(filtered_msg->elements[0].name, "foo"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value, sizeof(value)); +} + +/* + * Test against a record with only one attribute, matching the one of + * the multiple attributes in the list + */ +static void test_filter_attrs_one_attr_matched_of_many(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"foo", "bar", "baz", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + assert_int_equal(filtered_msg->num_elements, 1); + assert_string_equal(filtered_msg->elements[0].name, "foo"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value, sizeof(value)); +} + +/* + * Test against a record with only one attribute, matching both + * attributes in the list + */ +static void test_filter_attrs_two_attr_matched_attrs(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + /* deliberatly the other order */ + const char *attrs[] = {"bar", "foo", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "foo", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 2); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "foo"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes, only of which is in + * the list + */ +static void test_filter_attrs_two_attr_matched_one_attr(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + /* deliberatly the other order */ + const char *attrs[] = {"bar", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "foo", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 1); + + /* + * assert the ldb_filter_attrs does not read or modify + * filtered_msg.dn in this case + */ + assert_null(filtered_msg->dn); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes, both matching the one + * specified attribute in the list (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + /* deliberatly the other order */ + const char *attrs[] = {"bar", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This should fail the pidgenhole test */ + assert_int_equal(ret, -1); +} + +/* + * Test against a record with two attributes, both matching the one + * specified attribute in the list (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_dup(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"bar", "bar", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This does not fail the pidgenhole test */ + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(filtered_msg->num_elements, 2); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes, both matching one of the + * specified attributes in the list (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_one_of_two(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"bar", "foo", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This does not fail the pidgenhole test */ + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(filtered_msg->num_elements, 2); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); +} + +/* + * Test against a record with two attributes against * (but not the + * other named attribute) (a corrupt record) + */ +static void test_filter_attrs_two_dup_attr_matched_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", "foo", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + + /* foo and bar are the other order to in attrs */ + struct ldb_message_element elements[] = { + { + .name = "bar", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + /* Needed as * implies distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + + /* This does not fail the pidgenhole test */ + assert_int_equal(ret, LDB_SUCCESS); + assert_int_equal(filtered_msg->num_elements, 3); + + /* Assert that DB order is preserved */ + assert_string_equal(filtered_msg->elements[0].name, "bar"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_int_equal(filtered_msg->elements[0].values[0].length, + sizeof(value1)); + assert_memory_equal(filtered_msg->elements[0].values[0].data, + value1, sizeof(value1)); + assert_string_equal(filtered_msg->elements[1].name, "bar"); + assert_int_equal(filtered_msg->elements[1].num_values, 1); + assert_int_equal(filtered_msg->elements[1].values[0].length, + sizeof(value2)); + assert_memory_equal(filtered_msg->elements[1].values[0].data, + value2, sizeof(value2)); + /* + * assert the ldb_filter_attrs does not modify filtered_msg.dn + * in this case + */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); +} + +/* + * Test against a record with only one attribute, matching the * in + * the list + */ +static void test_filter_attrs_one_attr_matched_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + /* Needed as * implies distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 2); + + /* + * assert the ldb_filter_attrs does not modify filtered_msg.dn + * in this case + */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "foo", + NULL), + value); +} + +/* + * Test against a record with two attributes, matching the * in + * the list + */ +static void test_filter_attrs_two_attr_matched_star(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", NULL}; + + uint8_t value1[] = "The value.......end"; + uint8_t value2[] = "The value..MUST.end"; + struct ldb_val value_1 = { + .data = value1, + .length = (sizeof(value1)) + }; + struct ldb_val value_2 = { + .data = value2, + .length = (sizeof(value2)) + }; + struct ldb_message_element elements[] = { + { + .name = "foo", + .num_values = 1, + .values = &value_1 + }, + { + .name = "bar", + .num_values = 1, + .values = &value_2 + } + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 2, + .elements = elements, + }; + + assert_non_null(in.dn); + + /* Needed as * implies distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 3); + + /* + * assert the ldb_filter_attrs does not modify filtered_msg.dn + * in this case + */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "foo", + NULL), + value1); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "bar", + NULL), + value2); +} + +/* + * Test against a record with only one attribute, matching the * in + * the list, but without the DN being pre-filled. Fails due to need + * to contstruct the distinguishedName + */ +static void test_filter_attrs_one_attr_matched_star_no_dn(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, -1); +} + +/* + * Test against a record with only one attribute, matching the * in + * the list plus requsesting distinguishedName + */ +static void test_filter_attrs_one_attr_matched_star_dn(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"*", "distinguishedName", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + /* Needed for distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 2); + + /* show that ldb_filter_attrs does not modify in.dn */ + assert_ptr_equal(filtered_msg->dn, in.dn); + + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "distinguishedName", + NULL), + ldb_dn_get_linearized(in.dn)); + assert_string_equal(ldb_msg_find_attr_as_string(filtered_msg, + "foo", + NULL), + value); +} + +/* + * Test against a record with only one attribute, but returning + * distinguishedName from the list (only) + */ +static void test_filter_attrs_one_attr_matched_dn(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {"distinguishedName", NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + /* Needed for distinguishedName */ + filtered_msg->dn = in.dn; + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 1); + + /* show that ldb_filter_attrs does not modify in.dn */ + assert_ptr_equal(filtered_msg->dn, in.dn); + assert_string_equal(filtered_msg->elements[0].name, "distinguishedName"); + assert_int_equal(filtered_msg->elements[0].num_values, 1); + assert_string_equal(filtered_msg->elements[0].values[0].data, + ldb_dn_get_linearized(in.dn)); +} + +/* + * Test against a record with only one attribute, not matching the + * empty attribute list + */ +static void test_filter_attrs_one_attr_empty_list(void **state) +{ + struct ldbtest_ctx *ctx = *state; + int ret; + + struct ldb_message *filtered_msg = ldb_msg_new(ctx); + + const char *attrs[] = {NULL}; + + uint8_t value[] = "The value.......end"; + struct ldb_val value_1 = { + .data = value, + .length = (sizeof(value)) + }; + struct ldb_message_element element_1 = { + .name = "foo", + .num_values = 1, + .values = &value_1 + }; + struct ldb_message in = { + .dn = ldb_dn_new(ctx, ctx->ldb, "dc=samba,dc=org"), + .num_elements = 1, + .elements = &element_1, + }; + + assert_non_null(in.dn); + + ret = ldb_filter_attrs(ctx->ldb, + &in, + attrs, + filtered_msg); + assert_int_equal(ret, LDB_SUCCESS); + assert_non_null(filtered_msg); + assert_int_equal(filtered_msg->num_elements, 0); + assert_null(filtered_msg->dn); + assert_null(filtered_msg->elements); +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_of_many, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_attr_matched_attrs, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_attr_matched_one_attr, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_one_attr, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_dup, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_one_of_two, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_dup_attr_matched_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_two_attr_matched_star, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_star_no_dn, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_star_dn, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_matched_dn, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_filter_attrs_one_attr_empty_list, + setup, + teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/ldb/wscript b/lib/ldb/wscript index a63a6c2171f..f928e2c739c 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -512,6 +512,11 @@ def build(bld): deps='cmocka ldb ldb_tdb_err_map', install=False) + bld.SAMBA_BINARY('ldb_filter_attrs_test', + source='tests/ldb_filter_attrs_test.c', + deps='cmocka ldb ldb_tdb_err_map', + install=False) + bld.SAMBA_BINARY('ldb_key_value_sub_txn_tdb_test', bld.SUBDIR('ldb_key_value', '''ldb_kv_search.c -- 2.17.1 From 11427be15ed6701fb2a15830846b57fe5e62fb42 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 26 Aug 2019 14:48:52 +1200 Subject: [PATCH 124/376] ldb: use TALLOC_FREE() over talloc_free() in ldb_filter_attrs() This is a macro that sets the pointer to NULL after the talloc_free() and is part of our standard coding practices. Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit 2117789c35fbf6d0ed02f391f17593e11727ec3e) --- lib/ldb/common/ldb_pack.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c index 1d67622b69e..b5e1fbbc4ff 100644 --- a/lib/ldb/common/ldb_pack.c +++ b/lib/ldb/common/ldb_pack.c @@ -1251,8 +1251,7 @@ int ldb_filter_attrs(struct ldb_context *ldb, goto failed; } } else { - talloc_free(filtered_msg->elements); - filtered_msg->elements = NULL; + TALLOC_FREE(filtered_msg->elements); } return 0; -- 2.17.1 From 61a039cc21d845bb4b984929d878dd8cf68839fe Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 26 Aug 2019 14:50:15 +1200 Subject: [PATCH 125/376] ldb: Call TALLOC_FREE(filtered_msg->elements) on ldb_filter_attrs() failure Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Tue Aug 27 01:16:33 UTC 2019 on sn-devel-184 (cherry picked from commit 1521a22f4366c86ec955cb9d32b7a758315d8ce0) --- lib/ldb/common/ldb_pack.c | 1 + lib/ldb/tests/ldb_filter_attrs_test.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c index b5e1fbbc4ff..e7dd364008a 100644 --- a/lib/ldb/common/ldb_pack.c +++ b/lib/ldb/common/ldb_pack.c @@ -1256,5 +1256,6 @@ int ldb_filter_attrs(struct ldb_context *ldb, return 0; failed: + TALLOC_FREE(filtered_msg->elements); return -1; } diff --git a/lib/ldb/tests/ldb_filter_attrs_test.c b/lib/ldb/tests/ldb_filter_attrs_test.c index d04775879ac..7d555e0da2e 100644 --- a/lib/ldb/tests/ldb_filter_attrs_test.c +++ b/lib/ldb/tests/ldb_filter_attrs_test.c @@ -384,6 +384,7 @@ static void test_filter_attrs_two_dup_attr_matched_one_attr(void **state) /* This should fail the pidgenhole test */ assert_int_equal(ret, -1); + assert_null(filtered_msg->elements); } /* @@ -772,6 +773,7 @@ static void test_filter_attrs_one_attr_matched_star_no_dn(void **state) attrs, filtered_msg); assert_int_equal(ret, -1); + assert_null(filtered_msg->elements); } /* -- 2.17.1 From c71c51dda004a617eaeccb0819b70310de1ebd14 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 26 Jul 2019 09:49:13 +1200 Subject: [PATCH 126/376] ldb: don't try to save a value that isn't there BUG: https://bugzilla.samba.org/show_bug.cgi?id=14049 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit 54f30f2fe3f03c9640664f9a11260b093fc57a5b) --- lib/ldb/common/ldb_dn.c | 47 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index 9b2fa966e11..a7fb0d9c443 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -697,31 +697,32 @@ static bool ldb_dn_explode(struct ldb_dn *dn) goto failed; } - /* save last element */ - if ( t ) { - /* trim back */ - d -= (p - t); - l -= (p - t); - } + if (in_value) { + /* save last element */ + if ( t ) { + /* trim back */ + d -= (p - t); + l -= (p - t); + } + + *d++ = '\0'; + /* + * This talloc_memdup() is OK with the + * +1 because *d has been set to '\0' + * just above. + */ + dn->components[dn->comp_num].value.length = l; + dn->components[dn->comp_num].value.data = + (uint8_t *)talloc_memdup(dn->components, dt, l + 1); + if ( ! dn->components[dn->comp_num].value.data) { + /* ouch */ + goto failed; + } + talloc_set_name_const(dn->components[dn->comp_num].value.data, + (const char *)dn->components[dn->comp_num].value.data); - *d++ = '\0'; - /* - * This talloc_memdup() is OK with the - * +1 because *d has been set to '\0' - * just above. - */ - dn->components[dn->comp_num].value.length = l; - dn->components[dn->comp_num].value.data = - (uint8_t *)talloc_memdup(dn->components, dt, l + 1); - if ( ! dn->components[dn->comp_num].value.data) { - /* ouch */ - goto failed; + dn->comp_num++; } - talloc_set_name_const(dn->components[dn->comp_num].value.data, - (const char *)dn->components[dn->comp_num].value.data); - - dn->comp_num++; - talloc_free(data); return true; -- 2.17.1 From 0f993c094ea242934766761389cecd5ecfd14a37 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 25 Jul 2019 12:09:16 +1200 Subject: [PATCH 127/376] ldb: add some dn explode tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14049 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit a097ddf65ce56dcd2e0b072b6dd78f512a77a9da) --- lib/ldb/tests/test_ldb_dn.c | 70 +++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/lib/ldb/tests/test_ldb_dn.c b/lib/ldb/tests/test_ldb_dn.c index 4965dcef575..7c202399a21 100644 --- a/lib/ldb/tests/test_ldb_dn.c +++ b/lib/ldb/tests/test_ldb_dn.c @@ -23,6 +23,7 @@ #include #include +#include "ldb_private.h" static void test_ldb_dn_add_child_fmt(void **state) { @@ -105,12 +106,81 @@ static void test_ldb_dn_add_child_val2(void **state) } +struct explode_test { + const char *strdn; + int comp_num; + int ext_comp_num; + bool special; + bool invalid; + const char *linearized; + const char *ext_linearized; + bool explode_result; +}; + +static void test_ldb_dn_explode(void **state) +{ + size_t i; + struct ldb_context *ldb = ldb_init(NULL, NULL); + struct explode_test tests[] = { + {"A=B", 1, 0, false, false, "A=B", "A=B", true}, + {"", 0, 0, false, false, "", "", true}, + {" ", -1, -1, false, false, " ", " ", false}, + {"<>", 0, 0, false, false, "", NULL, true}, + {"<", 0, 0, false, false, "", NULL, true}, + {"<><", 0, 0, false, false, "", NULL, true}, + {"<><>", 0, 0, false, false, "", NULL, true}, + {"A=B,C=D", 2, 0, false, false, "A=B,C=D", "A=B,C=D", true}, + {"x=🔥", 1, 0, false, false, "x=🔥", "x=🔥", true}, + }; + + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + bool result; + const char *linear; + const char *ext_linear; + struct ldb_dn *dn = ldb_dn_new(ldb, ldb, tests[i].strdn); + + /* + * special, invalid, linear, and ext_linear are set before + * explode + */ + fprintf(stderr, "%zu «%s»: ", i, tests[i].strdn); + linear = ldb_dn_get_linearized(dn); + assert_true((linear == NULL) == (tests[i].linearized == NULL)); + assert_string_equal(linear, + tests[i].linearized); + + ext_linear = ldb_dn_get_extended_linearized(ldb, dn, 1); + assert_true((ext_linear == NULL) == + (tests[i].ext_linearized == NULL)); + + if (tests[i].ext_linearized != NULL) { + assert_string_equal(ext_linear, + tests[i].ext_linearized); + } + assert_true(ldb_dn_is_special(dn) == tests[i].special); + assert_true(ldb_dn_is_valid(dn) != tests[i].invalid); + + /* comp nums are set by explode */ + result = ldb_dn_validate(dn); + fprintf(stderr, "res %i lin «%s» ext «%s»\n", + result, linear, ext_linear); + + assert_true(result == tests[i].explode_result); + assert_int_equal(ldb_dn_get_comp_num(dn), + tests[i].comp_num); + assert_int_equal(ldb_dn_get_extended_comp_num(dn), + tests[i].ext_comp_num); + } +} + int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_ldb_dn_add_child_fmt), cmocka_unit_test(test_ldb_dn_add_child_fmt2), cmocka_unit_test(test_ldb_dn_add_child_val), cmocka_unit_test(test_ldb_dn_add_child_val2), + cmocka_unit_test(test_ldb_dn_explode), }; return cmocka_run_group_tests(tests, NULL, NULL); -- 2.17.1 From 1bc9476be79b994a3a9b0618f23f176e399c5aaa Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 22 Aug 2019 10:59:07 +1200 Subject: [PATCH 128/376] ldb: Rework all pointer NULL tests to use Samba's normal style Also avoid if () without braces BUG: https://bugzilla.samba.org/show_bug.cgi?id=14049 Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit 3f290e95c2c133eb2c983ecc984d3dff4809f3d3) --- lib/ldb/common/ldb_dn.c | 52 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index a7fb0d9c443..377dd74d9f3 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -298,19 +298,21 @@ static bool ldb_dn_explode(struct ldb_dn *dn) char *parse_dn; bool is_index; - if ( ! dn || dn->invalid) return false; + if (dn == NULL || dn->invalid) { + return false; + } - if (dn->components) { + if (dn->components != NULL) { return true; } - if (dn->ext_linearized) { + if (dn->ext_linearized != NULL) { parse_dn = dn->ext_linearized; } else { parse_dn = dn->linearized; } - if ( ! parse_dn ) { + if (parse_dn == NULL) { return false; } @@ -333,13 +335,13 @@ static bool ldb_dn_explode(struct ldb_dn *dn) /* in the common case we have 3 or more components */ /* make sure all components are zeroed, other functions depend on it */ dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3); - if ( ! dn->components) { + if (dn->components == NULL) { return false; } /* Components data space is allocated here once */ data = talloc_array(dn->components, char, strlen(parse_dn) + 1); - if (!data) { + if (data == NULL) { goto failed; } @@ -403,7 +405,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) dn->ext_components = ext_comp; ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name); - if (!ext_syntax) { + if (ext_syntax == NULL) { /* We don't know about this type of extended DN */ goto failed; } @@ -486,7 +488,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) * with spaces trimmed) */ *d++ = '\0'; dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt); - if ( ! dn->components[dn->comp_num].name) { + if (dn->components[dn->comp_num].name == NULL) { /* ouch */ goto failed; } @@ -564,7 +566,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) } /* ok found value terminator */ - if ( t ) { + if (t != NULL) { /* trim back */ d -= (p - t); l -= (p - t); @@ -585,7 +587,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) dn->components[dn->comp_num].value.data = \ (uint8_t *)talloc_memdup(dn->components, dt, l + 1); dn->components[dn->comp_num].value.length = l; - if ( ! dn->components[dn->comp_num].value.data) { + if (dn->components[dn->comp_num].value.data == NULL) { /* ouch ! */ goto failed; } @@ -600,7 +602,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) dn->components, struct ldb_dn_component, dn->comp_num + 1); - if ( ! dn->components) { + if (dn->components == NULL) { /* ouch ! */ goto failed; } @@ -618,7 +620,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn) values, which contain a '+' or '=' which should normally be escaped */ if (is_index) { - if ( t ) t = NULL; + if (t != NULL) { + t = NULL; + } *d++ = *p++; l++; break; @@ -639,7 +643,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn) *d++ = *p++; l++; - if ( t ) t = NULL; + if (t != NULL) { + t = NULL; + } break; case '\\': @@ -653,7 +659,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn) *d++ = *p++; l++; - if ( t ) t = NULL; + if (t != NULL) { + t = NULL; + } break; default: @@ -672,14 +680,20 @@ static bool ldb_dn_explode(struct ldb_dn *dn) escape = false; l++; - if ( t ) t = NULL; + if (t != NULL) { + t = NULL; + } break; } if (*p == ' ') { - if ( ! t) t = p; + if (t == NULL) { + t = p; + } } else { - if ( t ) t = NULL; + if (t != NULL) { + t = NULL; + } } *d++ = *p++; @@ -699,7 +713,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) if (in_value) { /* save last element */ - if ( t ) { + if (t != NULL) { /* trim back */ d -= (p - t); l -= (p - t); @@ -714,7 +728,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) dn->components[dn->comp_num].value.length = l; dn->components[dn->comp_num].value.data = (uint8_t *)talloc_memdup(dn->components, dt, l + 1); - if ( ! dn->components[dn->comp_num].value.data) { + if (dn->components[dn->comp_num].value.data == NULL) { /* ouch */ goto failed; } -- 2.17.1 From 9b0c30517834da57a436ac6a0bad1fa2c6173849 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 22 Aug 2019 11:09:55 +1200 Subject: [PATCH 129/376] ldb: Add test with == true or false to boolean if statements in ldb_dn_explode() This is beyond the normal level of clarity we expect in Samba, and is of course rudundent, but this is a complex routine that has confusing tests, some of pointers and some of boolean state values. This tries to make the code as clear as possible pending a more comprehensive rewrite. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14049 Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit 52bd2dde5ae809ecc115f7087e367327f4771e73) --- lib/ldb/common/ldb_dn.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index 377dd74d9f3..b9a414dc566 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -298,7 +298,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) char *parse_dn; bool is_index; - if (dn == NULL || dn->invalid) { + if (dn == NULL || dn->invalid == true) { return false; } @@ -324,7 +324,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) } /* Special DNs case */ - if (dn->special) { + if (dn->special == true) { return true; } @@ -350,7 +350,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) d = dt = data; while (*p) { - if (in_extended) { + if (in_extended == true) { if (!in_ex_name && !in_ex_value) { @@ -437,8 +437,8 @@ static bool ldb_dn_explode(struct ldb_dn *dn) *d++ = *p++; continue; } - if (in_attr) { - if (trim) { + if (in_attr == true) { + if (trim == true) { if (*p == ' ') { p++; continue; @@ -505,7 +505,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) goto failed; } - if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) { + if (is_oid == true && ( ! (isdigit(*p) || (*p == '.')))) { /* not a digit nor a dot, * invalid attribute oid */ ldb_dn_mark_invalid(dn); @@ -521,8 +521,8 @@ static bool ldb_dn_explode(struct ldb_dn *dn) continue; } - if (in_value) { - if (in_quote) { + if (in_value == true) { + if (in_quote == true) { if (*p == '\"') { if (p[-1] != '\\') { p++; @@ -535,7 +535,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) continue; } - if (trim) { + if (trim == true) { if (*p == ' ') { p++; continue; @@ -558,7 +558,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) */ case ',': - if (escape) { + if (escape == true) { *d++ = *p++; l++; escape = false; @@ -619,7 +619,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) accept the base64 encoded binary index values, which contain a '+' or '=' which should normally be escaped */ - if (is_index) { + if (is_index == true) { if (t != NULL) { t = NULL; } @@ -634,7 +634,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) case '>': case ';': /* a string with not escaped specials is invalid (tested) */ - if ( ! escape) { + if (escape == false) { ldb_dn_mark_invalid(dn); goto failed; } @@ -649,7 +649,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) break; case '\\': - if ( ! escape) { + if (escape == false) { escape = true; p++; continue; @@ -665,7 +665,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn) break; default: - if (escape) { + if (escape == true) { if (isxdigit(p[0]) && isxdigit(p[1])) { if (sscanf(p, "%02x", &x) != 1) { /* invalid escaping sequence */ @@ -705,13 +705,13 @@ static bool ldb_dn_explode(struct ldb_dn *dn) } } - if (in_attr || in_quote) { + if (in_attr == true || in_quote == true) { /* invalid dn */ ldb_dn_mark_invalid(dn); goto failed; } - if (in_value) { + if (in_value == true) { /* save last element */ if (t != NULL) { /* trim back */ -- 2.17.1 From e019f3a6aac62460ee9768fec4001e00f00f8096 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 27 Aug 2019 13:16:18 +1200 Subject: [PATCH 130/376] ldb: Do not read beyond the end of the extended DN component when printing The print functions used in Samba NULL terminate, but do not assume they will BUG: https://bugzilla.samba.org/show_bug.cgi?id=14049 Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit a8a3cef3a768aaff01227dd7b229fb7b3aef926f) --- lib/ldb/common/ldb_dn.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index b9a414dc566..83f94e3b913 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -871,11 +871,15 @@ char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int } if (i == 0) { - p = talloc_asprintf(mem_ctx, "<%s=%s>", - name, val.data); + p = talloc_asprintf(mem_ctx, "<%s=%.*s>", + name, + (int)val.length, + val.data); } else { - p = talloc_asprintf_append_buffer(p, ";<%s=%s>", - name, val.data); + p = talloc_asprintf_append_buffer(p, ";<%s=%.*s>", + name, + (int)val.length, + val.data); } talloc_free(val.data); -- 2.17.1 From 9392ee7d29081118afd2dfd531946cbdcaba729d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 27 Aug 2019 13:16:50 +1200 Subject: [PATCH 131/376] ldb: Extend the ldb_dn_explode test matrix BUG: https://bugzilla.samba.org/show_bug.cgi?id=14049 Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit 10058bcfa16d5029e61252d64d142a8aab9ec296) --- lib/ldb/tests/test_ldb_dn.c | 53 ++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/lib/ldb/tests/test_ldb_dn.c b/lib/ldb/tests/test_ldb_dn.c index 7c202399a21..05f30e4ac67 100644 --- a/lib/ldb/tests/test_ldb_dn.c +++ b/lib/ldb/tests/test_ldb_dn.c @@ -113,10 +113,42 @@ struct explode_test { bool special; bool invalid; const char *linearized; - const char *ext_linearized; + const char *ext_linearized_1; bool explode_result; }; +static int extended_dn_read_ID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + + /* Allow to check we can cope with validity checks */ + if (in->length != 4) { + return -1; + } + + *out = *in; + out->data = talloc_memdup(mem_ctx, in->data, in->length); + if (out->data == NULL) { + return -1; + } + + return 0; +} + +/* write out (resued for both HEX and clear for now) */ +static int extended_dn_write_ID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + *out = *in; + + out->data = talloc_memdup(mem_ctx, in->data, in->length); + if (out->data == NULL) { + return -1; + } + return 0; +} + + static void test_ldb_dn_explode(void **state) { size_t i; @@ -130,9 +162,22 @@ static void test_ldb_dn_explode(void **state) {"<><", 0, 0, false, false, "", NULL, true}, {"<><>", 0, 0, false, false, "", NULL, true}, {"A=B,C=D", 2, 0, false, false, "A=B,C=D", "A=B,C=D", true}, + {"A=B,C=D", -1, -1, false, false, "", NULL, false}, + {";A=B,C=D", -1, -1, false, false, "A=B,C=D", NULL, false}, + {";A=B,C=D", -1, -1, false, true, "A=B,C=D", NULL, false}, + {";A=B,C=D", 2, 1, false, false, "A=B,C=D", ";A=B,C=D", true}, {"x=🔥", 1, 0, false, false, "x=🔥", "x=🔥", true}, + {"@FOO", 0, 0, true, false, "@FOO", "@FOO", true}, + }; + + struct ldb_dn_extended_syntax syntax = { + .name = "ID", + .read_fn = extended_dn_read_ID, + .write_clear_fn = extended_dn_write_ID, + .write_hex_fn = extended_dn_write_ID }; + ldb_dn_extended_add_syntax(ldb, 0, &syntax); for (i = 0; i < ARRAY_SIZE(tests); i++) { bool result; @@ -152,11 +197,11 @@ static void test_ldb_dn_explode(void **state) ext_linear = ldb_dn_get_extended_linearized(ldb, dn, 1); assert_true((ext_linear == NULL) == - (tests[i].ext_linearized == NULL)); + (tests[i].ext_linearized_1 == NULL)); - if (tests[i].ext_linearized != NULL) { + if (tests[i].ext_linearized_1 != NULL) { assert_string_equal(ext_linear, - tests[i].ext_linearized); + tests[i].ext_linearized_1); } assert_true(ldb_dn_is_special(dn) == tests[i].special); assert_true(ldb_dn_is_valid(dn) != tests[i].invalid); -- 2.17.1 From bc0d16c9d8eacd254552ff28726a2ba5f2a1c8c0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 28 Aug 2019 17:44:52 +1200 Subject: [PATCH 132/376] ldb: Release ldb 2.0.7 * Robustness improvements against duplicate attributes in ldb_filter_attrs() (bug 13695) * Robustness improvements against invalid string DN values (bug 14049) Signed-off-by: Andrew Bartlett Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Sep 4 10:24:56 UTC 2019 on sn-devel-184 --- lib/ldb/ABI/ldb-2.0.7.sigs | 283 ++++++++++++++++++++++++++++++ lib/ldb/ABI/pyldb-util-2.0.7.sigs | 2 + lib/ldb/wscript | 2 +- 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 lib/ldb/ABI/ldb-2.0.7.sigs create mode 100644 lib/ldb/ABI/pyldb-util-2.0.7.sigs diff --git a/lib/ldb/ABI/ldb-2.0.7.sigs b/lib/ldb/ABI/ldb-2.0.7.sigs new file mode 100644 index 00000000000..5049dc64ce1 --- /dev/null +++ b/lib/ldb/ABI/ldb-2.0.7.sigs @@ -0,0 +1,283 @@ +ldb_add: int (struct ldb_context *, const struct ldb_message *) +ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *) +ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...) +ldb_attr_casefold: char *(TALLOC_CTX *, const char *) +ldb_attr_dn: int (const char *) +ldb_attr_in_list: int (const char * const *, const char *) +ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *) +ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *) +ldb_base64_decode: int (char *) +ldb_base64_encode: char *(TALLOC_CTX *, const char *, int) +ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *) +ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val) +ldb_binary_encode_string: char *(TALLOC_CTX *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t) +ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t) +ldb_check_critical_controls: int (struct ldb_control **) +ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **) +ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *) +ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *) +ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_debug_add: void (struct ldb_context *, const char *, ...) +ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level) +ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_delete: int (struct ldb_context *, struct ldb_dn *) +ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *) +ldb_dn_check_special: bool (struct ldb_dn *, const char *) +ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val) +ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *) +ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *) +ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *) +ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *) +ldb_dn_get_casefold: const char *(struct ldb_dn *) +ldb_dn_get_comp_num: int (struct ldb_dn *) +ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int) +ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int) +ldb_dn_get_extended_comp_num: int (struct ldb_dn *) +ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int) +ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_get_rdn_name: const char *(struct ldb_dn *) +ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *) +ldb_dn_has_extended: bool (struct ldb_dn *) +ldb_dn_is_null: bool (struct ldb_dn *) +ldb_dn_is_special: bool (struct ldb_dn *) +ldb_dn_is_valid: bool (struct ldb_dn *) +ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_minimise: bool (struct ldb_dn *) +ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...) +ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_extended_components: void (struct ldb_dn *) +ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val) +ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *) +ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *) +ldb_dn_validate: bool (struct ldb_dn *) +ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *) +ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int) +ldb_errstring: const char *(struct ldb_context *) +ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **) +ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_create_perms: unsigned int (struct ldb_context *) +ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_event_context: struct tevent_context *(struct ldb_context *) +ldb_get_flags: unsigned int (struct ldb_context *) +ldb_get_opaque: void *(struct ldb_context *, const char *) +ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *) +ldb_global_init: int (void) +ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *) +ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **) +ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *) +ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *) +ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **) +ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *) +ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *) +ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_map_add: int (struct ldb_module *, struct ldb_request *) +ldb_map_delete: int (struct ldb_module *, struct ldb_request *) +ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *) +ldb_map_modify: int (struct ldb_module *, struct ldb_request *) +ldb_map_rename: int (struct ldb_module *, struct ldb_request *) +ldb_map_search: int (struct ldb_module *, struct ldb_request *) +ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *) +ldb_match_msg_objectclass: int (const struct ldb_message *, const char *) +ldb_mod_register_control: int (struct ldb_module *, const char *) +ldb_modify: int (struct ldb_context *, const struct ldb_message *) +ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *) +ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +ldb_module_flags: uint32_t (struct ldb_context *) +ldb_module_get_ctx: struct ldb_context *(struct ldb_module *) +ldb_module_get_name: const char *(struct ldb_module *) +ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *) +ldb_module_get_private: void *(struct ldb_module *) +ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *) +ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +ldb_module_next: struct ldb_module *(struct ldb_module *) +ldb_module_popt_options: struct poptOption **(struct ldb_context *) +ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **) +ldb_module_send_referral: int (struct ldb_request *, char *) +ldb_module_set_next: void (struct ldb_module *, struct ldb_module *) +ldb_module_set_private: void (struct ldb_module *, void *) +ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_modules_load: int (const char *, const char *) +ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int) +ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **) +ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...) +ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *) +ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *) +ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *) +ldb_msg_add_string: int (struct ldb_message *, const char *, const char *) +ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **) +ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *) +ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *) +ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *) +ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **) +ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *) +ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *) +ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double) +ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t) +ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *) +ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int) +ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t) +ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t) +ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *) +ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *) +ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *) +ldb_msg_new: struct ldb_message *(TALLOC_CTX *) +ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **) +ldb_msg_remove_attr: void (struct ldb_message *, const char *) +ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *) +ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *) +ldb_msg_sort_elements: void (struct ldb_message *) +ldb_next_del_trans: int (struct ldb_module *) +ldb_next_end_trans: int (struct ldb_module *) +ldb_next_init: int (struct ldb_module *) +ldb_next_prepare_commit: int (struct ldb_module *) +ldb_next_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: int (struct ldb_module *) +ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_start_trans: int (struct ldb_module *) +ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_options_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *) +ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *) +ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *) +ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *) +ldb_register_hook: int (ldb_hook_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *) +ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *) +ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *) +ldb_req_get_custom_flags: uint32_t (struct ldb_request *) +ldb_req_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_trusted: void (struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t) +ldb_req_set_location: void (struct ldb_request *, const char *) +ldb_request: int (struct ldb_context *, struct ldb_request *) +ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_done: int (struct ldb_request *, int) +ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *) +ldb_request_get_status: int (struct ldb_request *) +ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***) +ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *) +ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *) +ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *) +ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *) +ldb_schema_attribute_remove: void (struct ldb_context *, const char *) +ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int) +ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *) +ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...) +ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *) +ldb_set_create_perms: void (struct ldb_context *, unsigned int) +ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *) +ldb_set_debug_stderr: int (struct ldb_context *) +ldb_set_default_dns: void (struct ldb_context *) +ldb_set_errstring: void (struct ldb_context *, const char *) +ldb_set_event_context: void (struct ldb_context *, struct tevent_context *) +ldb_set_flags: void (struct ldb_context *, unsigned int) +ldb_set_modules_dir: void (struct ldb_context *, const char *) +ldb_set_opaque: int (struct ldb_context *, const char *, void *) +ldb_set_require_private_event_context: void (struct ldb_context *) +ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int) +ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *) +ldb_set_utf8_default: void (struct ldb_context *) +ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t)) +ldb_setup_wellknown_attributes: int (struct ldb_context *) +ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *) +ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_strerror: const char *(int) +ldb_string_to_time: time_t (const char *) +ldb_string_utc_to_time: time_t (const char *) +ldb_timestring: char *(TALLOC_CTX *, time_t) +ldb_timestring_utc: char *(TALLOC_CTX *, time_t) +ldb_transaction_cancel: int (struct ldb_context *) +ldb_transaction_cancel_noerr: int (struct ldb_context *) +ldb_transaction_commit: int (struct ldb_context *) +ldb_transaction_prepare_commit: int (struct ldb_context *) +ldb_transaction_start: int (struct ldb_context *) +ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *) +ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *) +ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *) +ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_string_cmp: int (const struct ldb_val *, const char *) +ldb_val_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/lib/ldb/ABI/pyldb-util-2.0.7.sigs b/lib/ldb/ABI/pyldb-util-2.0.7.sigs new file mode 100644 index 00000000000..74d6719d2bc --- /dev/null +++ b/lib/ldb/ABI/pyldb-util-2.0.7.sigs @@ -0,0 +1,2 @@ +pyldb_Dn_FromDn: PyObject *(struct ldb_dn *) +pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **) diff --git a/lib/ldb/wscript b/lib/ldb/wscript index f928e2c739c..750306fbddb 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'ldb' -VERSION = '2.0.6' +VERSION = '2.0.7' import sys, os -- 2.17.1 From 116f8cfe3041676264f2bfa2ca43d6266cb326ab Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Sep 2019 11:23:22 +1200 Subject: [PATCH 133/376] docs: Deprecate "lanman auth = yes" This feature is only available for SMB1 and we need to warn users that this is going away soon, and allow the removal in a future release under our rules for parameter deprecation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14117 Signed-off-by: Andrew Bartlett Reviewed-by: Garming Sam Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Thu Sep 5 04:04:18 UTC 2019 on sn-devel-184 (cherry picked from commit 1006f7abe8980d2c01c181db93225353ce494b3a) --- docs-xml/smbdotconf/security/lanmanauth.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs-xml/smbdotconf/security/lanmanauth.xml b/docs-xml/smbdotconf/security/lanmanauth.xml index 97f2fb04dcb..e5e63e43076 100644 --- a/docs-xml/smbdotconf/security/lanmanauth.xml +++ b/docs-xml/smbdotconf/security/lanmanauth.xml @@ -2,8 +2,17 @@ context="G" type="boolean" function="_lanman_auth" + deprecated="1" xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> + This parameter has been deprecated since Samba 4.11 and + support for LanMan (as distinct from NTLM, NTLMv2 or + Kerberos authentication) + will be removed in a future Samba release. + That is, in the future, the current default of + lanman auth = no + will be the enforced behaviour. + This parameter determines whether or not smbd 8 will attempt to authenticate users or permit password changes -- 2.17.1 From f1d2b5eba72df50f98860557e3d3523b1e82f625 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Sep 2019 11:19:10 +1200 Subject: [PATCH 134/376] docs: Deprecate "encrypt passwords = no" This feature is only available for SMB1 and we need to warn users that this is going away soon, and allow the removal in a future release under our rules for parameter deprecation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14117 Signed-off-by: Andrew Bartlett Reviewed-by: Garming Sam (cherry picked from commit 8d0d99a4d78ba408bb45e2d693049025e60e277a) --- docs-xml/smbdotconf/security/encryptpasswords.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs-xml/smbdotconf/security/encryptpasswords.xml b/docs-xml/smbdotconf/security/encryptpasswords.xml index 4bd97809d86..4fdfa898501 100644 --- a/docs-xml/smbdotconf/security/encryptpasswords.xml +++ b/docs-xml/smbdotconf/security/encryptpasswords.xml @@ -1,8 +1,16 @@ + This parameter has been deprecated since Samba 4.11 and + support for plaintext (as distinct from NTLM, NTLMv2 + or Kerberos authentication) + will be removed in a future Samba release. + That is, in the future, the current default of + encrypt passwords = yes + will be the enforced behaviour. This boolean controls whether encrypted passwords will be negotiated with the client. Note that Windows NT 4.0 SP3 and above and also Windows 98 will by default expect encrypted passwords -- 2.17.1 From 04867f4c513c70313f71c59ed3131307c0d1c4dc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Sep 2019 16:12:10 +1200 Subject: [PATCH 135/376] WHATSNEW: Add entry for deprecation of "lanman auth" and "encrypt passwords = no" BUG: https://bugzilla.samba.org/show_bug.cgi?id=14117 Signed-off-by: Andrew Bartlett --- WHATSNEW.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index eece43fcd9e..904db5fefc3 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -68,6 +68,18 @@ in the following years. If you have a strong requirement for SMB1 (except for supporting old Linux Kernels), please file a bug at https://bugzilla.samba.org and let us know about the details. +LanMan and plaintext authentication deprecated +---------------------------------------------- + +The "lanman auth" and "encrypt passwords" parameters are deprecated +with this release as both are only applicable to SMB1 and are quite +insecure. NTLM, NTLMv2 and Kerberos authentication are unaffected, as +"encrypt passwords = yes" has been the default since Samba 3.0.0. + +If you have a strong requirement for these authentication protocols, +please file a bug at https://bugzilla.samba.org and let us know about +the details. + BIND9_FLATFILE deprecated ------------------------- @@ -357,6 +369,8 @@ smb.conf changes fruit:zero_file_id Changed default False debug encryption New: dump encryption keys False rndc command Deprecated + lanman auth Deprecated + encrypt passwords Deprecated CHANGES SINCE 4.11.0rc2 -- 2.17.1 From 11c2b21b97d2d8fcd46c7e3ac8005e940869bc51 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 12 Jul 2019 10:49:13 +0200 Subject: [PATCH 136/376] ctdb: fix compilation on systems with glibc robust mutexes On older systems like SLES 11 without POSIX robust mutexes, but with glib robust mutexes where all the functions are available but have a "_np" suffix, compilation fails in: ctdb/tests/src/test_mutex_raw.c.239.o: In function `worker': /root/samba-4.10.6/bin/default/../../ctdb/tests/src/test_mutex_raw.c:129: undefined reference to `pthread_mutex_consistent' ctdb/tests/src/test_mutex_raw.c.239.o: In function `main': /root/samba-4.10.6/bin/default/../../ctdb/tests/src/test_mutex_raw.c:285: undefined reference to `pthread_mutex_consistent' /root/samba-4.10.6/bin/default/../../ctdb/tests/src/test_mutex_raw.c:332: undefined reference to `pthread_mutexattr_setrobust' /root/samba-4.10.6/bin/default/../../ctdb/tests/src/test_mutex_raw.c:363: undefined reference to `pthread_mutex_consistent' collect2: ld returned 1 exit status This could be fixed by using libreplace system/threads.h instead of pthreads.h directly, but as there has been a desire to keep test_mutex_raw.c standalone and compilable without other external depenencies then libc and libpthread, make the tool developer build only. This should get the average user over the cliff. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14038 RN: Fix compiling ctdb on older systems lacking POSIX robust mutexes Signed-off-by: Ralph Boehme Reviewed-by: Martin Schwenke (cherry picked from commit f5388f97792ac2d7962950dad91aaf8ad49bceaa) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Fri Sep 6 08:19:44 UTC 2019 on sn-devel-184 --- ctdb/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctdb/wscript b/ctdb/wscript index 51a09fdc63d..9663213a2a8 100644 --- a/ctdb/wscript +++ b/ctdb/wscript @@ -1040,7 +1040,7 @@ def build(bld): ib_deps, install_path='${CTDB_TEST_LIBEXECDIR}') - if bld.env.HAVE_ROBUST_MUTEXES and sys.platform.startswith('linux'): + if bld.env.HAVE_ROBUST_MUTEXES and sys.platform.startswith('linux') and bld.env.DEVELOPER: bld.SAMBA_BINARY('test_mutex_raw', source='tests/src/test_mutex_raw.c', deps='pthread', -- 2.17.1 From bff4ee33420557c6b80646a94de926d4f4c0f24d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Jul 2019 14:37:31 +0200 Subject: [PATCH 137/376] libcli/smb: add new COMPRESSION and NETNAME negotiate context ids BUG: https://bugzilla.samba.org/show_bug.cgi?id=14055 Signed-off-by: Stefan Metzmacher Reviewed-by: Aurelien Aptel (cherry picked from commit e10b90f33bb812600886656a1124e2d434416563) --- libcli/smb/smb2_constants.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h index 3dd462cdd69..1430f02689c 100644 --- a/libcli/smb/smb2_constants.h +++ b/libcli/smb/smb2_constants.h @@ -131,6 +131,8 @@ /* Types of SMB2 Negotiate Contexts - only in dialect >= 0x310 */ #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES 0x0001 #define SMB2_ENCRYPTION_CAPABILITIES 0x0002 +#define SMB2_COMPRESSION_CAPABILITIES 0x0003 +#define SMB2_NETNAME_NEGOTIATE_CONTEXT_ID 0x0005 /* Values for the SMB2_PREAUTH_INTEGRITY_CAPABILITIES Context (>= 0x310) */ #define SMB2_PREAUTH_INTEGRITY_SHA512 0x0001 -- 2.17.1 From d01dbe68cdfcd873f53c02c9529a944bf209c58f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Jul 2019 14:38:26 +0200 Subject: [PATCH 138/376] libcli/smb: send SMB2_NETNAME_NEGOTIATE_CONTEXT_ID Note: Unlike the current documentation, the utf16 string is not null-terminated, that matches Windows Server 1903 as a client. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14055 RN: Add the target server name of SMB 3.1.1 connections as a hint to load balancers or servers with "multi-tenancy" support. Signed-off-by: Stefan Metzmacher Reviewed-by: Aurelien Aptel (cherry picked from commit 21f6cece543dd791e0f4636458bfe9819823420c) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Mon Sep 9 12:03:55 UTC 2019 on sn-devel-184 --- libcli/smb/smbXcli_base.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 2f5fac08128..c9b396106ae 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -4770,6 +4770,8 @@ static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_sta if (state->conn->max_protocol >= PROTOCOL_SMB3_10) { NTSTATUS status; struct smb2_negotiate_contexts c = { .num_contexts = 0, }; + uint8_t *netname_utf16 = NULL; + size_t netname_utf16_len = 0; uint32_t offset; DATA_BLOB b; uint8_t p[38]; @@ -4802,6 +4804,21 @@ static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_sta return NULL; } + ok = convert_string_talloc(state, CH_UNIX, CH_UTF16, + state->conn->remote_name, + strlen(state->conn->remote_name), + &netname_utf16, &netname_utf16_len); + if (!ok) { + return NULL; + } + + status = smb2_negotiate_context_add(state, &c, + SMB2_NETNAME_NEGOTIATE_CONTEXT_ID, + netname_utf16, netname_utf16_len); + if (!NT_STATUS_IS_OK(status)) { + return NULL; + } + status = smb2_negotiate_context_push(state, &b, c); if (!NT_STATUS_IS_OK(status)) { return NULL; -- 2.17.1 From 728e29d84ca594a5607f072e50de60deaa9da45e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Sep 2019 12:50:06 +0200 Subject: [PATCH 139/376] s3:blocking: call change_to_user_by_fsp() when dbwrap_watched_watch* finishes This is not strictly required as fd-based calls are used, but it's more consistent to call SMB_VFS_BRL_LOCK_WINDOWS() in the same environment on retry. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 28ac2cbaf92a8619f0380f024c5a220d9fdc4622) --- source3/smbd/blocking.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ffc3142b74c..ca8a625ba9d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -334,6 +334,15 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq) NTSTATUS status; bool ok; + /* + * Make sure we run as the user again + */ + ok = change_to_user_by_fsp(state->fsp); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + status = dbwrap_watched_watch_recv(subreq, NULL, NULL); TALLOC_FREE(subreq); -- 2.17.1 From 80a04a4e19adfe87c5217d75b11e41763f644749 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Sep 2019 12:47:07 +0200 Subject: [PATCH 140/376] s3:smb2_lock: call change_to_user_by_fsp() when dbwrap_watched_watch* finishes This is not strictly required as fd-based calls are used, but it's more consistent to call SMB_VFS_BRL_LOCK_WINDOWS() in the same environment on retry. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8b565de1acb0fda121cb0bd4cff42d66ee027529) --- source3/smbd/smb2_lock.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 36ec36301b1..e9c8d7f890e 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -421,6 +421,16 @@ static void smbd_smb2_lock_retry(struct tevent_req *subreq) struct server_id blocking_pid = { 0 }; uint64_t blocking_smblctx; NTSTATUS status; + bool ok; + + /* + * Make sure we run as the user again + */ + ok = change_to_user_by_fsp(state->fsp); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } status = dbwrap_watched_watch_recv(subreq, NULL, NULL); TALLOC_FREE(subreq); -- 2.17.1 From 244ad1210cc29ede25fb8692bae46aab7d6725ac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Sep 2019 08:43:32 +0200 Subject: [PATCH 141/376] s3:locking: add/split out byte_range_{valid,overlap}() helper functions They implement the logic from [MS-FSA]. The following commits will use these functions in other locations. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 0e5613e39d6c6bb892fed939c63b4f14b878803b) --- source3/locking/brlock.c | 109 +++++++++++++++++++++++++++++++++------ source3/locking/proto.h | 6 +++ 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index cdfd09ceff1..628c2574357 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -96,6 +96,92 @@ static bool brl_same_context(const struct lock_context *ctx1, (ctx1->tid == ctx2->tid)); } +bool byte_range_valid(uint64_t ofs, uint64_t len) +{ + uint64_t max_len = UINT64_MAX - ofs; + uint64_t effective_len; + + /* + * [MS-FSA] specifies this: + * + * If (((FileOffset + Length - 1) < FileOffset) && Length != 0) { + * return STATUS_INVALID_LOCK_RANGE + * } + * + * We avoid integer wrapping and calculate + * max and effective len instead. + */ + + if (len == 0) { + return true; + } + + effective_len = len - 1; + if (effective_len <= max_len) { + return true; + } + + return false; +} + +bool byte_range_overlap(uint64_t ofs1, + uint64_t len1, + uint64_t ofs2, + uint64_t len2) +{ + uint64_t last1; + uint64_t last2; + bool valid; + + /* + * This is based on [MS-FSA] 2.1.4.10 + * Algorithm for Determining If a Range Access + * Conflicts with Byte-Range Locks + */ + + /* + * The {0, 0} range doesn't conflict with any byte-range lock + */ + if (ofs1 == 0 && len1 == 0) { + return false; + } + if (ofs2 == 0 && len2 == 0) { + return false; + } + + /* + * The caller should have checked that the ranges are + * valid. But currently we gracefully handle + * the overflow of a read/write check. + */ + valid = byte_range_valid(ofs1, len1); + if (valid) { + last1 = ofs1 + len1 - 1; + } else { + last1 = UINT64_MAX; + } + valid = byte_range_valid(ofs2, len2); + if (valid) { + last2 = ofs2 + len2 - 1; + } else { + last2 = UINT64_MAX; + } + + /* + * If one range starts after the last + * byte of the other range there's + * no conflict. + */ + if (ofs1 > last2) { + return false; + } + if (ofs2 > last1) { + return false; + } + + return true; +} + /**************************************************************************** See if lck1 and lck2 overlap. ****************************************************************************/ @@ -103,20 +189,10 @@ static bool brl_same_context(const struct lock_context *ctx1, static bool brl_overlap(const struct lock_struct *lck1, const struct lock_struct *lck2) { - /* XXX Remove for Win7 compatibility. */ - /* this extra check is not redundant - it copes with locks - that go beyond the end of 64 bit file space */ - if (lck1->size != 0 && - lck1->start == lck2->start && - lck1->size == lck2->size) { - return True; - } - - if (lck1->start >= (lck2->start+lck2->size) || - lck2->start >= (lck1->start+lck1->size)) { - return False; - } - return True; + return byte_range_overlap(lck1->start, + lck1->size, + lck2->start, + lck2->size); } /**************************************************************************** @@ -336,11 +412,12 @@ NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck, files_struct *fsp = br_lck->fsp; struct lock_struct *locks = br_lck->lock_data; NTSTATUS status; + bool valid; SMB_ASSERT(plock->lock_type != UNLOCK_LOCK); - if ((plock->start + plock->size - 1 < plock->start) && - plock->size != 0) { + valid = byte_range_valid(plock->start, plock->size); + if (!valid) { return NT_STATUS_INVALID_LOCK_RANGE; } diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 3a086fa0516..2487fa5d14d 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -31,6 +31,12 @@ void brl_shutdown(void); unsigned int brl_num_locks(const struct byte_range_lock *brl); struct files_struct *brl_fsp(struct byte_range_lock *brl); +bool byte_range_valid(uint64_t ofs, uint64_t len); +bool byte_range_overlap(uint64_t ofs1, + uint64_t len1, + uint64_t ofs2, + uint64_t len2); + NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck, struct lock_struct *plock); -- 2.17.1 From f73b670b4db103069aa151d3af4ed7a92ce581c3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Aug 2019 00:47:39 +0200 Subject: [PATCH 142/376] s3:locking: add share_mode_wakeup_waiters() helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit bd8884e5722cbbb7783fb4ae53e4f35b31031b01) --- source3/locking/proto.h | 1 + source3/locking/share_mode_lock.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 2487fa5d14d..7cb8bf3e3c9 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -138,6 +138,7 @@ NTSTATUS share_mode_do_locked( bool *modified_dependent, void *private_data), void *private_data); +NTSTATUS share_mode_wakeup_waiters(struct file_id id); struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, struct file_id id); diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 430d14fab4a..372e188c1c0 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -771,6 +771,18 @@ NTSTATUS share_mode_do_locked( return NT_STATUS_OK; } +static void share_mode_wakeup_waiters_fn(struct db_record *rec, + bool *modified_dependent, + void *private_data) +{ + *modified_dependent = true; +} + +NTSTATUS share_mode_wakeup_waiters(struct file_id id) +{ + return share_mode_do_locked(id, share_mode_wakeup_waiters_fn, NULL); +} + struct fetch_share_mode_unlocked_state { TALLOC_CTX *mem_ctx; struct share_mode_lock *lck; -- 2.17.1 From 75e07d485944fdc76a6510bf5d450959475e7e5b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 19:19:07 +0200 Subject: [PATCH 143/376] s3:blocking: remove unused timeval_brl_min() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 3b788d97f9995e24e4005567f90a925957fb1e00) --- source3/smbd/blocking.c | 16 ---------------- source3/smbd/proto.h | 2 -- 2 files changed, 18 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ca8a625ba9d..cdc4613270e 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -28,22 +28,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING -/**************************************************************************** - We need a version of timeval_min that treats zero timval as infinite. -****************************************************************************/ - -struct timeval timeval_brl_min(const struct timeval *tv1, - const struct timeval *tv2) -{ - if (timeval_is_zero(tv1)) { - return *tv2; - } - if (timeval_is_zero(tv2)) { - return *tv1; - } - return timeval_min(tv1, tv2); -} - NTSTATUS smbd_do_locks_try( struct files_struct *fsp, enum brl_flavour lock_flav, diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 37eeb9f31ca..b59f1f4123d 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -95,8 +95,6 @@ bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req); /* The following definitions come from smbd/blocking.c */ -struct timeval timeval_brl_min(const struct timeval *tv1, - const struct timeval *tv2); NTSTATUS smbd_do_locks_try( struct files_struct *fsp, enum brl_flavour lock_flav, -- 2.17.1 From 0742879bd8d03333b8b7c2a790afebdb5f7dd92b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 16:10:58 +0200 Subject: [PATCH 144/376] s3:torture: fix the timeout alarm handling on LOCK9 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK) means existing requests are not finished with an error, but instead just keep dangling arround. Pass NT_STATUS_LOCAL_DISCONNECT in order to fail the cli_lock32() call after getting SIGALARM. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit e18c8ced8e7a872deb118191595425ef6b826bfa) --- source3/torture/torture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index f26c634b7a7..5a75796928a 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -2543,7 +2543,7 @@ static void alarm_handler(int dummy) static void alarm_handler_parent(int dummy) { - smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK); + smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT); } static void do_local_lock(int read_fd, int write_fd) -- 2.17.1 From ffdb166e49fa1a786ac1ea4e1ab09c286e75af69 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 14:31:54 +0200 Subject: [PATCH 145/376] s3:torture: convert LOCK9 into LOCK9A and LOCK9B LOCK9A is the original test (with a timeout of -1) and LOCK9B is the same but with timeout of 10 seconds. LOCK9B is needed to demonstrate a server bug in the next commits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit ac28eec3e4af710feab3be3d4b25bfbe38294431) --- selftest/skip | 2 +- source3/selftest/tests.py | 3 ++- source3/torture/torture.c | 38 ++++++++++++++++++++++++++------------ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/selftest/skip b/selftest/skip index 1e7448acb9f..c471072e88f 100644 --- a/selftest/skip +++ b/selftest/skip @@ -34,7 +34,7 @@ ^samba3.smbtorture_s3.*.pipe_number ^samba3.smbtorture_s3.LOCAL-DBTRANS #hangs for some reason ^samba3.smbtorture_s3.*.DIR1 #loops on 64 bit linux with ext4 -^samba3.smbtorture_s3.plain.LOCK9\(ad_dc_ntvfs\) # Fails against the s4 ntvfs server +^samba3.smbtorture_s3.plain.LOCK9.*\(ad_dc_ntvfs\) # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain.OPLOCK2\(ad_dc_ntvfs\) # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain.STREAMERROR\(ad_dc_ntvfs\) # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain.DIR1\(ad_dc_ntvfs\) # Fails against the s4 ntvfs server diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 9569aa9ae00..a3daeacae6b 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -78,7 +78,8 @@ plantestsuite("samba3.local_s3", "nt4_dc:local", [os.path.join(samba3srcdir, "sc plantestsuite("samba3.blackbox.registry.upgrade", "nt4_dc:local", [os.path.join(samba3srcdir, "script/tests/test_registry_upgrade.sh"), net, dbwrap_tool]) -tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7", "LOCK9", +tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7", + "LOCK9A", "LOCK9B", "LOCK10", "LOCK11", "LOCK12", diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 5a75796928a..66dc0cf4d1c 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -2546,7 +2546,7 @@ static void alarm_handler_parent(int dummy) smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT); } -static void do_local_lock(int read_fd, int write_fd) +static void do_local_lock(const char *fname, int read_fd, int write_fd) { int fd; char c = '\0'; @@ -2555,7 +2555,7 @@ static void do_local_lock(int read_fd, int write_fd) int ret; local_pathname = talloc_asprintf(talloc_tos(), - "%s/lockt9.lck", local_path); + "%s/%s", local_path, fname); if (!local_pathname) { printf("child: alloc fail\n"); exit(1); @@ -2614,10 +2614,10 @@ static void do_local_lock(int read_fd, int write_fd) exit(0); } -static bool run_locktest9(int dummy) +static bool _run_locktest9X(const char *fname, int timeout) { struct cli_state *cli1; - const char *fname = "\\lockt9.lck"; + char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname); uint16_t fnum; bool correct = False; int pipe_in[2], pipe_out[2]; @@ -2628,10 +2628,10 @@ static bool run_locktest9(int dummy) double seconds; NTSTATUS status; - printf("starting locktest9\n"); + printf("starting locktest9X: %s\n", fname); if (local_path == NULL) { - d_fprintf(stderr, "locktest9 must be given a local path via -l \n"); + d_fprintf(stderr, "locktest9X must be given a local path via -l \n"); return false; } @@ -2646,7 +2646,7 @@ static bool run_locktest9(int dummy) if (child_pid == 0) { /* Child. */ - do_local_lock(pipe_out[0], pipe_in[1]); + do_local_lock(fname, pipe_out[0], pipe_in[1]); exit(0); } @@ -2669,7 +2669,7 @@ static bool run_locktest9(int dummy) smbXcli_conn_set_sockopt(cli1->conn, sockops); - status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, + status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE, &fnum); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status)); @@ -2700,7 +2700,7 @@ static bool run_locktest9(int dummy) start = timeval_current(); - status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK); + status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was " "%s\n", nt_errstr(status)); @@ -2727,10 +2727,20 @@ fail: fail_nofd: - printf("finished locktest9\n"); + printf("finished locktest9X: %s\n", fname); return correct; } +static bool run_locktest9a(int dummy) +{ + return _run_locktest9X("lock9a.dat", -1); +} + +static bool run_locktest9b(int dummy) +{ + return _run_locktest9X("lock9b.dat", 10000); +} + struct locktest10_state { bool ok; bool done; @@ -13651,8 +13661,12 @@ static struct { .fn = run_locktest8, }, { - .name = "LOCK9", - .fn = run_locktest9, + .name = "LOCK9A", + .fn = run_locktest9a, + }, + { + .name = "LOCK9B", + .fn = run_locktest9b, }, { .name = "LOCK10", -- 2.17.1 From 841fceae68098160627066dd6bd180948c048d96 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 11:09:47 +0200 Subject: [PATCH 146/376] s3:blocking: demonstrate the posix lock retry fails This is just a temporary commit that shows the bug and its fix. It will be reverted once the problem is fixed. The posix lock retry fails if the client specified timeout is smaller than the hardcoded 1 second retry. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 2ec9e93a7aac2706b4a5931495d56a7b64f8d894) --- selftest/knownfail.d/lock9 | 1 + source3/smbd/blocking.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 selftest/knownfail.d/lock9 diff --git a/selftest/knownfail.d/lock9 b/selftest/knownfail.d/lock9 new file mode 100644 index 00000000000..044622586eb --- /dev/null +++ b/selftest/knownfail.d/lock9 @@ -0,0 +1 @@ +^samba3.smbtorture_s3.*.LOCK9B diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index cdc4613270e..91438fe4486 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -236,7 +236,7 @@ struct tevent_req *smbd_smb1_do_locks_send( DBG_DEBUG("Blocked on a posix lock. Retry in one second\n"); - tmp = timeval_current_ofs(1, 0); + tmp = timeval_current_ofs(15, 0); endtime = timeval_min(&endtime, &tmp); } @@ -381,7 +381,7 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq) DBG_DEBUG("Blocked on a posix lock. Retry in one second\n"); - tmp = timeval_current_ofs(1, 0); + tmp = timeval_current_ofs(15, 0); endtime = timeval_min(&endtime, &tmp); } -- 2.17.1 From b381f4b314c71c446a847de7cdb5baa658455c90 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 18:34:36 +0200 Subject: [PATCH 147/376] s3:blocking: split smbd_smb1_do_locks_retry() into _try() and _retry() This will make it possible to have just one caller to smbd_do_locks_try() later and use smbd_smb1_do_locks_try() from within smbd_smb1_do_locks_send(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Reviewed-by: Volker Lendecke Signed-off-by: Stefan Metzmacher (cherry picked from commit e79fcfaaf2ecfca6c3747f6fe4be51f332ebf10d) --- source3/smbd/blocking.c | 72 ++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 91438fe4486..0fa39ae58ab 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -109,6 +109,7 @@ struct smbd_smb1_do_locks_state { uint16_t blocker; }; +static void smbd_smb1_do_locks_try(struct tevent_req *req); static void smbd_smb1_do_locks_retry(struct tevent_req *subreq); static void smbd_smb1_blocked_locks_cleanup( struct tevent_req *req, enum tevent_req_state req_state); @@ -300,10 +301,8 @@ static void smbd_smb1_blocked_locks_cleanup( fsp, blocked, struct tevent_req *, num_blocked-1); } -static void smbd_smb1_do_locks_retry(struct tevent_req *subreq) +static void smbd_smb1_do_locks_try(struct tevent_req *req) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); struct smbd_smb1_do_locks_state *state = tevent_req_data( req, struct smbd_smb1_do_locks_state); struct files_struct *fsp = state->fsp; @@ -315,36 +314,10 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq) struct timeval endtime; struct server_id blocking_pid = { 0 }; uint64_t blocking_smblctx = 0; + struct tevent_req *subreq = NULL; NTSTATUS status; bool ok; - /* - * Make sure we run as the user again - */ - ok = change_to_user_by_fsp(state->fsp); - if (!ok) { - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - - status = dbwrap_watched_watch_recv(subreq, NULL, NULL); - TALLOC_FREE(subreq); - - DBG_DEBUG("dbwrap_watched_watch_recv returned %s\n", - nt_errstr(status)); - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - double elapsed = timeval_elapsed(&state->endtime); - if (elapsed > 0) { - smbd_smb1_brl_finish_by_req( - req, NT_STATUS_FILE_LOCK_CONFLICT); - return; - } - /* - * This is a posix lock retry. Just retry. - */ - } - lck = get_existing_share_mode_lock(state, fsp->file_id); if (tevent_req_nomem(lck, req)) { DBG_DEBUG("Could not get share mode lock\n"); @@ -396,6 +369,45 @@ done: smbd_smb1_brl_finish_by_req(req, status); } +static void smbd_smb1_do_locks_retry(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smbd_smb1_do_locks_state *state = tevent_req_data( + req, struct smbd_smb1_do_locks_state); + NTSTATUS status; + bool ok; + + /* + * Make sure we run as the user again + */ + ok = change_to_user_by_fsp(state->fsp); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + + status = dbwrap_watched_watch_recv(subreq, NULL, NULL); + TALLOC_FREE(subreq); + + DBG_DEBUG("dbwrap_watched_watch_recv returned %s\n", + nt_errstr(status)); + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + double elapsed = timeval_elapsed(&state->endtime); + if (elapsed > 0) { + smbd_smb1_brl_finish_by_req( + req, NT_STATUS_FILE_LOCK_CONFLICT); + return; + } + /* + * This is a posix lock retry. Just retry. + */ + } + + smbd_smb1_do_locks_try(req); +} + NTSTATUS smbd_smb1_do_locks_recv(struct tevent_req *req) { struct smbd_smb1_do_locks_state *state = tevent_req_data( -- 2.17.1 From 6b23f24ee383763c45af8c627df09060d76d9dd8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 18:34:36 +0200 Subject: [PATCH 148/376] s3:blocking: move from 'timeout' to 'smbd_smb1_do_locks_state->timeout' This will make it possible to just use smbd_smb1_do_locks_try() in a later commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8fe708acb43ea36d0cbf398713b125daba180a2d) --- source3/smbd/blocking.c | 20 +++++++++++--------- source3/smbd/proto.h | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 0fa39ae58ab..81facc43154 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -101,6 +101,7 @@ struct smbd_smb1_do_locks_state { struct tevent_context *ev; struct smb_request *smbreq; struct files_struct *fsp; + uint32_t timeout; struct timeval endtime; bool large_offset; /* required for correct cancel */ enum brl_flavour lock_flav; @@ -119,7 +120,7 @@ struct tevent_req *smbd_smb1_do_locks_send( struct tevent_context *ev, struct smb_request **smbreq, /* talloc_move()d into our state */ struct files_struct *fsp, - uint32_t timeout, + uint32_t lock_timeout, bool large_offset, enum brl_flavour lock_flav, uint16_t num_locks, @@ -142,6 +143,7 @@ struct tevent_req *smbd_smb1_do_locks_send( state->ev = ev; state->smbreq = talloc_move(state, smbreq); state->fsp = fsp; + state->timeout = lock_timeout; state->large_offset = large_offset; state->lock_flav = lock_flav; state->num_locks = num_locks; @@ -155,13 +157,13 @@ struct tevent_req *smbd_smb1_do_locks_send( return tevent_req_post(req, ev); } - if ((timeout != 0) && (timeout != UINT32_MAX)) { + if ((state->timeout != 0) && (state->timeout != UINT32_MAX)) { /* * Windows internal resolution for blocking locks * seems to be about 200ms... Don't wait for less than * that. JRA. */ - timeout = MAX(timeout, lp_lock_spin_time()); + state->timeout = MAX(state->timeout, lp_lock_spin_time()); } lck = get_existing_share_mode_lock(state, state->fsp->file_id); @@ -187,7 +189,7 @@ struct tevent_req *smbd_smb1_do_locks_send( goto done; } - if (timeout == 0) { + if (state->timeout == 0) { struct smbd_lock_element *blocker = &locks[state->blocker]; if ((blocker->offset >= 0xEF000000) && @@ -196,7 +198,7 @@ struct tevent_req *smbd_smb1_do_locks_send( * This must be an optimization of an ancient * application bug... */ - timeout = lp_lock_spin_time(); + state->timeout = lp_lock_spin_time(); } if ((fsp->lock_failure_seen) && @@ -208,15 +210,15 @@ struct tevent_req *smbd_smb1_do_locks_send( */ DBG_DEBUG("Delaying lock request due to previous " "failure\n"); - timeout = lp_lock_spin_time(); + state->timeout = lp_lock_spin_time(); } } DBG_DEBUG("timeout=%"PRIu32", blocking_smblctx=%"PRIu64"\n", - timeout, + state->timeout, blocking_smblctx); - if (timeout == 0) { + if (state->timeout == 0) { tevent_req_nterror(req, status); goto done; } @@ -229,7 +231,7 @@ struct tevent_req *smbd_smb1_do_locks_send( TALLOC_FREE(lck); tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); - state->endtime = timeval_current_ofs_msec(timeout); + state->endtime = timeval_current_ofs_msec(state->timeout); endtime = state->endtime; if (blocking_smblctx == UINT64_MAX) { diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index b59f1f4123d..cd1ec9a1f9e 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -108,7 +108,7 @@ struct tevent_req *smbd_smb1_do_locks_send( struct tevent_context *ev, struct smb_request **smbreq, /* talloc_move()d into our state */ struct files_struct *fsp, - uint32_t timeout, + uint32_t lock_timeout, bool large_offset, enum brl_flavour lock_flav, uint16_t num_locks, -- 2.17.1 From 2c31c9d365d3aaa323e10abff15fc4404a4a52dd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 14:21:38 +0200 Subject: [PATCH 149/376] s3:blocking: fix posix lock retry We should evaluate the timeout condition after the very last retry and not before. Otherwise we'd fail to retry when waiting for posix locks. The problem happens if the client provided timeout is smaller than the 1 sec (for testing temporary 15 secs) retry. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit e8d719d31f885d7b6d5b317165f90ec40df169c9) --- selftest/knownfail.d/lock9 | 1 - source3/smbd/blocking.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) delete mode 100644 selftest/knownfail.d/lock9 diff --git a/selftest/knownfail.d/lock9 b/selftest/knownfail.d/lock9 deleted file mode 100644 index 044622586eb..00000000000 --- a/selftest/knownfail.d/lock9 +++ /dev/null @@ -1 +0,0 @@ -^samba3.smbtorture_s3.*.LOCK9B diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 81facc43154..587923aa5ec 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -319,6 +319,7 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) struct tevent_req *subreq = NULL; NTSTATUS status; bool ok; + double elapsed; lck = get_existing_share_mode_lock(state, fsp->file_id); if (tevent_req_nomem(lck, req)) { @@ -341,6 +342,24 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) goto done; } + /* + * The client specified timeout elapsed + * avoid further retries. + * + * Otherwise keep waiting either waiting + * for changes in locking.tdb or the polling + * mode timers waiting for posix locks. + */ + elapsed = timeval_elapsed(&state->endtime); + if (elapsed > 0) { + /* + * On timeout we always return + * NT_STATUS_FILE_LOCK_CONFLICT + */ + status = NT_STATUS_FILE_LOCK_CONFLICT; + goto done; + } + subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); if (tevent_req_nomem(subreq, req)) { @@ -395,17 +414,12 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq) DBG_DEBUG("dbwrap_watched_watch_recv returned %s\n", nt_errstr(status)); - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - double elapsed = timeval_elapsed(&state->endtime); - if (elapsed > 0) { - smbd_smb1_brl_finish_by_req( - req, NT_STATUS_FILE_LOCK_CONFLICT); - return; - } - /* - * This is a posix lock retry. Just retry. - */ - } + /* + * We ignore any errors here, it's most likely + * we just get NT_STATUS_OK or NT_STATUS_IO_TIMEOUT. + * + * In any case we can just give it a retry. + */ smbd_smb1_do_locks_try(req); } -- 2.17.1 From e91bae2bdb11c8466a42ae51660bb564de1aedc2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 16:44:11 +0200 Subject: [PATCH 150/376] s3:blocking: Remove bug reproducer from a few commits ago The problem is fixed, now we can revert the change that made it easier to trigger. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 62ec58b06c38ee82bb3147c4d325413fd3a76499) --- source3/smbd/blocking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 587923aa5ec..af889a10d62 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -239,7 +239,7 @@ struct tevent_req *smbd_smb1_do_locks_send( DBG_DEBUG("Blocked on a posix lock. Retry in one second\n"); - tmp = timeval_current_ofs(15, 0); + tmp = timeval_current_ofs(1, 0); endtime = timeval_min(&endtime, &tmp); } @@ -375,7 +375,7 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) DBG_DEBUG("Blocked on a posix lock. Retry in one second\n"); - tmp = timeval_current_ofs(15, 0); + tmp = timeval_current_ofs(1, 0); endtime = timeval_min(&endtime, &tmp); } -- 2.17.1 From 1fd0a52e6727b191aa008f7a260ad748d34d5870 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 17:26:43 +0200 Subject: [PATCH 151/376] s3:blocking: use dynamic posix lock wait intervals We want to start with a short timeout (200ms) and slow down to larger timeouts up to 2s for the default value of "lock spin time". BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 15765644d2590d6549f8fcc01c39c56387eed654) --- source3/smbd/blocking.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index af889a10d62..50e1d436eb7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -102,6 +102,7 @@ struct smbd_smb1_do_locks_state { struct smb_request *smbreq; struct files_struct *fsp; uint32_t timeout; + uint32_t polling_msecs; struct timeval endtime; bool large_offset; /* required for correct cancel */ enum brl_flavour lock_flav; @@ -115,6 +116,32 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq); static void smbd_smb1_blocked_locks_cleanup( struct tevent_req *req, enum tevent_req_state req_state); +static void smbd_smb1_do_locks_update_polling_msecs( + struct smbd_smb1_do_locks_state *state) +{ + /* + * The default lp_lock_spin_time() is 200ms. + * + * v_min is in the range of 0.002 to 20 secs + * (0.2 secs by default) + * + * v_max is in the range of 0.02 to 200 secs + * (2.0 secs by default) + * + * The typical steps are: + * 0.2, 0.4, 0.6, 0.8, ... 2.0 + */ + uint32_t v_min = MAX(2, MIN(20000, lp_lock_spin_time())); + uint32_t v_max = 10 * v_min; + + if (state->polling_msecs >= v_max) { + state->polling_msecs = v_max; + return; + } + + state->polling_msecs += v_min; +} + struct tevent_req *smbd_smb1_do_locks_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -237,9 +264,12 @@ struct tevent_req *smbd_smb1_do_locks_send( if (blocking_smblctx == UINT64_MAX) { struct timeval tmp; - DBG_DEBUG("Blocked on a posix lock. Retry in one second\n"); + smbd_smb1_do_locks_update_polling_msecs(state); + + DBG_DEBUG("Blocked on a posix lock. Retry in %"PRIu32" msecs\n", + state->polling_msecs); - tmp = timeval_current_ofs(1, 0); + tmp = timeval_current_ofs_msec(state->polling_msecs); endtime = timeval_min(&endtime, &tmp); } @@ -373,9 +403,12 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) if (blocking_smblctx == UINT64_MAX) { struct timeval tmp; - DBG_DEBUG("Blocked on a posix lock. Retry in one second\n"); + smbd_smb1_do_locks_update_polling_msecs(state); + + DBG_DEBUG("Blocked on a posix lock. Retry in %"PRIu32" msecs\n", + state->polling_msecs); - tmp = timeval_current_ofs(1, 0); + tmp = timeval_current_ofs_msec(state->polling_msecs); endtime = timeval_min(&endtime, &tmp); } -- 2.17.1 From 85b9b5f04fdf7fa432f7260b27f77342f27dddbb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 16:30:16 +0200 Subject: [PATCH 152/376] s4:torture/raw: assert to get LOCK_NOT_GRANTED in torture_samba3_posixtimedlock() There should not be a different if the blocker is a posix process instead of another smbd. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 2a77025a1e16d897281e5840192c93fa03328681) --- selftest/knownfail.d/samba3posixtimedlock | 1 + source4/torture/raw/samba3misc.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 selftest/knownfail.d/samba3posixtimedlock diff --git a/selftest/knownfail.d/samba3posixtimedlock b/selftest/knownfail.d/samba3posixtimedlock new file mode 100644 index 00000000000..56d2d349e1e --- /dev/null +++ b/selftest/knownfail.d/samba3posixtimedlock @@ -0,0 +1 @@ +^samba3.raw.samba3posixtimedlock.samba3posixtimedlock diff --git a/source4/torture/raw/samba3misc.c b/source4/torture/raw/samba3misc.c index dc460b9cd8b..2f484023bea 100644 --- a/source4/torture/raw/samba3misc.c +++ b/source4/torture/raw/samba3misc.c @@ -775,8 +775,8 @@ static void receive_lock_result(struct smbcli_request *req) } /* - * Check that Samba3 correctly deals with conflicting posix byte range locks - * on an underlying file + * Check that Samba3 correctly deals with conflicting local posix byte range + * locks on an underlying file via "normal" SMB1 (without unix extentions). * * Note: This test depends on "posix locking = yes". * Note: To run this test, use "--option=torture:localdir=" @@ -873,7 +873,7 @@ bool torture_samba3_posixtimedlock(struct torture_context *tctx, struct smbcli_s status = smb_raw_lock(cli->tree, &io); ret = true; - CHECK_STATUS(tctx, status, NT_STATUS_FILE_LOCK_CONFLICT); + CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED); if (!ret) { goto done; -- 2.17.1 From b56bb2ac59dd190cdf3c726a7becf2ae9d296657 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 12:04:43 +0200 Subject: [PATCH 153/376] s3:blocking: maintain state->deny_status For Windows locks we start with LOCK_NOT_GRANTED and use FILE_LOCK_CONFLICT if we retried after a timeout. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit aba0ee46258f3dd910421facb742fce3318a6946) --- selftest/knownfail.d/samba3posixtimedlock | 1 - source3/smbd/blocking.c | 33 +++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) delete mode 100644 selftest/knownfail.d/samba3posixtimedlock diff --git a/selftest/knownfail.d/samba3posixtimedlock b/selftest/knownfail.d/samba3posixtimedlock deleted file mode 100644 index 56d2d349e1e..00000000000 --- a/selftest/knownfail.d/samba3posixtimedlock +++ /dev/null @@ -1 +0,0 @@ -^samba3.raw.samba3posixtimedlock.samba3posixtimedlock diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 50e1d436eb7..a87d62d910a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -109,6 +109,7 @@ struct smbd_smb1_do_locks_state { uint16_t num_locks; struct smbd_lock_element *locks; uint16_t blocker; + NTSTATUS deny_status; }; static void smbd_smb1_do_locks_try(struct tevent_req *req); @@ -176,6 +177,16 @@ struct tevent_req *smbd_smb1_do_locks_send( state->num_locks = num_locks; state->locks = locks; + if (lock_flav == POSIX_LOCK) { + /* + * SMB1 posix locks always use + * NT_STATUS_FILE_LOCK_CONFLICT. + */ + state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; + } else { + state->deny_status = NT_STATUS_LOCK_NOT_GRANTED; + } + DBG_DEBUG("state=%p, state->smbreq=%p\n", state, state->smbreq); if (num_locks == 0) { @@ -245,10 +256,19 @@ struct tevent_req *smbd_smb1_do_locks_send( state->timeout, blocking_smblctx); + /* + * If the endtime is not elapsed yet, + * it means we'll retry after a timeout. + * In that case we'll have to return + * NT_STATUS_FILE_LOCK_CONFLICT + * instead of NT_STATUS_LOCK_NOT_GRANTED. + */ if (state->timeout == 0) { + status = state->deny_status; tevent_req_nterror(req, status); goto done; } + state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); @@ -379,16 +399,19 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) * Otherwise keep waiting either waiting * for changes in locking.tdb or the polling * mode timers waiting for posix locks. + * + * If the endtime is not expired yet, + * it means we'll retry after a timeout. + * In that case we'll have to return + * NT_STATUS_FILE_LOCK_CONFLICT + * instead of NT_STATUS_LOCK_NOT_GRANTED. */ elapsed = timeval_elapsed(&state->endtime); if (elapsed > 0) { - /* - * On timeout we always return - * NT_STATUS_FILE_LOCK_CONFLICT - */ - status = NT_STATUS_FILE_LOCK_CONFLICT; + status = state->deny_status; goto done; } + state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); -- 2.17.1 From 8b3a50609f430ec08add2bbac77b106a585d97c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 12:33:28 +0200 Subject: [PATCH 154/376] s3:brlock: always return LOCK_NOT_GRANTED instead of FILE_LOCK_CONFLICT Returning NT_STATUS_FILE_LOCK_CONFLICT is a SMB1 only detail for delayed brlock requests, which is handled in smbd_smb1_do_locks*(). The brlock layer should be consistent even for posix locks. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Signed-off-by: Volker Lendecke (cherry picked from commit ad98eec6090430ba5296a5111dde2e53b9cd217a) --- source3/locking/brlock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 628c2574357..0a85bd0b057 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -462,7 +462,7 @@ NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck, plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL; if (errno_ret == EACCES || errno_ret == EAGAIN) { - status = NT_STATUS_FILE_LOCK_CONFLICT; + status = NT_STATUS_LOCK_NOT_GRANTED; goto fail; } else { status = map_nt_error_from_unix(errno); @@ -829,7 +829,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, TALLOC_FREE(tp); /* Remember who blocked us. */ plock->context.smblctx = curr_lock->context.smblctx; - return NT_STATUS_FILE_LOCK_CONFLICT; + return NT_STATUS_LOCK_NOT_GRANTED; } /* Just copy the Windows lock into the new array. */ memcpy(&tp[count], curr_lock, sizeof(struct lock_struct)); @@ -849,7 +849,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, TALLOC_FREE(tp); /* Remember who blocked us. */ plock->context.smblctx = curr_lock->context.smblctx; - return NT_STATUS_FILE_LOCK_CONFLICT; + return NT_STATUS_LOCK_NOT_GRANTED; } /* Work out overlaps. */ @@ -912,7 +912,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, if (errno_ret == EACCES || errno_ret == EAGAIN) { TALLOC_FREE(tp); - status = NT_STATUS_FILE_LOCK_CONFLICT; + status = NT_STATUS_LOCK_NOT_GRANTED; goto fail; } else { TALLOC_FREE(tp); -- 2.17.1 From e5385142987202a67fc3667506ee233f2c726107 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 16:14:23 +0200 Subject: [PATCH 155/376] s3:smb2_lock: move from 'blocking' to 'state->blocking' This will simplify the next commits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit f13d13ae9da3072862a781bc926e7a06e8384337) --- source3/smbd/smb2_lock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index e9c8d7f890e..4cf735ff48d 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -42,6 +42,7 @@ struct smbd_smb2_lock_state { struct smbd_smb2_request *smb2req; struct smb_request *smb1req; struct files_struct *fsp; + bool blocking; uint16_t lock_count; struct smbd_lock_element *locks; }; @@ -200,7 +201,6 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req; struct smbd_smb2_lock_state *state; - bool blocking = false; bool isunlock = false; uint16_t i; struct smbd_lock_element *locks; @@ -241,7 +241,7 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } - blocking = true; + state->blocking = true; break; case SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY: @@ -383,7 +383,7 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - if (blocking && + if (state->blocking && (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) || NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT))) { struct tevent_req *subreq; -- 2.17.1 From 5e156be97a37b9bd42b18a78cf6ab541271971e7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 16:39:41 +0200 Subject: [PATCH 156/376] s3:smb2_lock: split smbd_smb2_lock_retry() into _try() and _retry() This makes it possible to reuse _try() in the _send() function in the next commits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit d096742da1a045357f52ccd5b28d499c30e96152) --- source3/smbd/smb2_lock.c | 49 ++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 4cf735ff48d..c2b4603f3e1 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -189,6 +189,7 @@ static void smbd_smb2_request_lock_done(struct tevent_req *subreq) } } +static void smbd_smb2_lock_try(struct tevent_req *req); static void smbd_smb2_lock_retry(struct tevent_req *subreq); static bool smbd_smb2_lock_cancel(struct tevent_req *req); @@ -410,10 +411,8 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } -static void smbd_smb2_lock_retry(struct tevent_req *subreq) +static void smbd_smb2_lock_try(struct tevent_req *req) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); struct smbd_smb2_lock_state *state = tevent_req_data( req, struct smbd_smb2_lock_state); struct share_mode_lock *lck = NULL; @@ -421,22 +420,7 @@ static void smbd_smb2_lock_retry(struct tevent_req *subreq) struct server_id blocking_pid = { 0 }; uint64_t blocking_smblctx; NTSTATUS status; - bool ok; - - /* - * Make sure we run as the user again - */ - ok = change_to_user_by_fsp(state->fsp); - if (!ok) { - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - - status = dbwrap_watched_watch_recv(subreq, NULL, NULL); - TALLOC_FREE(subreq); - if (tevent_req_nterror(req, status)) { - return; - } + struct tevent_req *subreq = NULL; lck = get_existing_share_mode_lock( talloc_tos(), state->fsp->file_id); @@ -467,6 +451,33 @@ static void smbd_smb2_lock_retry(struct tevent_req *subreq) tevent_req_set_callback(subreq, smbd_smb2_lock_retry, req); } +static void smbd_smb2_lock_retry(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smbd_smb2_lock_state *state = tevent_req_data( + req, struct smbd_smb2_lock_state); + NTSTATUS status; + bool ok; + + /* + * Make sure we run as the user again + */ + ok = change_to_user_by_fsp(state->fsp); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + + status = dbwrap_watched_watch_recv(subreq, NULL, NULL); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + smbd_smb2_lock_try(req); +} + static NTSTATUS smbd_smb2_lock_recv(struct tevent_req *req) { return tevent_req_simple_recv_ntstatus(req); -- 2.17.1 From c4ab0c8502284ee0a4e4336f42c352b5a19dda43 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 16:39:41 +0200 Subject: [PATCH 157/376] s3:smb2_lock: error out early in smbd_smb2_lock_send() We no longer expect NT_STATUS_FILE_LOCK_CONFLICT from the VFS layer and assert that in a future version. This makes it easier to port the same logic to smbd_smb2_lock_try(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 39d514cdc358f175d0968f4a78f8f2f05a6c1707) --- source3/smbd/smb2_lock.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index c2b4603f3e1..c049c33ebbc 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -383,10 +383,26 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, tevent_req_done(req); return tevent_req_post(req, ev); } + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { + /* + * This is a bug and will be changed into an assert + * in a future version. We should only + * ever get NT_STATUS_LOCK_NOT_GRANTED here! + */ + static uint64_t _bug_count; + int _level = (_bug_count++ == 0) ? DBGLVL_ERR: DBGLVL_DEBUG; + DBG_PREFIX(_level, ("BUG: Got %s mapping to " + "NT_STATUS_LOCK_NOT_GRANTED\n", + nt_errstr(status))); + status = NT_STATUS_LOCK_NOT_GRANTED; + } + if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { + TALLOC_FREE(lck); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } - if (state->blocking && - (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) || - NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT))) { + if (state->blocking) { struct tevent_req *subreq; DBG_DEBUG("Watching share mode lock\n"); -- 2.17.1 From 1fb82e04d0231392a9243b6b924e6c1765110a8d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 16:39:41 +0200 Subject: [PATCH 158/376] s3:smb2_lock: let smbd_smb2_lock_try() explicitly check for the retry condition This makes it possible to reuse _try() in the _send() function in the next commit. We should not retry forever on a hard error. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7f77e0b4e9878f1f3515206d052adc012e26aafb) --- source3/smbd/smb2_lock.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index c049c33ebbc..153705b26a1 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -457,6 +457,32 @@ static void smbd_smb2_lock_try(struct tevent_req *req) tevent_req_done(req); return; } + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { + /* + * This is a bug and will be changed into an assert + * in future version. We should only + * ever get NT_STATUS_LOCK_NOT_GRANTED here! + */ + static uint64_t _bug_count; + int _level = (_bug_count++ == 0) ? DBGLVL_ERR: DBGLVL_DEBUG; + DBG_PREFIX(_level, ("BUG: Got %s mapping to " + "NT_STATUS_LOCK_NOT_GRANTED\n", + nt_errstr(status))); + status = NT_STATUS_LOCK_NOT_GRANTED; + } + if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { + TALLOC_FREE(lck); + tevent_req_nterror(req, status); + return; + } + + if (!state->blocking) { + TALLOC_FREE(lck); + tevent_req_nterror(req, status); + return; + } + + DBG_DEBUG("Watching share mode lock\n"); subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); -- 2.17.1 From 00fc583960f0983c84f960408c8cc92c25c0a928 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Aug 2019 16:39:41 +0200 Subject: [PATCH 159/376] s3:smb2_lock: make use of smbd_smb2_lock_try() in smbd_smb2_lock_send() We only need the logic to call smbd_do_locks_try() and a possible retry once in smbd_smb2_lock_try(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher (cherry picked from commit 359e9992be713bbecfdb19998d69e1d3f020c5e9) --- source3/smbd/smb2_lock.c | 68 ++++------------------------------------ 1 file changed, 6 insertions(+), 62 deletions(-) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 153705b26a1..a8ccf21cc20 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -205,10 +205,6 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, bool isunlock = false; uint16_t i; struct smbd_lock_element *locks; - struct share_mode_lock *lck = NULL; - uint16_t blocker_idx; - struct server_id blocking_pid = { 0 }; - uint64_t blocking_smblctx; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, @@ -363,68 +359,16 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - lck = get_existing_share_mode_lock( - talloc_tos(), state->fsp->file_id); - if (tevent_req_nomem(lck, req)) { - return tevent_req_post(req, ev); - } - - status = smbd_do_locks_try( - state->fsp, - WINDOWS_LOCK, - state->lock_count, - state->locks, - &blocker_idx, - &blocking_pid, - &blocking_smblctx); - - if (NT_STATUS_IS_OK(status)) { - TALLOC_FREE(lck); - tevent_req_done(req); - return tevent_req_post(req, ev); - } - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { - /* - * This is a bug and will be changed into an assert - * in a future version. We should only - * ever get NT_STATUS_LOCK_NOT_GRANTED here! - */ - static uint64_t _bug_count; - int _level = (_bug_count++ == 0) ? DBGLVL_ERR: DBGLVL_DEBUG; - DBG_PREFIX(_level, ("BUG: Got %s mapping to " - "NT_STATUS_LOCK_NOT_GRANTED\n", - nt_errstr(status))); - status = NT_STATUS_LOCK_NOT_GRANTED; - } - if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { - TALLOC_FREE(lck); - tevent_req_nterror(req, status); + smbd_smb2_lock_try(req); + if (!tevent_req_is_in_progress(req)) { return tevent_req_post(req, ev); } - if (state->blocking) { - struct tevent_req *subreq; - - DBG_DEBUG("Watching share mode lock\n"); - - subreq = dbwrap_watched_watch_send( - state, state->ev, lck->data->record, blocking_pid); - TALLOC_FREE(lck); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, smbd_smb2_lock_retry, req); - - tevent_req_defer_callback(req, smb2req->sconn->ev_ctx); - aio_add_req_to_fsp(state->fsp, req); - tevent_req_set_cancel_fn(req, smbd_smb2_lock_cancel); + tevent_req_defer_callback(req, smb2req->sconn->ev_ctx); + aio_add_req_to_fsp(state->fsp, req); + tevent_req_set_cancel_fn(req, smbd_smb2_lock_cancel); - return req; - } - - TALLOC_FREE(lck); - tevent_req_nterror(req, status); - return tevent_req_post(req, ev); + return req; } static void smbd_smb2_lock_try(struct tevent_req *req) -- 2.17.1 From 061b60353d76ac368f7e48df9fe7fb899f7a2642 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 17:38:30 +0200 Subject: [PATCH 160/376] s4:torture/smb2: add smb2.samba3misc.localposixlock1 This demonstrates that the SMB2 code path doesn't do any retry for local posix locks. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7155d3a2c5d7237f00cccb1802c1341cf295864e) --- selftest/knownfail.d/smb2.localposixlock | 1 + selftest/skip | 1 + source3/selftest/tests.py | 2 +- source4/torture/smb2/samba3misc.c | 188 +++++++++++++++++++++++ source4/torture/smb2/smb2.c | 1 + source4/torture/smb2/wscript_build | 1 + 6 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 selftest/knownfail.d/smb2.localposixlock create mode 100644 source4/torture/smb2/samba3misc.c diff --git a/selftest/knownfail.d/smb2.localposixlock b/selftest/knownfail.d/smb2.localposixlock new file mode 100644 index 00000000000..1b84f074e0b --- /dev/null +++ b/selftest/knownfail.d/smb2.localposixlock @@ -0,0 +1 @@ +^samba3.smb2.samba3misc.localposixlock1 diff --git a/selftest/skip b/selftest/skip index c471072e88f..11bf29599fa 100644 --- a/selftest/skip +++ b/selftest/skip @@ -93,6 +93,7 @@ ^samba4.rpc.samr.passwords.*ncacn_np\(ad_dc_slowtests\) # currently fails, possibly config issue ^samba4.rpc.samr.passwords.*s4member # currently fails, possibly config issue ^samba4.raw.scan.eamax +^samba4.smb2.samba3misc ^samba4.smb2.notify ^samba4.smb2.scan ^samba4.smb2.lease diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index a3daeacae6b..ebc366de3ea 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -529,7 +529,7 @@ for t in tests: plansmbtorture4testsuite(t, env, '//$SERVER/tmp -k yes -U$DC_USERNAME@$REALM%$DC_PASSWORD --option=torture:addc=$DC_SERVER', description='kerberos connection') plansmbtorture4testsuite(t, env, '//$SERVER/tmpguest -U% --option=torture:addc=$DC_SERVER', description='anonymous connection') plansmbtorture4testsuite(t, env, '//$SERVER/tmp -k no -U$DC_USERNAME@$REALM%$DC_PASSWORD', description='ntlm user@realm') - elif t == "raw.samba3posixtimedlock": + elif t == "raw.samba3posixtimedlock" or t == "smb2.samba3misc": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmpguest -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpguest -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/ad_dc/share') elif t == "raw.chkpath": diff --git a/source4/torture/smb2/samba3misc.c b/source4/torture/smb2/samba3misc.c new file mode 100644 index 00000000000..a5fe6c1bbea --- /dev/null +++ b/source4/torture/smb2/samba3misc.c @@ -0,0 +1,188 @@ +/* + Unix SMB/CIFS implementation. + + Test some misc Samba3 code paths + + Copyright (C) Volker Lendecke 2006 + Copyright (C) Stefan Metzmacher 2019 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/time.h" +#include "system/filesys.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" +#include "../libcli/smb/smbXcli_base.h" +#include "torture/torture.h" +#include "torture/smb2/proto.h" +#include "torture/util.h" +#include "lib/events/events.h" +#include "param/param.h" + +#define CHECK_STATUS(status, correct) do { \ + const char *_cmt = "(" __location__ ")"; \ + torture_assert_ntstatus_equal_goto(tctx,status,correct, \ + ret,done,_cmt); \ + } while (0) + +#define BASEDIR "samba3misc.smb2" + +#define WAIT_FOR_ASYNC_RESPONSE(req) \ + while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \ + if (tevent_loop_once(tctx->ev) != 0) { \ + break; \ + } \ + } + +static void torture_smb2_tree_disconnect_timer(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct smb2_tree *tree = + talloc_get_type_abort(private_data, + struct smb2_tree); + + smbXcli_conn_disconnect(tree->session->transport->conn, + NT_STATUS_CTX_CLIENT_QUERY_TIMEOUT); +} + +/* + * Check that Samba3 correctly deals with conflicting local posix byte range + * locks on an underlying file via "normal" SMB2 (without posix extentions). + * + * Note: This test depends on "posix locking = yes". + * Note: To run this test, use "--option=torture:localdir=" + */ +static bool torture_samba3_localposixlock1(struct torture_context *tctx, + struct smb2_tree *tree) +{ + NTSTATUS status; + bool ret = true; + int rc; + const char *fname = "posixtimedlock.dat"; + const char *fpath; + const char *localdir; + const char *localname; + struct smb2_handle h = {{0}}; + struct smb2_lock lck = {0}; + struct smb2_lock_element el[1] = {{0}}; + struct smb2_request *req = NULL; + int fd = -1; + struct flock posix_lock; + struct tevent_timer *te; + + status = torture_smb2_testdir(tree, BASEDIR, &h); + CHECK_STATUS(status, NT_STATUS_OK); + smb2_util_close(tree, h); + + status = torture_smb2_testfile(tree, fname, &h); + CHECK_STATUS(status, NT_STATUS_OK); + + fpath = talloc_asprintf(tctx, "%s\\%s", BASEDIR, fname); + torture_assert(tctx, fpath != NULL, "fpath\n"); + + status = torture_smb2_testfile(tree, fpath, &h); + CHECK_STATUS(status, NT_STATUS_OK); + + localdir = torture_setting_string(tctx, "localdir", NULL); + torture_assert(tctx, localdir != NULL, + "--option=torture:localdir= required\n"); + + localname = talloc_asprintf(tctx, "%s/%s/%s", + localdir, BASEDIR, fname); + torture_assert(tctx, localname != NULL, "localname\n"); + + /* + * Lock a byte range from posix + */ + + torture_comment(tctx, " local open(%s)\n", localname); + fd = open(localname, O_RDWR); + if (fd == -1) { + torture_warning(tctx, "open(%s) failed: %s\n", + localname, strerror(errno)); + torture_assert(tctx, fd != -1, "open localname\n"); + } + + posix_lock.l_type = F_WRLCK; + posix_lock.l_whence = SEEK_SET; + posix_lock.l_start = 0; + posix_lock.l_len = 1; + + torture_comment(tctx, " local fcntl\n"); + rc = fcntl(fd, F_SETLK, &posix_lock); + if (rc == -1) { + torture_warning(tctx, "fcntl failed: %s\n", strerror(errno)); + torture_assert(tctx, rc != -1, "fcntl lock\n"); + } + + el[0].offset = 0; + el[0].length = 1; + el[0].reserved = 0x00000000; + el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | + SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; + lck.in.locks = el; + lck.in.lock_count = 0x0001; + lck.in.lock_sequence = 0x00000000; + lck.in.file.handle = h; + + torture_comment(tctx, " remote non-blocking lock\n"); + status = smb2_lock(tree, &lck); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + torture_comment(tctx, " remote async blocking lock\n"); + el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; + req = smb2_lock_send(tree, &lck); + torture_assert(tctx, req != NULL, "smb2_lock_send()\n"); + + te = tevent_add_timer(tctx->ev, + tctx, timeval_current_ofs(5, 0), + torture_smb2_tree_disconnect_timer, + tree); + torture_assert(tctx, te != NULL, "tevent_add_timer\n"); + + torture_comment(tctx, " remote wait for STATUS_PENDING\n"); + WAIT_FOR_ASYNC_RESPONSE(req); + + torture_comment(tctx, " local close file\n"); + close(fd); + fd = -1; + + torture_comment(tctx, " remote lock should now succeed\n"); + status = smb2_lock_recv(req, &lck); + CHECK_STATUS(status, NT_STATUS_OK); + +done: + if (fd != -1) { + close(fd); + } + smb2_util_close(tree, h); + smb2_deltree(tree, BASEDIR); + return ret; +} + +struct torture_suite *torture_smb2_samba3misc_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = torture_suite_create(ctx, "samba3misc"); + + torture_suite_add_1smb2_test(suite, "localposixlock1", + torture_samba3_localposixlock1); + + suite->description = talloc_strdup(suite, "SMB2 Samba3 MISC"); + + return suite; +} diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c index f495c19d251..e57dba3c1d9 100644 --- a/source4/torture/smb2/smb2.c +++ b/source4/torture/smb2/smb2.c @@ -195,6 +195,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx) torture_suite_add_suite(suite, torture_smb2_doc_init(suite)); torture_suite_add_suite(suite, torture_smb2_multichannel_init(suite)); + torture_suite_add_suite(suite, torture_smb2_samba3misc_init(suite)); suite->description = talloc_strdup(suite, "SMB2-specific tests"); diff --git a/source4/torture/smb2/wscript_build b/source4/torture/smb2/wscript_build index e605a4589ac..8b17cfb36d4 100644 --- a/source4/torture/smb2/wscript_build +++ b/source4/torture/smb2/wscript_build @@ -34,6 +34,7 @@ bld.SAMBA_MODULE('TORTURE_SMB2', sharemode.c smb2.c streams.c + samba3misc.c util.c ''', subsystem='smbtorture', -- 2.17.1 From c4d7c186aca3b9fb42354ac47f10514468b4c8b7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2019 14:50:27 +0200 Subject: [PATCH 161/376] s3:smb2_lock: add retry for POSIX locks BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8decf41bbb8be2b4ac463eb6ace16a8628276ab5) --- selftest/knownfail.d/smb2.localposixlock | 1 - source3/smbd/smb2_lock.c | 55 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/smb2.localposixlock diff --git a/selftest/knownfail.d/smb2.localposixlock b/selftest/knownfail.d/smb2.localposixlock deleted file mode 100644 index 1b84f074e0b..00000000000 --- a/selftest/knownfail.d/smb2.localposixlock +++ /dev/null @@ -1 +0,0 @@ -^samba3.smb2.samba3misc.localposixlock1 diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index a8ccf21cc20..8ba54fe6995 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -43,6 +43,7 @@ struct smbd_smb2_lock_state { struct smb_request *smb1req; struct files_struct *fsp; bool blocking; + uint32_t polling_msecs; uint16_t lock_count; struct smbd_lock_element *locks; }; @@ -371,6 +372,32 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return req; } +static void smbd_smb2_lock_update_polling_msecs( + struct smbd_smb2_lock_state *state) +{ + /* + * The default lp_lock_spin_time() is 200ms. + * + * v_min is in the range of 0.002 to 20 secs + * (0.2 secs by default) + * + * v_max is in the range of 0.02 to 200 secs + * (2.0 secs by default) + * + * The typical steps are: + * 0.2, 0.4, 0.6, 0.8, ... 2.0 + */ + uint32_t v_min = MAX(2, MIN(20000, lp_lock_spin_time())); + uint32_t v_max = 10 * v_min; + + if (state->polling_msecs >= v_max) { + state->polling_msecs = v_max; + return; + } + + state->polling_msecs += v_min; +} + static void smbd_smb2_lock_try(struct tevent_req *req) { struct smbd_smb2_lock_state *state = tevent_req_data( @@ -381,6 +408,7 @@ static void smbd_smb2_lock_try(struct tevent_req *req) uint64_t blocking_smblctx; NTSTATUS status; struct tevent_req *subreq = NULL; + struct timeval endtime = { 0 }; lck = get_existing_share_mode_lock( talloc_tos(), state->fsp->file_id); @@ -426,6 +454,15 @@ static void smbd_smb2_lock_try(struct tevent_req *req) return; } + if (blocking_smblctx == UINT64_MAX) { + smbd_smb2_lock_update_polling_msecs(state); + + DBG_DEBUG("Blocked on a posix lock. Retry in %"PRIu32" msecs\n", + state->polling_msecs); + + endtime = timeval_current_ofs_msec(state->polling_msecs); + } + DBG_DEBUG("Watching share mode lock\n"); subreq = dbwrap_watched_watch_send( @@ -435,6 +472,18 @@ static void smbd_smb2_lock_try(struct tevent_req *req) return; } tevent_req_set_callback(subreq, smbd_smb2_lock_retry, req); + + if (!timeval_is_zero(&endtime)) { + bool ok; + + ok = tevent_req_set_endtime(subreq, + state->ev, + endtime); + if (!ok) { + tevent_req_oom(req); + return; + } + } } static void smbd_smb2_lock_retry(struct tevent_req *subreq) @@ -457,6 +506,12 @@ static void smbd_smb2_lock_retry(struct tevent_req *subreq) status = dbwrap_watched_watch_recv(subreq, NULL, NULL); TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + /* + * This is just a trigger for a timed retry. + */ + status = NT_STATUS_OK; + } if (tevent_req_nterror(req, status)) { return; } -- 2.17.1 From da765a062aa4b57814ea426c94c6b3ba23dca47c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Aug 2019 12:28:39 +0200 Subject: [PATCH 162/376] s4:torture/raw: improvements for multilock2 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8a7039be530adcdda9e7e7621bdcf902f5ca1721) --- source4/torture/raw/lock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index f1fbdd6da71..f264d0aea11 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -2449,7 +2449,7 @@ static bool test_multilock2(struct torture_context *tctx, lock[0].pid = cli->session->pid+2; io.lockx.in.lock_cnt = 1; req2 = smb_raw_lock_send(cli->tree, &io); - torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, + torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx, "Failed to setup timed locks (%s)\n", __location__)); /* Unlock lock[0] */ @@ -2465,6 +2465,9 @@ static bool test_multilock2(struct torture_context *tctx, status = smbcli_request_simple_recv(req2); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + /* Start the clock. */ t = time_mono(NULL); -- 2.17.1 From 6bd411aad81477637255fcb5c826ddaf43f593b1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Aug 2019 12:13:15 +0200 Subject: [PATCH 163/376] s4:torture/raw: add multilock3 test This demonstrates that unrelated lock ranges are not blocked by other blocked requests on the same fsp. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 297763c6b618c07148d788b46218a0798225bf79) --- selftest/knownfail.d/multilock | 1 + source4/torture/raw/lock.c | 266 +++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 selftest/knownfail.d/multilock diff --git a/selftest/knownfail.d/multilock b/selftest/knownfail.d/multilock new file mode 100644 index 00000000000..e0e6e81c453 --- /dev/null +++ b/selftest/knownfail.d/multilock @@ -0,0 +1 @@ +^samba3.raw.lock.multilock3.*nt4_dc diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index f264d0aea11..bea55f6a605 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -2494,6 +2494,271 @@ done: return ret; } +/* + test multi3 Locking&X operation + This test is designed to show that + lock precedence on the server is based + on the order received, not on the ability + to grant. + + Compared to test_multilock2() (above) + this test demonstrates that completely + unrelated ranges work independently. + + For example: + + A blocked lock request containing 2 locks + will be satified before a subsequent blocked + lock request over one of the same regions, + even if that region is then unlocked. But + a lock of a different region goes through. E.g. + + All locks are LOCKING_ANDX_EXCLUSIVE_LOCK (rw). + + (a) lock 100->109, 120->129 (granted) + (b) lock 100->109, 120->129 (blocks, timeout=20s) + (c) lock 100->109 (blocks, timeout=2s) + (d) lock 110->119 (granted) + (e) lock 110->119 (blocks, timeout=20s) + (f) unlock 100->109 (a) + (g) lock 100->109 (not granted, blocked by (b)) + (h) lock 100->109 (not granted, blocked by itself (b)) + (i) lock (c) will not be granted(conflict, times out) + as lock (b) will take precedence. + (j) unlock 110-119 (d) + (k) lock (e) completes and is not blocked by (a) nor (b) + (l) lock 100->109 (not granted(conflict), blocked by (b)) + (m) lock 100->109 (not granted(conflict), blocked by itself (b)) + (n) unlock 120-129 (a) + (o) lock (b) completes +*/ +static bool test_multilock3(struct torture_context *tctx, + struct smbcli_state *cli) +{ + union smb_lock io; + struct smb_lock_entry lock[2]; + union smb_lock io3; + struct smb_lock_entry lock3[1]; + NTSTATUS status; + bool ret = true; + int fnum; + const char *fname = BASEDIR "\\multilock3_test.txt"; + time_t t; + struct smbcli_request *req = NULL; + struct smbcli_request *req2 = NULL; + struct smbcli_request *req4 = NULL; + + torture_assert(tctx, torture_setup_dir(cli, BASEDIR), + "Failed to setup up test directory: " BASEDIR); + + torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 3\n"); + io.generic.level = RAW_LOCK_LOCKX; + + /* Create the test file. */ + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx, + "Failed to create %s - %s\n", + fname, smbcli_errstr(cli->tree))); + + /* + * a) + * Lock regions 100->109, 120->129 as + * two separate write locks in one request. + */ + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 2; + io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + lock[1].pid = cli->session->pid; + lock[1].offset = 120; + lock[1].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * b) + * Now request the same locks on a different + * context as blocking locks. + */ + io.lockx.in.timeout = 20000; + lock[0].pid = cli->session->pid+1; + lock[1].pid = cli->session->pid+1; + req = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * c) + * Request the first lock again on a separate context. + * Wait 2 seconds. This should time out (the previous + * multi-lock request should take precedence). + */ + io.lockx.in.timeout = 2000; + lock[0].pid = cli->session->pid+2; + io.lockx.in.lock_cnt = 1; + req2 = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * d) + * Lock regions 110->119 + */ + io3.lockx.level = RAW_LOCK_LOCKX; + io3.lockx.in.file.fnum = fnum; + io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 0; + io3.lockx.in.lock_cnt = 1; + io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock3[0].pid = cli->session->pid+3; + lock3[0].offset = 110; + lock3[0].count = 10; + io3.lockx.in.locks = &lock3[0]; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * e) + * try 110-119 again + */ + io3.lockx.in.timeout = 20000; + lock3[0].pid = cli->session->pid+4; + req4 = smb_raw_lock_send(cli->tree, &io3); + torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * f) + * Unlock (a) lock[0] 100-109 + */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[0]; + lock[0].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * g) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+5; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + /* + * h) + * try to lock lock[0] 100-109 again with + * the pid that's still waiting + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req2->state <= SMBCLI_REQUEST_RECV, + "req2 should still wait"); + + /* + * i) + * Did the second lock complete (should time out) ? + */ + status = smbcli_request_simple_recv(req2); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV, + "req4 should still wait"); + + /* + * j) + * Unlock (d) lock[0] 110-119 + */ + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 1; + io3.lockx.in.lock_cnt = 0; + lock3[0].pid = cli->session->pid+3; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * k) + * receive the successful blocked lock request (e) + * on 110-119 while the 100-109/120-129 is still waiting. + */ + status = smbcli_request_simple_recv(req4); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * l) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+6; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + + /* + * m) + * try to lock lock[0] 100-109 again with + * the pid that's still waiting + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + + /* Start the clock. */ + t = time_mono(NULL); + + /* + * n) + * Unlock lock[1] 120-129 */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[1]; + lock[1].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * o) + * receive the successful blocked lock request (b) + */ + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Fail if this took more than 2 seconds. */ + torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx, + "Blocking locks were not granted immediately (%s)\n", + __location__)); +done: + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + return ret; +} /* basic testing of lock calls @@ -2517,6 +2782,7 @@ struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx) torture_suite_add_1smb_test(suite, "zerobyteread", test_zerobyteread); torture_suite_add_1smb_test(suite, "multilock", test_multilock); torture_suite_add_1smb_test(suite, "multilock2", test_multilock2); + torture_suite_add_1smb_test(suite, "multilock3", test_multilock3); return suite; } -- 2.17.1 From cc9afc3dac2fd680fd5731160889fc39eb0e360c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Aug 2019 14:49:29 +0200 Subject: [PATCH 164/376] s4:torture/raw: add multilock4 test This is similar to multilock3, but uses read-only (LOCKING_ANDX_SHARED_LOCK) locks for the blocked requests. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit d3e65ceb1ec25c7b62a7e908506126269011f30d) --- selftest/knownfail.d/multilock | 1 + source4/torture/raw/lock.c | 266 +++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) diff --git a/selftest/knownfail.d/multilock b/selftest/knownfail.d/multilock index e0e6e81c453..01538acc5a8 100644 --- a/selftest/knownfail.d/multilock +++ b/selftest/knownfail.d/multilock @@ -1 +1,2 @@ ^samba3.raw.lock.multilock3.*nt4_dc +^samba3.raw.lock.multilock4.*nt4_dc diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index bea55f6a605..26339f9b28b 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -2760,6 +2760,271 @@ done: return ret; } +/* + test multi4 Locking&X operation + This test is designed to show that + lock precedence on the server is based + on the order received, not on the ability + to grant. + + Compared to test_multilock3() (above) + this test demonstrates that pending read-only/shared + locks doesn't block shared locks others. + + The outstanding requests build an implicit + database that's checked before checking + the already granted locks in the real database. + + For example: + + A blocked read-lock request containing 2 locks + will be still be blocked, while one region + is still write-locked. While it doesn't block + other read-lock requests for the other region. E.g. + + (a) lock(rw) 100->109, 120->129 (granted) + (b) lock(ro) 100->109, 120->129 (blocks, timeout=20s) + (c) lock(ro) 100->109 (blocks, timeout=MAX) + (d) lock(rw) 110->119 (granted) + (e) lock(rw) 110->119 (blocks, timeout=20s) + (f) unlock 100->109 (a) + (g) lock(ro) (c) completes and is not blocked by (a) nor (b) + (h) lock(rw) 100->109 (not granted, blocked by (c)) + (i) lock(rw) 100->109 (pid (b)) (not granted(conflict), blocked by (c)) + (j) unlock 110-119 + (k) lock (e) completes and is not blocked by (a) nor (b) + (l) lock 100->109 (not granted(conflict), blocked by (b)) + (m) lock 100->109 (pid (b)) (not granted(conflict), blocked by itself (b)) + (n) unlock 120-129 (a) + (o) lock (b) completes +*/ +static bool test_multilock4(struct torture_context *tctx, + struct smbcli_state *cli) +{ + union smb_lock io; + struct smb_lock_entry lock[2]; + union smb_lock io3; + struct smb_lock_entry lock3[1]; + NTSTATUS status; + bool ret = true; + int fnum; + const char *fname = BASEDIR "\\multilock4_test.txt"; + time_t t; + struct smbcli_request *req = NULL; + struct smbcli_request *req2 = NULL; + struct smbcli_request *req4 = NULL; + + torture_assert(tctx, torture_setup_dir(cli, BASEDIR), + "Failed to setup up test directory: " BASEDIR); + + torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 4\n"); + io.generic.level = RAW_LOCK_LOCKX; + + /* Create the test file. */ + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx, + "Failed to create %s - %s\n", + fname, smbcli_errstr(cli->tree))); + + /* + * a) + * Lock regions 100->109, 120->129 as + * two separate write locks in one request. + */ + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 2; + io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + lock[1].pid = cli->session->pid; + lock[1].offset = 120; + lock[1].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * b) + * Now request the same locks on a different + * context as blocking locks. But readonly. + */ + io.lockx.in.timeout = 20000; + io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK; + lock[0].pid = cli->session->pid+1; + lock[1].pid = cli->session->pid+1; + req = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * c) + * Request the first lock again on a separate context. + * Wait forever. The previous multi-lock request (b) + * should take precedence. Also readonly. + */ + io.lockx.in.timeout = UINT32_MAX; + lock[0].pid = cli->session->pid+2; + io.lockx.in.lock_cnt = 1; + req2 = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * d) + * Lock regions 110->119 + */ + io3.lockx.level = RAW_LOCK_LOCKX; + io3.lockx.in.file.fnum = fnum; + io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 0; + io3.lockx.in.lock_cnt = 1; + io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock3[0].pid = cli->session->pid+3; + lock3[0].offset = 110; + lock3[0].count = 10; + io3.lockx.in.locks = &lock3[0]; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * e) + * try 110-119 again + */ + io3.lockx.in.timeout = 20000; + lock3[0].pid = cli->session->pid+4; + req4 = smb_raw_lock_send(cli->tree, &io3); + torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * f) + * Unlock (a) lock[0] 100-109 + */ + io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[0]; + lock[0].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * g) + * receive the successful blocked lock request (c) + * on 110-119 while (b) 100-109/120-129 is still waiting. + */ + status = smbcli_request_simple_recv(req2); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * h) + * try to lock lock[0] 100-109 again + * (read/write) + */ + lock[0].pid = cli->session->pid+5; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + /* + * i) + * try to lock lock[0] 100-109 again with the pid (b) + * that's still waiting. + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV, + "req4 should still wait"); + + /* + * j) + * Unlock (d) lock[0] 110-119 + */ + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 1; + io3.lockx.in.lock_cnt = 0; + lock3[0].pid = cli->session->pid+3; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * k) + * receive the successful blocked + * lock request (e) on 110-119. + */ + status = smbcli_request_simple_recv(req4); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * l) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+6; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* + * m) + * try to lock lock[0] 100-109 again with the pid (b) + * that's still waiting + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + + /* Start the clock. */ + t = time_mono(NULL); + + /* + * n) + * Unlock (a) lock[1] 120-129 + */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[1]; + lock[1].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * o) + * receive the successful blocked lock request (b) + */ + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Fail if this took more than 2 seconds. */ + torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx, + "Blocking locks were not granted immediately (%s)\n", + __location__)); +done: + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + return ret; +} + /* basic testing of lock calls */ @@ -2783,6 +3048,7 @@ struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx) torture_suite_add_1smb_test(suite, "multilock", test_multilock); torture_suite_add_1smb_test(suite, "multilock2", test_multilock2); torture_suite_add_1smb_test(suite, "multilock3", test_multilock3); + torture_suite_add_1smb_test(suite, "multilock4", test_multilock4); return suite; } -- 2.17.1 From a037ebbc34795de46196ff50ad439356056fe082 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Aug 2019 15:12:01 +0200 Subject: [PATCH 165/376] s4:torture/raw: add multilock5 test This is similar to multilock3, but uses a read-only (LOCKING_ANDX_SHARED_LOCK) locks for the first lock request. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 6d4296aca0c9a9287c0c78c8f8847a560bd2ea24) --- selftest/knownfail.d/multilock | 1 + source4/torture/raw/lock.c | 269 +++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) diff --git a/selftest/knownfail.d/multilock b/selftest/knownfail.d/multilock index 01538acc5a8..b3fe93fd34e 100644 --- a/selftest/knownfail.d/multilock +++ b/selftest/knownfail.d/multilock @@ -1,2 +1,3 @@ ^samba3.raw.lock.multilock3.*nt4_dc ^samba3.raw.lock.multilock4.*nt4_dc +^samba3.raw.lock.multilock5.*nt4_dc diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index 26339f9b28b..c29a577b34a 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -3025,6 +3025,274 @@ done: return ret; } +/* + test multi5 Locking&X operation + This test is designed to show that + lock precedence on the server is based + on the order received, not on the ability + to grant. + + Compared to test_multilock3() (above) + this test demonstrates that the initial + lock request that block the following + exclusive locks can be a shared lock. + + For example: + + All locks except (a) are LOCKING_ANDX_EXCLUSIVE_LOCK (rw). + + (a) lock(ro) 100->109, 120->129 (granted) + (b) lock 100->109, 120->129 (blocks, timeout=20s) + (c) lock 100->109 (blocks, timeout=2s) + (d) lock 110->119 (granted) + (e) lock 110->119 (blocks, timeout=20s) + (f) unlock 100->109 (a) + (g) lock 100->109 (not granted, blocked by (b)) + (h) lock 100->109 (not granted, blocked by itself (b)) + (i) lock (c) will not be granted(conflict, times out) + as lock (b) will take precedence. + (j) unlock 110-119 (d) + (k) lock (e) completes and is not blocked by (a) nor (b) + (l) lock 100->109 (not granted(conflict), blocked by (b)) + (m) lock 100->109 (not granted(conflict), blocked by itself (b)) + (n) unlock 120-129 (a) + (o) lock (b) completes +*/ +static bool test_multilock5(struct torture_context *tctx, + struct smbcli_state *cli) +{ + union smb_lock io; + struct smb_lock_entry lock[2]; + union smb_lock io3; + struct smb_lock_entry lock3[1]; + NTSTATUS status; + bool ret = true; + int fnum; + const char *fname = BASEDIR "\\multilock5_test.txt"; + time_t t; + struct smbcli_request *req = NULL; + struct smbcli_request *req2 = NULL; + struct smbcli_request *req4 = NULL; + + torture_assert(tctx, torture_setup_dir(cli, BASEDIR), + "Failed to setup up test directory: " BASEDIR); + + torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 5\n"); + io.generic.level = RAW_LOCK_LOCKX; + + /* Create the test file. */ + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx, + "Failed to create %s - %s\n", + fname, smbcli_errstr(cli->tree))); + + /* + * a) + * Lock regions 100->109, 120->129 as + * two separate write locks in one request. + * (read only) + */ + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 2; + io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + lock[1].pid = cli->session->pid; + lock[1].offset = 120; + lock[1].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * b) + * Now request the same locks on a different + * context as blocking locks. + * (read write) + */ + io.lockx.in.timeout = 20000; + io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock[0].pid = cli->session->pid+1; + lock[1].pid = cli->session->pid+1; + req = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * c) + * Request the first lock again on a separate context. + * Wait 2 seconds. This should time out (the previous + * multi-lock request should take precedence). + * (read write) + */ + io.lockx.in.timeout = 2000; + lock[0].pid = cli->session->pid+2; + io.lockx.in.lock_cnt = 1; + req2 = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * d) + * Lock regions 110->119 + */ + io3.lockx.level = RAW_LOCK_LOCKX; + io3.lockx.in.file.fnum = fnum; + io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 0; + io3.lockx.in.lock_cnt = 1; + io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock3[0].pid = cli->session->pid+3; + lock3[0].offset = 110; + lock3[0].count = 10; + io3.lockx.in.locks = &lock3[0]; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * e) + * try 110-119 again + */ + io3.lockx.in.timeout = 20000; + lock3[0].pid = cli->session->pid+4; + req4 = smb_raw_lock_send(cli->tree, &io3); + torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * f) + * Unlock (a) lock[0] 100-109 + * + * Note we send LOCKING_ANDX_EXCLUSIVE_LOCK + * while the lock used LOCKING_ANDX_SHARED_LOCK + * to check if that also works. + */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[0]; + lock[0].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * g) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+5; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + /* + * h) + * try to lock lock[0] 100-109 again with the pid (b) + * that's still waiting. + * (read write) + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req2->state <= SMBCLI_REQUEST_RECV, + "req2 should still wait"); + + /* + * i) + * Did the second lock complete (should time out) ? + */ + status = smbcli_request_simple_recv(req2); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV, + "req4 should still wait"); + + /* + * j) + * Unlock (d) lock[0] 110-119 + */ + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 1; + io3.lockx.in.lock_cnt = 0; + lock3[0].pid = cli->session->pid+3; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * k) + * receive the successful blocked lock requests + * on 110-119 while the 100-109/120-129 is still waiting. + */ + status = smbcli_request_simple_recv(req4); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * l) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+6; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* + * m) + * try to lock lock[0] 100-109 again with the pid (b) + * that's still waiting + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + + /* Start the clock. */ + t = time_mono(NULL); + + /* + * n) + * Unlock (a) lock[1] 120-129 + */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[1]; + lock[1].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * o) + * receive the successful blocked lock request (b) + */ + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Fail if this took more than 2 seconds. */ + torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx, + "Blocking locks were not granted immediately (%s)\n", + __location__)); +done: + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + return ret; +} + /* basic testing of lock calls */ @@ -3049,6 +3317,7 @@ struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx) torture_suite_add_1smb_test(suite, "multilock2", test_multilock2); torture_suite_add_1smb_test(suite, "multilock3", test_multilock3); torture_suite_add_1smb_test(suite, "multilock4", test_multilock4); + torture_suite_add_1smb_test(suite, "multilock5", test_multilock5); return suite; } -- 2.17.1 From d857b21d4fec18aa71f9bec4343924053dd9f083 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Aug 2019 16:24:34 +0200 Subject: [PATCH 166/376] s4:torture/raw: add multilock6 test This is similar to multilock3, but uses a read-only (LOCKING_ANDX_SHARED_LOCK) locks for the 2nd lock request. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit d3bc0199697fd7d6e04479321ca644a227bc4ede) --- selftest/knownfail | 1 + selftest/knownfail.d/multilock | 1 + source4/torture/raw/lock.c | 263 +++++++++++++++++++++++++++++++++ 3 files changed, 265 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index ded80b12259..7b54b77a708 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -109,6 +109,7 @@ .*net.api.delshare.* # DelShare isn't implemented yet ^samba4.smb2.oplock.doc ^samba4.smb2.lock.valid-request +^samba4.raw.lock.multilock6.ad_dc_ntvfs ^samba4.ldap.python \(ad_dc_default\).Test add_ldif\(\) with BASE64 security descriptor input using WRONG domain SID\(.*\)$ ^samba4.raw.lock.*.async # bug 6960 ^samba4.raw.open.ntcreatex_supersede diff --git a/selftest/knownfail.d/multilock b/selftest/knownfail.d/multilock index b3fe93fd34e..9fa497bd643 100644 --- a/selftest/knownfail.d/multilock +++ b/selftest/knownfail.d/multilock @@ -1,3 +1,4 @@ ^samba3.raw.lock.multilock3.*nt4_dc ^samba3.raw.lock.multilock4.*nt4_dc ^samba3.raw.lock.multilock5.*nt4_dc +^samba3.raw.lock.multilock6.*nt4_dc diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index c29a577b34a..f684e923a49 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -3293,6 +3293,268 @@ done: return ret; } +/* + test multi6 Locking&X operation + This test is designed to show that + lock precedence on the server is based + on the order received, not on the ability + to grant. + + Compared to test_multilock4() (above) + this test demonstrates the behavior if + only just the first blocking lock + being a shared lock. + + For example: + + All locks except (b) are LOCKING_ANDX_EXCLUSIVE_LOCK (rw). + + (a) lock 100->109, 120->129 (granted) + (b) lock(ro) 100->109, 120->129 (blocks, timeout=20s) + (c) lock 100->109 (blocks, timeout=2s) + (d) lock 110->119 (granted) + (e) lock 110->119 (blocks, timeout=20s) + (f) unlock 100->109 (a) + (g) lock 100->109 (not granted, blocked by (b)) + (h) lock 100->109 (not granted, blocked by itself (b)) + (i) lock (c) will not be granted(conflict, times out) + as lock (b) will take precedence. + (j) unlock 110-119 (d) + (k) lock (e) completes and is not blocked by (a) nor (b) + (l) lock 100->109 (not granted(conflict), blocked by (b)) + (m) lock 100->109 (not granted(conflict), blocked by itself (b)) + (n) unlock 120-129 (a) + (o) lock (b) completes +*/ +static bool test_multilock6(struct torture_context *tctx, + struct smbcli_state *cli) +{ + union smb_lock io; + struct smb_lock_entry lock[2]; + union smb_lock io3; + struct smb_lock_entry lock3[1]; + NTSTATUS status; + bool ret = true; + int fnum; + const char *fname = BASEDIR "\\multilock6_test.txt"; + time_t t; + struct smbcli_request *req = NULL; + struct smbcli_request *req2 = NULL; + struct smbcli_request *req4 = NULL; + + torture_assert(tctx, torture_setup_dir(cli, BASEDIR), + "Failed to setup up test directory: " BASEDIR); + + torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 6\n"); + io.generic.level = RAW_LOCK_LOCKX; + + /* Create the test file. */ + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx, + "Failed to create %s - %s\n", + fname, smbcli_errstr(cli->tree))); + + /* + * a) + * Lock regions 100->109, 120->129 as + * two separate write locks in one request. + */ + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 2; + io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + lock[1].pid = cli->session->pid; + lock[1].offset = 120; + lock[1].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * b) + * Now request the same locks on a different + * context as blocking locks. + * (read only) + */ + io.lockx.in.timeout = 20000; + io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK; + lock[0].pid = cli->session->pid+1; + lock[1].pid = cli->session->pid+1; + req = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * c) + * Request the first lock again on a separate context. + * Wait 2 seconds. This should time out (the previous + * multi-lock request should take precedence). + */ + io.lockx.in.timeout = 2000; + io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock[0].pid = cli->session->pid+2; + io.lockx.in.lock_cnt = 1; + req2 = smb_raw_lock_send(cli->tree, &io); + torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * d) + * Lock regions 110->119 + */ + io3.lockx.level = RAW_LOCK_LOCKX; + io3.lockx.in.file.fnum = fnum; + io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 0; + io3.lockx.in.lock_cnt = 1; + io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK; + lock3[0].pid = cli->session->pid+3; + lock3[0].offset = 110; + lock3[0].count = 10; + io3.lockx.in.locks = &lock3[0]; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * e) + * try 110-119 again + */ + io3.lockx.in.timeout = 20000; + lock3[0].pid = cli->session->pid+4; + req4 = smb_raw_lock_send(cli->tree, &io3); + torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx, + "Failed to setup timed locks (%s)\n", __location__)); + + /* + * f) + * Unlock (a) lock[0] 100-109 + */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[0]; + lock[0].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * g) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+5; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + /* + * h) + * try to lock lock[0] 100-109 again with the pid (b) + * that's still waiting + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req2->state <= SMBCLI_REQUEST_RECV, + "req2 should still wait"); + + /* + * i) + * Did the second lock (c) complete (should time out) ? + */ + status = smbcli_request_simple_recv(req2); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV, + "req4 should still wait"); + + /* + * j) + * Unlock (d) lock[0] 110-119 + */ + io3.lockx.in.timeout = 0; + io3.lockx.in.ulock_cnt = 1; + io3.lockx.in.lock_cnt = 0; + lock3[0].pid = cli->session->pid+3; + status = smb_raw_lock(cli->tree, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * k) + * receive the successful blocked lock request (e) + * on 110-119 while (b) 100-109/120-129 is still waiting. + */ + status = smbcli_request_simple_recv(req4); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * l) + * try to lock lock[0] 100-109 again + */ + lock[0].pid = cli->session->pid+6; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* + * m) + * try to lock lock[0] 100-109 again with the pid (b) + * that's still waiting + */ + lock[0].pid = cli->session->pid+1; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV, + "req should still wait"); + + /* Start the clock. */ + t = time_mono(NULL); + + /* + * n) + * Unlock (a) lock[1] 120-129 + */ + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 1; + io.lockx.in.lock_cnt = 0; + io.lockx.in.locks = &lock[1]; + lock[1].pid = cli->session->pid; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * o) + * receive the successful blocked lock request (b) + */ + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Fail if this took more than 2 seconds. */ + torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx, + "Blocking locks were not granted immediately (%s)\n", + __location__)); +done: + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + return ret; +} + /* basic testing of lock calls */ @@ -3318,6 +3580,7 @@ struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx) torture_suite_add_1smb_test(suite, "multilock3", test_multilock3); torture_suite_add_1smb_test(suite, "multilock4", test_multilock4); torture_suite_add_1smb_test(suite, "multilock5", test_multilock5); + torture_suite_add_1smb_test(suite, "multilock6", test_multilock6); return suite; } -- 2.17.1 From 9f46f3b0e722d993a650fc3659e842aad08837a6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 18:17:47 +0200 Subject: [PATCH 167/376] s3:blocking: use timeval_expired(&state->endtime) to stop processing This is less racy than timeval_elapsed() > 0 as the current time is already expired and timeout = 0 will always work correct. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 5a841a43f9c4f862e2d7235429363b3066cf5850) --- source3/smbd/blocking.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index a87d62d910a..9f64a86d3ee 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -159,9 +159,10 @@ struct tevent_req *smbd_smb1_do_locks_send( struct share_mode_lock *lck = NULL; struct server_id blocking_pid = { 0 }; uint64_t blocking_smblctx = 0; - struct timeval endtime; + struct timeval endtime = { 0 }; NTSTATUS status = NT_STATUS_OK; bool ok; + bool expired; req = tevent_req_create( mem_ctx, &state, struct smbd_smb1_do_locks_state); @@ -251,19 +252,28 @@ struct tevent_req *smbd_smb1_do_locks_send( state->timeout = lp_lock_spin_time(); } } + state->endtime = timeval_current_ofs_msec(state->timeout); DBG_DEBUG("timeout=%"PRIu32", blocking_smblctx=%"PRIu64"\n", state->timeout, blocking_smblctx); /* + * The client specified timeout expired + * avoid further retries. + * + * Otherwise keep waiting either waiting + * for changes in locking.tdb or the polling + * mode timers waiting for posix locks. + * * If the endtime is not elapsed yet, * it means we'll retry after a timeout. * In that case we'll have to return * NT_STATUS_FILE_LOCK_CONFLICT * instead of NT_STATUS_LOCK_NOT_GRANTED. */ - if (state->timeout == 0) { + expired = timeval_expired(&state->endtime); + if (expired) { status = state->deny_status; tevent_req_nterror(req, status); goto done; @@ -278,7 +288,6 @@ struct tevent_req *smbd_smb1_do_locks_send( TALLOC_FREE(lck); tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); - state->endtime = timeval_current_ofs_msec(state->timeout); endtime = state->endtime; if (blocking_smblctx == UINT64_MAX) { @@ -363,13 +372,13 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) struct smbd_smb1_do_locks_state *retry_state = tevent_req_data( retry_req, struct smbd_smb1_do_locks_state); struct share_mode_lock *lck; - struct timeval endtime; + struct timeval endtime = { 0 }; struct server_id blocking_pid = { 0 }; uint64_t blocking_smblctx = 0; struct tevent_req *subreq = NULL; NTSTATUS status; bool ok; - double elapsed; + bool expired; lck = get_existing_share_mode_lock(state, fsp->file_id); if (tevent_req_nomem(lck, req)) { @@ -393,7 +402,7 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) } /* - * The client specified timeout elapsed + * The client specified timeout expired * avoid further retries. * * Otherwise keep waiting either waiting @@ -406,8 +415,8 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) * NT_STATUS_FILE_LOCK_CONFLICT * instead of NT_STATUS_LOCK_NOT_GRANTED. */ - elapsed = timeval_elapsed(&state->endtime); - if (elapsed > 0) { + expired = timeval_expired(&state->endtime); + if (expired) { status = state->deny_status; goto done; } -- 2.17.1 From f479c7bc03a06a409b0037d7957806ba3208b55b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 18:02:57 +0200 Subject: [PATCH 168/376] s3:blocking: split out smbd_smb1_do_locks_setup_timeout() This function can be called multiple times, but only the first time will setup the endtime. And the endtime is relative to the request time and not the current time. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8da7c10a58292022ee57406db9a365de9ffaf5cf) --- source3/smbd/blocking.c | 98 ++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 9f64a86d3ee..98074c0c09a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -117,6 +117,68 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq); static void smbd_smb1_blocked_locks_cleanup( struct tevent_req *req, enum tevent_req_state req_state); +static void smbd_smb1_do_locks_setup_timeout( + struct smbd_smb1_do_locks_state *state, + const struct smbd_lock_element *blocker) +{ + struct files_struct *fsp = state->fsp; + + if (!timeval_is_zero(&state->endtime)) { + /* + * already done + */ + return; + } + + if ((state->timeout != 0) && (state->timeout != UINT32_MAX)) { + /* + * Windows internal resolution for blocking locks + * seems to be about 200ms... Don't wait for less than + * that. JRA. + */ + state->timeout = MAX(state->timeout, lp_lock_spin_time()); + } + + if (state->timeout != 0) { + goto set_endtime; + } + + if (blocker == NULL) { + goto set_endtime; + } + + if ((blocker->offset >= 0xEF000000) && + ((blocker->offset >> 63) == 0)) { + /* + * This must be an optimization of an ancient + * application bug... + */ + state->timeout = lp_lock_spin_time(); + } + + if ((fsp->lock_failure_seen) && + (blocker->offset == fsp->lock_failure_offset)) { + /* + * Delay repeated lock attempts on the same + * lock. Maybe a more advanced version of the + * above check? + */ + DBG_DEBUG("Delaying lock request due to previous " + "failure\n"); + state->timeout = lp_lock_spin_time(); + } + +set_endtime: + /* + * Note state->timeout might still 0, + * but that's ok, as we don't want to retry + * in that case. + */ + state->endtime = timeval_add(&state->smbreq->request_time, + state->timeout / 1000, + (state->timeout % 1000) * 1000); +} + static void smbd_smb1_do_locks_update_polling_msecs( struct smbd_smb1_do_locks_state *state) { @@ -196,15 +258,6 @@ struct tevent_req *smbd_smb1_do_locks_send( return tevent_req_post(req, ev); } - if ((state->timeout != 0) && (state->timeout != UINT32_MAX)) { - /* - * Windows internal resolution for blocking locks - * seems to be about 200ms... Don't wait for less than - * that. JRA. - */ - state->timeout = MAX(state->timeout, lp_lock_spin_time()); - } - lck = get_existing_share_mode_lock(state, state->fsp->file_id); if (tevent_req_nomem(lck, req)) { DBG_DEBUG("Could not get share mode lock\n"); @@ -228,32 +281,7 @@ struct tevent_req *smbd_smb1_do_locks_send( goto done; } - if (state->timeout == 0) { - struct smbd_lock_element *blocker = &locks[state->blocker]; - - if ((blocker->offset >= 0xEF000000) && - ((blocker->offset >> 63) == 0)) { - /* - * This must be an optimization of an ancient - * application bug... - */ - state->timeout = lp_lock_spin_time(); - } - - if ((fsp->lock_failure_seen) && - (blocker->offset == fsp->lock_failure_offset)) { - /* - * Delay repeated lock attempts on the same - * lock. Maybe a more advanced version of the - * above check? - */ - DBG_DEBUG("Delaying lock request due to previous " - "failure\n"); - state->timeout = lp_lock_spin_time(); - } - } - state->endtime = timeval_current_ofs_msec(state->timeout); - + smbd_smb1_do_locks_setup_timeout(state, &locks[state->blocker]); DBG_DEBUG("timeout=%"PRIu32", blocking_smblctx=%"PRIu64"\n", state->timeout, blocking_smblctx); -- 2.17.1 From 333026209a8abe5d9d00297ce7f0d6cdf66d6ce0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 15:21:50 +0200 Subject: [PATCH 169/376] s3:blocking: do the timeout calculation before calling dbwrap_watched_watch_send() This makes the next commits easier to understand. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 997548a5f1a14d82f1e80cce6d9ee55e85b5107c) --- source3/smbd/blocking.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 98074c0c09a..ac90f8c3ef1 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -308,14 +308,6 @@ struct tevent_req *smbd_smb1_do_locks_send( } state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; - subreq = dbwrap_watched_watch_send( - state, state->ev, lck->data->record, blocking_pid); - if (tevent_req_nomem(subreq, req)) { - goto done; - } - TALLOC_FREE(lck); - tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); - endtime = state->endtime; if (blocking_smblctx == UINT64_MAX) { @@ -330,6 +322,14 @@ struct tevent_req *smbd_smb1_do_locks_send( endtime = timeval_min(&endtime, &tmp); } + subreq = dbwrap_watched_watch_send( + state, state->ev, lck->data->record, blocking_pid); + if (tevent_req_nomem(subreq, req)) { + goto done; + } + TALLOC_FREE(lck); + tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); + ok = tevent_req_set_endtime(subreq, state->ev, endtime); if (!ok) { tevent_req_oom(req); @@ -450,14 +450,6 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) } state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; - subreq = dbwrap_watched_watch_send( - state, state->ev, lck->data->record, blocking_pid); - if (tevent_req_nomem(subreq, req)) { - goto done; - } - TALLOC_FREE(lck); - tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); - endtime = state->endtime; if (blocking_smblctx == UINT64_MAX) { @@ -472,6 +464,14 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) endtime = timeval_min(&endtime, &tmp); } + subreq = dbwrap_watched_watch_send( + state, state->ev, lck->data->record, blocking_pid); + if (tevent_req_nomem(subreq, req)) { + goto done; + } + TALLOC_FREE(lck); + tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); + ok = tevent_req_set_endtime(subreq, state->ev, endtime); if (!ok) { status = NT_STATUS_NO_MEMORY; -- 2.17.1 From 11e489b0789d7c9cc7f082c054c97c6c4c6f131a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Aug 2019 14:55:13 +0200 Subject: [PATCH 170/376] s3:blocking: fix the fsp->blocked_smb1_lock_reqs handling A new request is first checks against all pending requests before checking the already granted locks. Before we retried the lock array of another request (the first in the list), but then finished current request, which is wrong. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 312327106271abafeb53e62dfb71a38bf93e2d41) --- selftest/knownfail.d/multilock | 4 - source3/smbd/blocking.c | 134 ++++++++++++++++++++++++++++++--- 2 files changed, 125 insertions(+), 13 deletions(-) delete mode 100644 selftest/knownfail.d/multilock diff --git a/selftest/knownfail.d/multilock b/selftest/knownfail.d/multilock deleted file mode 100644 index 9fa497bd643..00000000000 --- a/selftest/knownfail.d/multilock +++ /dev/null @@ -1,4 +0,0 @@ -^samba3.raw.lock.multilock3.*nt4_dc -^samba3.raw.lock.multilock4.*nt4_dc -^samba3.raw.lock.multilock5.*nt4_dc -^samba3.raw.lock.multilock6.*nt4_dc diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ac90f8c3ef1..39042d2f46d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -116,6 +116,14 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req); static void smbd_smb1_do_locks_retry(struct tevent_req *subreq); static void smbd_smb1_blocked_locks_cleanup( struct tevent_req *req, enum tevent_req_state req_state); +static NTSTATUS smbd_smb1_do_locks_check( + struct files_struct *fsp, + enum brl_flavour lock_flav, + uint16_t num_locks, + struct smbd_lock_element *locks, + uint16_t *blocker_idx, + struct server_id *blocking_pid, + uint64_t *blocking_smblctx); static void smbd_smb1_do_locks_setup_timeout( struct smbd_smb1_do_locks_state *state, @@ -264,7 +272,7 @@ struct tevent_req *smbd_smb1_do_locks_send( return tevent_req_post(req, ev); } - status = smbd_do_locks_try( + status = smbd_smb1_do_locks_check( state->fsp, state->lock_flav, state->num_locks, @@ -390,15 +398,123 @@ static void smbd_smb1_blocked_locks_cleanup( fsp, blocked, struct tevent_req *, num_blocked-1); } +static NTSTATUS smbd_smb1_do_locks_check_blocked( + uint16_t num_blocked, + struct smbd_lock_element *blocked, + uint16_t num_locks, + struct smbd_lock_element *locks, + uint16_t *blocker_idx, + uint64_t *blocking_smblctx) +{ + uint16_t li; + + for (li=0; li < num_locks; li++) { + struct smbd_lock_element *l = &locks[li]; + uint16_t bi; + bool valid; + + valid = byte_range_valid(l->offset, l->count); + if (!valid) { + return NT_STATUS_INVALID_LOCK_RANGE; + } + + for (bi = 0; bi < num_blocked; bi++) { + struct smbd_lock_element *b = &blocked[li]; + bool overlap; + + /* Read locks never conflict. */ + if (l->brltype == READ_LOCK && b->brltype == READ_LOCK) { + continue; + } + + overlap = byte_range_overlap(l->offset, + l->count, + b->offset, + b->count); + if (!overlap) { + continue; + } + + *blocker_idx = li; + *blocking_smblctx = b->smblctx; + return NT_STATUS_LOCK_NOT_GRANTED; + } + } + + return NT_STATUS_OK; +} + +static NTSTATUS smbd_smb1_do_locks_check( + struct files_struct *fsp, + enum brl_flavour lock_flav, + uint16_t num_locks, + struct smbd_lock_element *locks, + uint16_t *blocker_idx, + struct server_id *blocking_pid, + uint64_t *blocking_smblctx) +{ + struct tevent_req **blocked = fsp->blocked_smb1_lock_reqs; + size_t num_blocked = talloc_array_length(blocked); + NTSTATUS status; + size_t bi; + + /* + * We check the pending/blocked requests + * from the oldest to the youngest request. + * + * Note due to the retry logic the current request + * might already be in the list. + */ + + for (bi = 0; bi < num_blocked; bi++) { + struct smbd_smb1_do_locks_state *blocked_state = + tevent_req_data(blocked[bi], + struct smbd_smb1_do_locks_state); + + if (blocked_state->locks == locks) { + SMB_ASSERT(blocked_state->num_locks == num_locks); + SMB_ASSERT(blocked_state->lock_flav == lock_flav); + + /* + * We found ourself... + */ + break; + } + + status = smbd_smb1_do_locks_check_blocked( + blocked_state->num_locks, + blocked_state->locks, + num_locks, + locks, + blocker_idx, + blocking_smblctx); + if (!NT_STATUS_IS_OK(status)) { + *blocking_pid = messaging_server_id( + fsp->conn->sconn->msg_ctx); + return status; + } + } + + status = smbd_do_locks_try( + fsp, + lock_flav, + num_locks, + locks, + blocker_idx, + blocking_pid, + blocking_smblctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + static void smbd_smb1_do_locks_try(struct tevent_req *req) { struct smbd_smb1_do_locks_state *state = tevent_req_data( req, struct smbd_smb1_do_locks_state); struct files_struct *fsp = state->fsp; - struct tevent_req **blocked = fsp->blocked_smb1_lock_reqs; - struct tevent_req *retry_req = blocked[0]; - struct smbd_smb1_do_locks_state *retry_state = tevent_req_data( - retry_req, struct smbd_smb1_do_locks_state); struct share_mode_lock *lck; struct timeval endtime = { 0 }; struct server_id blocking_pid = { 0 }; @@ -414,11 +530,11 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) return; } - status = smbd_do_locks_try( + status = smbd_smb1_do_locks_check( fsp, - retry_state->lock_flav, - retry_state->num_locks, - retry_state->locks, + state->lock_flav, + state->num_locks, + state->locks, &state->blocker, &blocking_pid, &blocking_smblctx); -- 2.17.1 From 5e9d294a045d7b7e1d77dd5f306d74b165585344 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 18:18:50 +0200 Subject: [PATCH 171/376] s3:blocking: call smbd_smb1_do_locks_setup_timeout() also in smbd_smb1_do_locks_try() This is a noop if smbd_smb1_do_locks_setup_timeout() was called before. But it allows us to use smbd_smb1_do_locks_try() in smbd_smb1_do_locks_send() in a following commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 6e30a89b3f00ad55391454fbaa1272074e1962f0) --- source3/smbd/blocking.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 39042d2f46d..77dfc5a3d44 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -545,6 +545,11 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) goto done; } + smbd_smb1_do_locks_setup_timeout(state, &state->locks[state->blocker]); + DBG_DEBUG("timeout=%"PRIu32", blocking_smblctx=%"PRIu64"\n", + state->timeout, + blocking_smblctx); + /* * The client specified timeout expired * avoid further retries. -- 2.17.1 From c8086b8873b37fde75dfbcd0054b5db7565b8708 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Aug 2019 20:09:55 +0200 Subject: [PATCH 172/376] s3:blocking: make use of smbd_smb1_do_locks_try() in smbd_smb1_do_locks_send() We only need the logic to call smbd_smb1_do_locks_check() and a possible retry once in smbd_smb1_do_locks_try(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8975673e3c3f9f7dbdb7ba7562bb81a62cd24e2e) --- source3/smbd/blocking.c | 90 ++--------------------------------------- 1 file changed, 4 insertions(+), 86 deletions(-) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 77dfc5a3d44..514985bcd75 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -224,15 +224,9 @@ struct tevent_req *smbd_smb1_do_locks_send( uint16_t num_locks, struct smbd_lock_element *locks) { - struct tevent_req *req = NULL, *subreq = NULL; + struct tevent_req *req = NULL; struct smbd_smb1_do_locks_state *state = NULL; - struct share_mode_lock *lck = NULL; - struct server_id blocking_pid = { 0 }; - uint64_t blocking_smblctx = 0; - struct timeval endtime = { 0 }; - NTSTATUS status = NT_STATUS_OK; bool ok; - bool expired; req = tevent_req_create( mem_ctx, &state, struct smbd_smb1_do_locks_state); @@ -266,94 +260,18 @@ struct tevent_req *smbd_smb1_do_locks_send( return tevent_req_post(req, ev); } - lck = get_existing_share_mode_lock(state, state->fsp->file_id); - if (tevent_req_nomem(lck, req)) { - DBG_DEBUG("Could not get share mode lock\n"); + smbd_smb1_do_locks_try(req); + if (!tevent_req_is_in_progress(req)) { return tevent_req_post(req, ev); } - status = smbd_smb1_do_locks_check( - state->fsp, - state->lock_flav, - state->num_locks, - state->locks, - &state->blocker, - &blocking_pid, - &blocking_smblctx); - if (NT_STATUS_IS_OK(status)) { - tevent_req_done(req); - goto done; - } - if (!ERROR_WAS_LOCK_DENIED(status)) { - tevent_req_nterror(req, status); - goto done; - } - - smbd_smb1_do_locks_setup_timeout(state, &locks[state->blocker]); - DBG_DEBUG("timeout=%"PRIu32", blocking_smblctx=%"PRIu64"\n", - state->timeout, - blocking_smblctx); - - /* - * The client specified timeout expired - * avoid further retries. - * - * Otherwise keep waiting either waiting - * for changes in locking.tdb or the polling - * mode timers waiting for posix locks. - * - * If the endtime is not elapsed yet, - * it means we'll retry after a timeout. - * In that case we'll have to return - * NT_STATUS_FILE_LOCK_CONFLICT - * instead of NT_STATUS_LOCK_NOT_GRANTED. - */ - expired = timeval_expired(&state->endtime); - if (expired) { - status = state->deny_status; - tevent_req_nterror(req, status); - goto done; - } - state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; - - endtime = state->endtime; - - if (blocking_smblctx == UINT64_MAX) { - struct timeval tmp; - - smbd_smb1_do_locks_update_polling_msecs(state); - - DBG_DEBUG("Blocked on a posix lock. Retry in %"PRIu32" msecs\n", - state->polling_msecs); - - tmp = timeval_current_ofs_msec(state->polling_msecs); - endtime = timeval_min(&endtime, &tmp); - } - - subreq = dbwrap_watched_watch_send( - state, state->ev, lck->data->record, blocking_pid); - if (tevent_req_nomem(subreq, req)) { - goto done; - } - TALLOC_FREE(lck); - tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); - - ok = tevent_req_set_endtime(subreq, state->ev, endtime); - if (!ok) { - tevent_req_oom(req); - goto done; - } - ok = smbd_smb1_fsp_add_blocked_lock_req(fsp, req); if (!ok) { tevent_req_oom(req); - goto done; + return tevent_req_post(req, ev); } tevent_req_set_cleanup_fn(req, smbd_smb1_blocked_locks_cleanup); return req; -done: - TALLOC_FREE(lck); - return tevent_req_post(req, ev); } static void smbd_smb1_blocked_locks_cleanup( -- 2.17.1 From a1117587afb6bf2f813982dfca4a47e982f44b96 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 15:29:32 +0200 Subject: [PATCH 173/376] s3:blocking: handle NT_STATUS_RETRY from the VFS backend This allows the VFS backends to implement async byte range locking. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7d1cd6f22e7e3d95aba04c45776057945c2a5e30) --- source3/smbd/blocking.c | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 514985bcd75..fbd1ea812f3 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -103,6 +103,7 @@ struct smbd_smb1_do_locks_state { struct files_struct *fsp; uint32_t timeout; uint32_t polling_msecs; + uint32_t retry_msecs; struct timeval endtime; bool large_offset; /* required for correct cancel */ enum brl_flavour lock_flav; @@ -187,6 +188,33 @@ set_endtime: (state->timeout % 1000) * 1000); } +static void smbd_smb1_do_locks_update_retry_msecs( + struct smbd_smb1_do_locks_state *state) +{ + /* + * The default lp_lock_spin_time() is 200ms, + * we just use half of it to trigger the first retry. + * + * v_min is in the range of 0.001 to 10 secs + * (0.1 secs by default) + * + * v_max is in the range of 0.01 to 100 secs + * (1.0 secs by default) + * + * The typical steps are: + * 0.1, 0.2, 0.3, 0.4, ... 1.0 + */ + uint32_t v_min = MAX(2, MIN(20000, lp_lock_spin_time()))/2; + uint32_t v_max = 10 * v_min; + + if (state->retry_msecs >= v_max) { + state->retry_msecs = v_max; + return; + } + + state->retry_msecs += v_min; +} + static void smbd_smb1_do_locks_update_polling_msecs( struct smbd_smb1_do_locks_state *state) { @@ -459,9 +487,60 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) if (NT_STATUS_IS_OK(status)) { goto done; } + if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { + /* + * We got NT_STATUS_RETRY, + * we reset polling_msecs so that + * that the retries based on LOCK_NOT_GRANTED + * will later start with small intervalls again. + */ + state->polling_msecs = 0; + + /* + * The backend wasn't able to decide yet. + * We need to wait even for non-blocking + * locks. + * + * The backend uses blocking_smblctx == UINT64_MAX + * to indicate that we should use retry timers. + * + * It uses blocking_smblctx == 0 to indicate + * it will use share_mode_wakeup_waiters() + * to wake us. Note that unrelated changes in + * locking.tdb may cause retries. + */ + + if (blocking_smblctx != UINT64_MAX) { + SMB_ASSERT(blocking_smblctx == 0); + goto setup_retry; + } + + smbd_smb1_do_locks_update_retry_msecs(state); + + DBG_DEBUG("Waiting for a backend decision. " + "Retry in %"PRIu32" msecs\n", + state->retry_msecs); + + /* + * We completely ignore state->endtime here + * we we'll wait for a backend decision forever. + * If the backend is smart enough to implement + * some NT_STATUS_RETRY logic, it has to + * switch to any other status after in order + * to avoid waiting forever. + */ + endtime = timeval_current_ofs_msec(state->retry_msecs); + goto setup_retry; + } if (!ERROR_WAS_LOCK_DENIED(status)) { goto done; } + /* + * We got LOCK_NOT_GRANTED, make sure + * a following STATUS_RETRY will start + * with short intervalls again. + */ + state->retry_msecs = 0; smbd_smb1_do_locks_setup_timeout(state, &state->locks[state->blocker]); DBG_DEBUG("timeout=%"PRIu32", blocking_smblctx=%"PRIu64"\n", @@ -503,6 +582,7 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) endtime = timeval_min(&endtime, &tmp); } +setup_retry: subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); if (tevent_req_nomem(subreq, req)) { @@ -511,6 +591,10 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) TALLOC_FREE(lck); tevent_req_set_callback(subreq, smbd_smb1_do_locks_retry, req); + if (timeval_is_zero(&endtime)) { + return; + } + ok = tevent_req_set_endtime(subreq, state->ev, endtime); if (!ok) { status = NT_STATUS_NO_MEMORY; -- 2.17.1 From 74527a20584bd9d22c8487a6ebdeaca21525afe3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 16:25:59 +0200 Subject: [PATCH 174/376] s3:smb2_lock: handle NT_STATUS_RETRY from the VFS backend This allows the VFS backends to implement async byte range locking. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7471b0f63276e707784c98b832992ff08b1898ef) --- source3/smbd/smb2_lock.c | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 8ba54fe6995..26de8b521ed 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -44,6 +44,7 @@ struct smbd_smb2_lock_state { struct files_struct *fsp; bool blocking; uint32_t polling_msecs; + uint32_t retry_msecs; uint16_t lock_count; struct smbd_lock_element *locks; }; @@ -372,6 +373,33 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return req; } +static void smbd_smb2_lock_update_retry_msecs( + struct smbd_smb2_lock_state *state) +{ + /* + * The default lp_lock_spin_time() is 200ms, + * we just use half of it to trigger the first retry. + * + * v_min is in the range of 0.001 to 10 secs + * (0.1 secs by default) + * + * v_max is in the range of 0.01 to 100 secs + * (1.0 secs by default) + * + * The typical steps are: + * 0.1, 0.2, 0.3, 0.4, ... 1.0 + */ + uint32_t v_min = MAX(2, MIN(20000, lp_lock_spin_time()))/2; + uint32_t v_max = 10 * v_min; + + if (state->retry_msecs >= v_max) { + state->retry_msecs = v_max; + return; + } + + state->retry_msecs += v_min; +} + static void smbd_smb2_lock_update_polling_msecs( struct smbd_smb2_lock_state *state) { @@ -429,6 +457,51 @@ static void smbd_smb2_lock_try(struct tevent_req *req) tevent_req_done(req); return; } + if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { + /* + * We got NT_STATUS_RETRY, + * we reset polling_msecs so that + * that the retries based on LOCK_NOT_GRANTED + * will later start with small intervalls again. + */ + state->polling_msecs = 0; + + /* + * The backend wasn't able to decide yet. + * We need to wait even for non-blocking + * locks. + * + * The backend uses blocking_smblctx == UINT64_MAX + * to indicate that we should use retry timers. + * + * It uses blocking_smblctx == 0 to indicate + * it will use share_mode_wakeup_waiters() + * to wake us. Note that unrelated changes in + * locking.tdb may cause retries. + */ + + if (blocking_smblctx != UINT64_MAX) { + SMB_ASSERT(blocking_smblctx == 0); + goto setup_retry; + } + + smbd_smb2_lock_update_retry_msecs(state); + + DBG_DEBUG("Waiting for a backend decision. " + "Retry in %"PRIu32" msecs\n", + state->retry_msecs); + + /* + * We completely ignore state->endtime here + * we we'll wait for a backend decision forever. + * If the backend is smart enough to implement + * some NT_STATUS_RETRY logic, it has to + * switch to any other status after in order + * to avoid waiting forever. + */ + endtime = timeval_current_ofs_msec(state->retry_msecs); + goto setup_retry; + } if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { /* * This is a bug and will be changed into an assert @@ -447,6 +520,12 @@ static void smbd_smb2_lock_try(struct tevent_req *req) tevent_req_nterror(req, status); return; } + /* + * We got LOCK_NOT_GRANTED, make sure + * a following STATUS_RETRY will start + * with short intervalls again. + */ + state->retry_msecs = 0; if (!state->blocking) { TALLOC_FREE(lck); @@ -463,6 +542,7 @@ static void smbd_smb2_lock_try(struct tevent_req *req) endtime = timeval_current_ofs_msec(state->polling_msecs); } +setup_retry: DBG_DEBUG("Watching share mode lock\n"); subreq = dbwrap_watched_watch_send( -- 2.17.1 From ec21e68912d2c9b1f4c3aa57d9b34db038a6b66c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 8 Aug 2019 19:26:28 +0200 Subject: [PATCH 175/376] s3:locking: add brl_req_guid() and brl_req_mem_ctx() helper functions This allows the vfs backend to detect a retry and keep state between the retries. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 66d92f37c3a643d97489a59bb6d1e75e91528c20) --- source3/include/locking.h | 2 ++ source3/locking/brlock.c | 45 +++++++++++++++++++++++++++++++++---- source3/locking/locking.c | 11 ++++++++- source3/locking/proto.h | 8 +++++++ source3/modules/vfs_fruit.c | 13 +++++++++++ source3/smbd/blocking.c | 2 ++ source3/smbd/globals.c | 18 +++++++++++++++ source3/smbd/globals.h | 2 ++ source3/smbd/reply.c | 7 ++++++ source3/smbd/smb2_lock.c | 1 + source3/smbd/trans2.c | 2 ++ 11 files changed, 106 insertions(+), 5 deletions(-) diff --git a/source3/include/locking.h b/source3/include/locking.h index 3e7560bef9e..0175db2dd47 100644 --- a/source3/include/locking.h +++ b/source3/include/locking.h @@ -30,6 +30,7 @@ enum brl_type {READ_LOCK, WRITE_LOCK, UNLOCK_LOCK}; enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1}; #include "librpc/gen_ndr/server_id.h" +#include "librpc/gen_ndr/misc.h" /* This contains elements that differentiate locks. The smbpid is a client supplied pid, and is essentially the locking context for @@ -62,6 +63,7 @@ struct lock_struct { }; struct smbd_lock_element { + struct GUID req_guid; uint64_t smblctx; enum brl_type brltype; uint64_t offset; diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 0a85bd0b057..f22580164f9 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -46,6 +46,8 @@ static struct db_context *brlock_db; struct byte_range_lock { struct files_struct *fsp; + TALLOC_CTX *req_mem_ctx; + const struct GUID *req_guid; unsigned int num_locks; bool modified; struct lock_struct *lock_data; @@ -84,6 +86,25 @@ struct files_struct *brl_fsp(struct byte_range_lock *brl) return brl->fsp; } +TALLOC_CTX *brl_req_mem_ctx(const struct byte_range_lock *brl) +{ + if (brl->req_mem_ctx == NULL) { + return talloc_get_type_abort(brl, struct byte_range_lock); + } + + return brl->req_mem_ctx; +} + +const struct GUID *brl_req_guid(const struct byte_range_lock *brl) +{ + if (brl->req_guid == NULL) { + static const struct GUID brl_zero_req_guid; + return &brl_zero_req_guid; + } + + return brl->req_guid; +} + /**************************************************************************** See if two locking contexts are equal. ****************************************************************************/ @@ -1823,6 +1844,25 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp) return br_lck; } +struct byte_range_lock *brl_get_locks_for_locking(TALLOC_CTX *mem_ctx, + files_struct *fsp, + TALLOC_CTX *req_mem_ctx, + const struct GUID *req_guid) +{ + struct byte_range_lock *br_lck = NULL; + + br_lck = brl_get_locks(mem_ctx, fsp); + if (br_lck == NULL) { + return NULL; + } + SMB_ASSERT(req_mem_ctx != NULL); + br_lck->req_mem_ctx = req_mem_ctx; + SMB_ASSERT(req_guid != NULL); + br_lck->req_guid = req_guid; + + return br_lck; +} + struct brl_get_locks_readonly_state { TALLOC_CTX *mem_ctx; struct byte_range_lock **br_lock; @@ -1884,14 +1924,11 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) /* * No locks on this file. Return an empty br_lock. */ - br_lock = talloc(fsp, struct byte_range_lock); + br_lock = talloc_zero(fsp, struct byte_range_lock); if (br_lock == NULL) { return NULL; } - br_lock->num_locks = 0; - br_lock->lock_data = NULL; - } else if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not parse byte range lock record: " "%s\n", nt_errstr(status))); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d87a882d14f..8fa1237d6ad 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -232,6 +232,8 @@ static void decrement_current_lock_count(files_struct *fsp, struct do_lock_state { struct files_struct *fsp; + TALLOC_CTX *req_mem_ctx; + const struct GUID *req_guid; uint64_t smblctx; uint64_t count; uint64_t offset; @@ -251,7 +253,10 @@ static void do_lock_fn( struct do_lock_state *state = private_data; struct byte_range_lock *br_lck = NULL; - br_lck = brl_get_locks(talloc_tos(), state->fsp); + br_lck = brl_get_locks_for_locking(talloc_tos(), + state->fsp, + state->req_mem_ctx, + state->req_guid); if (br_lck == NULL) { state->status = NT_STATUS_NO_MEMORY; return; @@ -272,6 +277,8 @@ static void do_lock_fn( } NTSTATUS do_lock(files_struct *fsp, + TALLOC_CTX *req_mem_ctx, + const struct GUID *req_guid, uint64_t smblctx, uint64_t count, uint64_t offset, @@ -282,6 +289,8 @@ NTSTATUS do_lock(files_struct *fsp, { struct do_lock_state state = { .fsp = fsp, + .req_mem_ctx = req_mem_ctx, + .req_guid = req_guid, .smblctx = smblctx, .count = count, .offset = offset, diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 7cb8bf3e3c9..7cf681561bc 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -30,6 +30,8 @@ void brl_shutdown(void); unsigned int brl_num_locks(const struct byte_range_lock *brl); struct files_struct *brl_fsp(struct byte_range_lock *brl); +TALLOC_CTX *brl_req_mem_ctx(const struct byte_range_lock *brl); +const struct GUID *brl_req_guid(const struct byte_range_lock *brl); bool byte_range_valid(uint64_t ofs, uint64_t len); bool byte_range_overlap(uint64_t ofs1, @@ -76,6 +78,10 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid, br_off start, br_off size, void *private_data), void *private_data); +struct byte_range_lock *brl_get_locks_for_locking(TALLOC_CTX *mem_ctx, + files_struct *fsp, + TALLOC_CTX *req_mem_ctx, + const struct GUID *req_guid); struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp); struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp); @@ -100,6 +106,8 @@ NTSTATUS query_lock(files_struct *fsp, enum brl_type *plock_type, enum brl_flavour lock_flav); NTSTATUS do_lock(files_struct *fsp, + TALLOC_CTX *req_mem_ctx, + const struct GUID *req_guid, uint64_t smblctx, uint64_t count, uint64_t offset, diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 0be7f20e9af..85c7af21d58 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -2621,6 +2621,7 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle, bool netatalk_already_open_for_writing = false; bool netatalk_already_open_with_deny_read = false; bool netatalk_already_open_with_deny_write = false; + struct GUID req_guid = GUID_random(); /* FIXME: hardcoded data fork, add resource fork */ enum apple_fork fork_type = APPLE_FORK_DATA; @@ -2684,8 +2685,11 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle, /* Set NetAtalk locks matching our access */ if (access_mask & FILE_READ_DATA) { off = access_to_netatalk_brl(fork_type, FILE_READ_DATA); + req_guid.time_hi_and_version = __LINE__; status = do_lock( fsp, + talloc_tos(), + &req_guid, fsp->op->global->open_persistent_id, 1, off, @@ -2701,8 +2705,11 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle, if (!share_for_read) { off = denymode_to_netatalk_brl(fork_type, DENY_READ); + req_guid.time_hi_and_version = __LINE__; status = do_lock( fsp, + talloc_tos(), + &req_guid, fsp->op->global->open_persistent_id, 1, off, @@ -2718,8 +2725,11 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle, if (access_mask & FILE_WRITE_DATA) { off = access_to_netatalk_brl(fork_type, FILE_WRITE_DATA); + req_guid.time_hi_and_version = __LINE__; status = do_lock( fsp, + talloc_tos(), + &req_guid, fsp->op->global->open_persistent_id, 1, off, @@ -2735,8 +2745,11 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle, if (!share_for_write) { off = denymode_to_netatalk_brl(fork_type, DENY_WRITE); + req_guid.time_hi_and_version = __LINE__; status = do_lock( fsp, + talloc_tos(), + &req_guid, fsp->op->global->open_persistent_id, 1, off, diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index fbd1ea812f3..94e75a9b405 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -45,6 +45,8 @@ NTSTATUS smbd_do_locks_try( status = do_lock( fsp, + locks, /* req_mem_ctx */ + &e->req_guid, e->smblctx, e->count, e->offset, diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 6bc448b901d..0cdce20d122 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -109,3 +109,21 @@ void smbd_init_globals(void) ZERO_STRUCT(sec_ctx_stack); } + +struct GUID smbd_request_guid(struct smb_request *smb1req, uint16_t idx) +{ + struct GUID v = { + .time_low = (uint32_t)smb1req->mid, + .time_hi_and_version = idx, + }; + + if (smb1req->smb2req != NULL) { + v.time_mid = (uint16_t)smb1req->smb2req->current_idx; + } else { + v.time_mid = (uint16_t)(uintptr_t)smb1req->vwv; + } + + SBVAL((uint8_t *)&v, 8, (uintptr_t)smb1req->xconn); + + return v; +} diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 03d50882d16..47916ba29a1 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -115,6 +115,8 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn); void smbd_lock_socket(struct smbXsrv_connection *xconn); void smbd_unlock_socket(struct smbXsrv_connection *xconn); +struct GUID smbd_request_guid(struct smb_request *smb1req, uint16_t idx); + NTSTATUS smbd_do_unlocking(struct smb_request *req, files_struct *fsp, uint16_t num_ulocks, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2622681a2da..dec67a10cae 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3842,6 +3842,7 @@ void reply_lockread(struct smb_request *req) */ *lck = (struct smbd_lock_element) { + .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = WRITE_LOCK, .count = SVAL(req->vwv+1, 0), @@ -4869,6 +4870,7 @@ void reply_writeunlock(struct smb_request *req) if (numtowrite && !fsp->print_file) { struct smbd_lock_element l = { + .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = UNLOCK_LOCK, .offset = startpos, @@ -5764,6 +5766,7 @@ void reply_lock(struct smb_request *req) } *lck = (struct smbd_lock_element) { + .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = WRITE_LOCK, .count = IVAL(req->vwv+1, 0), @@ -5855,6 +5858,7 @@ void reply_unlock(struct smb_request *req) } lck = (struct smbd_lock_element) { + .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = UNLOCK_LOCK, .offset = IVAL(req->vwv+3, 0), @@ -8433,6 +8437,8 @@ void reply_lockingX(struct smb_request *req) * smb_unlkrng structs */ for (i = 0; i < num_ulocks; i++) { + ulocks[i].req_guid = smbd_request_guid(req, + UINT16_MAX - i), ulocks[i].smblctx = get_lock_pid( data, i, large_file_format); ulocks[i].count = get_lock_count( @@ -8490,6 +8496,7 @@ void reply_lockingX(struct smb_request *req) } for (i = 0; i < num_locks; i++) { + locks[i].req_guid = smbd_request_guid(req, i), locks[i].smblctx = get_lock_pid(data, i, large_file_format); locks[i].count = get_lock_count(data, i, large_file_format); locks[i].offset = get_lock_offset(data, i, large_file_format); diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 26de8b521ed..381aae6cb60 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -318,6 +318,7 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + locks[i].req_guid = smbd_request_guid(smb2req->smb1req, i); locks[i].smblctx = fsp->op->global->open_persistent_id; locks[i].offset = in_locks[i].offset; locks[i].count = in_locks[i].length; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5b99240e9e8..0539b35bb73 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7572,6 +7572,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, if (lock_type == UNLOCK_LOCK) { struct smbd_lock_element l = { + .req_guid = smbd_request_guid(req, 0), .smblctx = smblctx, .brltype = UNLOCK_LOCK, .offset = offset, @@ -7587,6 +7588,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, } *lck = (struct smbd_lock_element) { + .req_guid = smbd_request_guid(req, 0), .smblctx = smblctx, .brltype = lock_type, .count = count, -- 2.17.1 From 9bf1c5c3e48ff905eec6f9ee469f1067b4105d42 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 18:22:38 +0200 Subject: [PATCH 176/376] vfs_delay_inject: add support for brl_[un]lock_windows() This demonstrates the two ways to handle the retry: - smb layer retry => plock->context.smblctx = UINT64_MAX - vfs backend retry => plock->context.smblctx = 0 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit c2503a5c68e967054ab84ca0d8ce693200c2e002) --- source3/modules/vfs_delay_inject.c | 117 +++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/source3/modules/vfs_delay_inject.c b/source3/modules/vfs_delay_inject.c index d561fadb03b..569bd40054a 100644 --- a/source3/modules/vfs_delay_inject.c +++ b/source3/modules/vfs_delay_inject.c @@ -304,12 +304,129 @@ static ssize_t vfs_delay_inject_pwrite_recv(struct tevent_req *req, return state->ret; } +struct vfs_delay_inject_brl_lock_state { + struct vfs_delay_inject_brl_lock_state *prev, *next; + struct files_struct *fsp; + struct GUID req_guid; + struct timeval delay_tv; + struct tevent_timer *delay_te; +}; + +static struct vfs_delay_inject_brl_lock_state *brl_lock_states; + +static int vfs_delay_inject_brl_lock_state_destructor(struct vfs_delay_inject_brl_lock_state *state) +{ + DLIST_REMOVE(brl_lock_states, state); + return 0; +} + +static void vfs_delay_inject_brl_lock_timer(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + struct vfs_delay_inject_brl_lock_state *state = + talloc_get_type_abort(private_data, + struct vfs_delay_inject_brl_lock_state); + NTSTATUS status; + + TALLOC_FREE(state->delay_te); + + status = share_mode_wakeup_waiters(state->fsp->file_id); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("share_mode_wakeup_waiters(%s) %s\n", + file_id_string_tos(&state->fsp->file_id), + nt_errstr(status)); + } +} + +static NTSTATUS vfs_delay_inject_brl_lock_windows(struct vfs_handle_struct *handle, + struct byte_range_lock *br_lck, + struct lock_struct *plock) +{ + struct files_struct *fsp = brl_fsp(br_lck); + TALLOC_CTX *req_mem_ctx = brl_req_mem_ctx(br_lck); + const struct GUID *req_guid = brl_req_guid(br_lck); + struct vfs_delay_inject_brl_lock_state *state = NULL; + bool expired; + + for (state = brl_lock_states; state != NULL; state = state->next) { + bool match; + + match = GUID_equal(&state->req_guid, req_guid); + if (match) { + break; + } + } + + if (state == NULL) { + int delay; + bool use_timer; + + state = talloc_zero(req_mem_ctx, + struct vfs_delay_inject_brl_lock_state); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + state->fsp = fsp; + state->req_guid = *req_guid; + + delay = lp_parm_int(SNUM(handle->conn), + "delay_inject", "brl_lock_windows", 0); + state->delay_tv = timeval_current_ofs_msec(delay); + + use_timer = lp_parm_bool(SNUM(handle->conn), + "delay_inject", "brl_lock_windows_use_timer", true); + + if (use_timer) { + state->delay_te = tevent_add_timer( + global_event_context(), + state, + state->delay_tv, + vfs_delay_inject_brl_lock_timer, + state); + if (state->delay_te == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + + talloc_set_destructor(state, + vfs_delay_inject_brl_lock_state_destructor); + DLIST_ADD_END(brl_lock_states, state); + } + + if (state->delay_te != NULL) { + plock->context.smblctx = 0; + return NT_STATUS_RETRY; + } + + expired = timeval_expired(&state->delay_tv); + if (!expired) { + plock->context.smblctx = UINT64_MAX; + return NT_STATUS_RETRY; + } + + TALLOC_FREE(state); + + return SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock); +} + +static bool vfs_delay_inject_brl_unlock_windows(struct vfs_handle_struct *handle, + struct byte_range_lock *br_lck, + const struct lock_struct *plock) +{ + return SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, br_lck, plock); +} + static struct vfs_fn_pointers vfs_delay_inject_fns = { .ntimes_fn = vfs_delay_inject_ntimes, .pread_send_fn = vfs_delay_inject_pread_send, .pread_recv_fn = vfs_delay_inject_pread_recv, .pwrite_send_fn = vfs_delay_inject_pwrite_send, .pwrite_recv_fn = vfs_delay_inject_pwrite_recv, + + .brl_lock_windows_fn = vfs_delay_inject_brl_lock_windows, + .brl_unlock_windows_fn = vfs_delay_inject_brl_unlock_windows, }; static_decl_vfs; -- 2.17.1 From be42cfafee057993d038f7d476d094c53b00b57e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 20 Aug 2019 15:53:59 +0200 Subject: [PATCH 177/376] s3:selftest: add delay_inject:brl_lock_windows testing BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Mon Sep 9 15:42:45 UTC 2019 on sn-devel-184 (cherry picked from commit 2b43ce6704ecf035e6734337a2dea3458153a4b2) Autobuild-User(v4-11-test): Stefan Metzmacher Autobuild-Date(v4-11-test): Mon Sep 9 17:19:11 UTC 2019 on sn-devel-184 --- selftest/target/Samba3.pm | 12 ++++++++++++ source3/selftest/tests.py | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 9638bb44f08..131d576a767 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -2263,6 +2263,18 @@ sub provision($$$$$$$$$) delay_inject:pread_send = 2000 delay_inject:pwrite_send = 2000 +[brl_delay_inject1] + copy = tmp + vfs objects = delay_inject + delay_inject:brl_lock_windows = 90 + delay_inject:brl_lock_windows_use_timer = yes + +[brl_delay_inject2] + copy = tmp + vfs objects = delay_inject + delay_inject:brl_lock_windows = 90 + delay_inject:brl_lock_windows_use_timer = no + [delete_readonly] path = $prefix_abs/share delete readonly = yes diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index ebc366de3ea..31cb8ca33f1 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -531,6 +531,10 @@ for t in tests: plansmbtorture4testsuite(t, env, '//$SERVER/tmp -k no -U$DC_USERNAME@$REALM%$DC_PASSWORD', description='ntlm user@realm') elif t == "raw.samba3posixtimedlock" or t == "smb2.samba3misc": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmpguest -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/brl_delay_inject1 -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share', + description="brl_delay_inject1") + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/brl_delay_inject2 -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share', + description="brl_delay_inject2") plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpguest -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/ad_dc/share') elif t == "raw.chkpath": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD') -- 2.17.1 From 02ccbe08a53e385460d17b54bbabee5a362e1a5b Mon Sep 17 00:00:00 2001 From: Evgeny Sinelnikov Date: Wed, 31 Jul 2019 23:17:20 +0400 Subject: [PATCH 178/376] s3:ldap: Fix join with don't exists machine account MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add check for requested replies of existing machine object during join machine to domain. This solves regression fail during join with error: "None of the information to be translated has been translated." https://bugzilla.samba.org/show_bug.cgi?id=14007 Reviewed-by: Guenther Deschner Reviewed-by: Alexander Bokovoy Reviewed-by: Stefan Metzmacher Autobuild-User(master): Günther Deschner Autobuild-Date(master): Wed Sep 4 17:02:37 UTC 2019 on sn-devel-184 (cherry picked from commit ad4ef1657e9b2a088a3bfadcce196cfcceead1dc) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Tue Sep 10 09:13:15 UTC 2019 on sn-devel-184 --- source3/libads/ldap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 4f3d43b02b1..2110390b65f 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2121,13 +2121,14 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, } ret = ads_find_machine_acct(ads, &res, machine_escaped); - ads_msgfree(ads, res); - if (ADS_ERR_OK(ret)) { + if (ADS_ERR_OK(ret) && ads_count_replies(ads, res) == 1) { DBG_DEBUG("Host account for %s already exists.\n", machine_escaped); ret = ADS_ERROR_LDAP(LDAP_ALREADY_EXISTS); + ads_msgfree(ads, res); goto done; } + ads_msgfree(ads, res); new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_escaped, org_unit); samAccountName = talloc_asprintf(ctx, "%s$", machine_name); -- 2.17.1 From 0318b68675d0318027ff5b6abf4a0d010839e6fd Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:49:24 +0200 Subject: [PATCH 179/376] s4:torture: add a file-id related test Note I'm using the share vfs_fruit_xattr because I need a share with both a streams and a acl_* VFS object. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 2ecab3c60abf9baa16a6a5e3eba0fc4720def840) --- selftest/knownfail.d/samba3.smb2.create | 1 + source3/selftest/tests.py | 2 + source4/selftest/tests.py | 1 + source4/torture/smb2/create.c | 212 ++++++++++++++++++++++++ source4/torture/smb2/smb2.c | 1 + 5 files changed, 217 insertions(+) create mode 100644 selftest/knownfail.d/samba3.smb2.create diff --git a/selftest/knownfail.d/samba3.smb2.create b/selftest/knownfail.d/samba3.smb2.create new file mode 100644 index 00000000000..89455dacdf0 --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.create @@ -0,0 +1 @@ +^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 31cb8ca33f1..20f2eea7661 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -689,6 +689,8 @@ for t in tests: plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/delete_readonly -U$USERNAME%$PASSWORD --option=torture:delete_readonly=true') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') + elif t == "smb2.fileid": + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_xattr -U$USERNAME%$PASSWORD') elif t == "rpc.wkssvc": plansmbtorture4testsuite(t, "ad_member", '//$SERVER/tmp -U$DC_USERNAME%$DC_PASSWORD') elif t == "rpc.srvsvc": diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index bf3dd98cbef..3f55649f217 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -342,6 +342,7 @@ smb2_s3only = [ "smb2.kernel-oplocks", "smb2.durable-v2-delay", "smb2.aio_delay", + "smb2.fileid", ] smb2 = [x for x in smbtorture4_testsuites("smb2.") if x not in smb2_s3only] diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index 9b32062ab07..beddefc4c8d 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -1905,6 +1905,204 @@ done: return ret; } +static bool test_fileid(struct torture_context *tctx, + struct smb2_tree *tree) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + const char *fname = DNAME "\\foo"; + const char *sname = DNAME "\\foo:bar"; + struct smb2_handle testdirh; + struct smb2_handle h1; + struct smb2_create create; + union smb_fileinfo finfo; + union smb_setfileinfo sinfo; + struct smb2_find f; + unsigned int count; + union smb_search_data *d; + uint64_t fileid; + uint64_t stream_fileid; + NTSTATUS status; + bool ret = true; + + smb2_deltree(tree, DNAME); + + status = torture_smb2_testdir(tree, DNAME, &testdirh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir failed\n"); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN_IF, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + fileid = BVAL(&create.out.on_disk_id, 0); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + stream_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, stream_fileid, fileid, + ret, done, "bad fileid\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_write failed\n"); + + sinfo = (union smb_setfileinfo) { + .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, + .basic_info.in.file.handle = h1, + }; + unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL)); + + status = smb2_setinfo_file(tree, &sinfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_setinfo_file failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + +done: + smb2_util_close(tree, testdirh); + smb2_deltree(tree, DNAME); + talloc_free(mem_ctx); + return ret; +} + /* basic testing of SMB2 read */ @@ -1942,3 +2140,17 @@ struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx) return suite; } + +/* + basic testing of SMB2 File-IDs +*/ +struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = torture_suite_create(ctx, "fileid"); + + torture_suite_add_1smb2_test(suite, "fileid", test_fileid); + + suite->description = talloc_strdup(suite, "SMB2-CREATE tests"); + + return suite; +} diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c index e57dba3c1d9..7cca19e65d3 100644 --- a/source4/torture/smb2/smb2.c +++ b/source4/torture/smb2/smb2.c @@ -155,6 +155,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx) torture_suite_add_suite(suite, torture_smb2_aio_delay_init(suite)); torture_suite_add_suite(suite, torture_smb2_create_init(suite)); torture_suite_add_suite(suite, torture_smb2_twrp_init(suite)); + torture_suite_add_suite(suite, torture_smb2_fileid_init(suite)); torture_suite_add_suite(suite, torture_smb2_acls_init(suite)); torture_suite_add_suite(suite, torture_smb2_notify_init(suite)); torture_suite_add_suite(suite, torture_smb2_notify_inotify_init(suite)); -- 2.17.1 From cca34da443ed6ee530fcf8c0def63d4b00527ffd Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 3 Sep 2019 17:50:54 +0200 Subject: [PATCH 180/376] lib: add round_timespec_to_nttime() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 5403bb22e6cb39baf6dc1b91558744d41e9f6f64) --- lib/util/time.c | 9 +++++++++ lib/util/time.h | 1 + 2 files changed, 10 insertions(+) diff --git a/lib/util/time.c b/lib/util/time.c index bd067f84e8e..3a6043025f4 100644 --- a/lib/util/time.c +++ b/lib/util/time.c @@ -956,6 +956,15 @@ void round_timespec_to_usec(struct timespec *ts) } } +/**************************************************************************** + Round a timespec to NTTIME resolution. +****************************************************************************/ + +void round_timespec_to_nttime(struct timespec *ts) +{ + ts->tv_nsec = (ts->tv_nsec / 100) * 100; +} + /**************************************************************************** Put a 8 byte filetime from a struct timespec. Uses GMT. ****************************************************************************/ diff --git a/lib/util/time.h b/lib/util/time.h index 1988b330576..7a8f8af35d9 100644 --- a/lib/util/time.h +++ b/lib/util/time.h @@ -328,6 +328,7 @@ struct timespec timespec_min(const struct timespec *ts1, int timespec_compare(const struct timespec *ts1, const struct timespec *ts2); void round_timespec_to_sec(struct timespec *ts); void round_timespec_to_usec(struct timespec *ts); +void round_timespec_to_nttime(struct timespec *ts); NTTIME unix_timespec_to_nt_time(struct timespec ts); #endif /* _SAMBA_TIME_H_ */ -- 2.17.1 From 6dfeecf345c0a009fff6b233241156eff3160467 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 11:12:08 +0200 Subject: [PATCH 181/376] s3:lib: round itime to NTTIME resolution in make_file_id_from_itime() The rounding is needed because when a file is created via eg an SMB2 CREATE request, we need to calculate the correct File-ID for the QFID Create-Context or for a subsequent GETINFO SMB request on the same file-handle. Any later metadata request that received the File-ID will do so by going through dos_mode() -> ... -> parse_dos_attribute_blob(), where the File-ID will be calculated from the on-disk itime which has NTTIME resolution. As long as that is the only available itime backend, I'm rounding itime inside make_file_id_from_itime(), not in the callers. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 84abeaa60ffced276da2b28b8add6efaa6da5ca6) --- source3/lib/file_id.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source3/lib/file_id.c b/source3/lib/file_id.c index 7d4fb006afe..21f22ffbf3b 100644 --- a/source3/lib/file_id.c +++ b/source3/lib/file_id.c @@ -102,6 +102,8 @@ uint64_t make_file_id_from_itime(SMB_STRUCT_STAT *st) return ino; } + round_timespec_to_nttime(&itime); + file_id_low = itime.tv_nsec; if (file_id_low == 0) { /* -- 2.17.1 From d47f8ca1a769571dae73081cda6a01812c1a256c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:48:40 +0200 Subject: [PATCH 182/376] s3:smbd: ensure to update the File-ID in struct smb_filename Initialize the File-ID in fsp->fsp_name->st, any subsequent metadata fetch on this file-handle needs this, eg QFID SMB2 Create-Context or GETINFO SMB requests. It would be nice if SMB_VFS_SET_DOS_ATTRIBUTE() would do this, unfortunately it gets a const struct smb_filename. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 3483b75fed8985bd2968bbf8c85985107115fba8) --- source3/smbd/open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2ee4a2c4fca..a5650ac9c2d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3710,6 +3710,15 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (info == FILE_WAS_CREATED) { smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; + + if (lp_store_dos_attributes(SNUM(conn)) && + smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID) + { + uint64_t file_id; + + file_id = make_file_id_from_itime(&smb_fname->st); + update_stat_ex_file_id(&smb_fname->st, file_id); + } } if (info != FILE_WAS_OPENED) { @@ -3862,6 +3871,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, smb_dname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; if (lp_store_dos_attributes(SNUM(conn))) { + if (smb_dname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID) + { + uint64_t file_id; + + file_id = make_file_id_from_itime(&smb_dname->st); + update_stat_ex_file_id(&smb_dname->st, file_id); + } + if (!posix_open) { file_set_dosmode(conn, smb_dname, file_attributes | FILE_ATTRIBUTE_DIRECTORY, -- 2.17.1 From 4930920648ad6879a72c77d79508025478dcbaa2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:48:57 +0200 Subject: [PATCH 183/376] vfs_catia: stat info may have been updated, make sure to return changes BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 4e49999c97f53acc7006f1dc6b6812bb0e156db5) --- source3/modules/vfs_catia.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 762491ede31..1869d21dbcf 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -2377,6 +2377,10 @@ static NTSTATUS catia_get_dos_attributes(struct vfs_handle_struct *handle, status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle, mapped_smb_fname, dosmode); + if (NT_STATUS_IS_OK(status)) { + smb_fname->st = mapped_smb_fname->st; + } + TALLOC_FREE(mapped_name); TALLOC_FREE(mapped_smb_fname); -- 2.17.1 From cb09104951cdefba991464e486c536b06356fd25 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:49:47 +0200 Subject: [PATCH 184/376] s3:lib: add update_stat_ex_from_saved_stat() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit ac18730f10ce96a607a3a07e1360b522ebf72f38) --- source3/include/proto.h | 2 ++ source3/lib/system.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/source3/include/proto.h b/source3/include/proto.h index 8b387f7c563..ad6f3bbf9c3 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -223,6 +223,8 @@ void update_stat_ex_mtime(struct stat_ex *dst, struct timespec write_ts); void update_stat_ex_itime(struct stat_ex *dst, struct timespec itime); void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time); void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id); +void update_stat_ex_from_saved_stat(struct stat_ex *dst, + const struct stat_ex *src); int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times); int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, diff --git a/source3/lib/system.c b/source3/lib/system.c index a67388e436a..0620439c944 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -355,6 +355,26 @@ void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id) dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_FILE_ID; } +void update_stat_ex_from_saved_stat(struct stat_ex *dst, + const struct stat_ex *src) +{ + if (!VALID_STAT(*src)) { + return; + } + + if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) { + update_stat_ex_create_time(dst, src->st_ex_btime); + } + + if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) { + update_stat_ex_itime(dst, src->st_ex_itime); + } + + if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) { + update_stat_ex_file_id(dst, src->st_ex_file_id); + } +} + void init_stat_ex_from_stat (struct stat_ex *dst, const struct stat *src, bool fake_dir_create_times) -- 2.17.1 From b14dd975c754be30d247591190bec5db3f305245 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 07:57:34 +0200 Subject: [PATCH 185/376] s3: replace fsp_stat() with vfs_stat_fsp() Both functions do the same, they differ just in the type of the returned result. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit ab03394969f8a4c748aea7d0d8ed37f9ced6cc30) --- source3/modules/vfs_dirsort.c | 13 ++++++++----- source3/smbd/fileio.c | 17 ----------------- source3/smbd/proto.h | 1 - source3/smbd/reply.c | 23 +++++++++++++++-------- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c index c23f6f0152d..c6b5ea41c93 100644 --- a/source3/modules/vfs_dirsort.c +++ b/source3/modules/vfs_dirsort.c @@ -44,19 +44,22 @@ static bool get_sorted_dir_mtime(vfs_handle_struct *handle, { int ret; struct timespec mtime; + NTSTATUS status; if (data->fsp) { - ret = fsp_stat(data->fsp); + status = vfs_stat_fsp(data->fsp); + if (!NT_STATUS_IS_OK(status)) { + return false; + } mtime = data->fsp->fsp_name->st.st_ex_mtime; } else { ret = SMB_VFS_STAT(handle->conn, data->smb_fname); + if (ret == -1) { + return false; + } mtime = data->smb_fname->st.st_ex_mtime; } - if (ret == -1) { - return false; - } - *ret_mtime = mtime; return true; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a00b368f92b..067ce5a9ad4 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -1068,20 +1068,3 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug } return NT_STATUS_OK; } - -/************************************************************ - Perform a stat whether a valid fd or not. -************************************************************/ - -int fsp_stat(files_struct *fsp) -{ - if (fsp->fh->fd == -1) { - if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { - return SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); - } else { - return SMB_VFS_STAT(fsp->conn, fsp->fsp_name); - } - } else { - return SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } -} diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index cd1ec9a1f9e..10ffaf6e480 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -342,7 +342,6 @@ void delete_write_cache(files_struct *fsp); void set_filelen_write_cache(files_struct *fsp, off_t file_size); ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason); NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through); -int fsp_stat(files_struct *fsp); /* The following definitions come from smbd/filename.c */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dec67a10cae..35d1ae772d5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3662,6 +3662,7 @@ void reply_readbraw(struct smb_request *req) files_struct *fsp; struct lock_struct lock; off_t size = 0; + NTSTATUS status; START_PROFILE(SMBreadbraw); @@ -3759,7 +3760,8 @@ void reply_readbraw(struct smb_request *req) return; } - if (fsp_stat(fsp) == 0) { + status = vfs_stat_fsp(fsp); + if (NT_STATUS_IS_OK(status)) { size = fsp->fsp_name->st.st_ex_size; } @@ -4090,6 +4092,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, ssize_t nread = -1; struct lock_struct lock; int saved_errno = 0; + NTSTATUS status; init_strict_lock_struct(fsp, (uint64_t)req->smbpid, (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK, @@ -4114,8 +4117,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */]; DATA_BLOB header; - if(fsp_stat(fsp) == -1) { - reply_nterror(req, map_nt_error_from_unix(errno)); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); goto out; } @@ -5323,6 +5327,7 @@ void reply_lseek(struct smb_request *req) off_t res= -1; int mode,umode; files_struct *fsp; + NTSTATUS status; START_PROFILE(SMBlseek); @@ -5367,9 +5372,9 @@ void reply_lseek(struct smb_request *req) if(errno == EINVAL) { off_t current_pos = startpos; - if(fsp_stat(fsp) == -1) { - reply_nterror(req, - map_nt_error_from_unix(errno)); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBlseek); return; } @@ -8739,6 +8744,7 @@ void reply_getattrE(struct smb_request *req) int mode; files_struct *fsp; struct timespec create_ts; + NTSTATUS status; START_PROFILE(SMBgetattrE); @@ -8757,8 +8763,9 @@ void reply_getattrE(struct smb_request *req) } /* Do an fstat on this file */ - if(fsp_stat(fsp)) { - reply_nterror(req, map_nt_error_from_unix(errno)); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBgetattrE); return; } -- 2.17.1 From b4aaa612d33caf51b44830d75997d4ad93b7740d Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 08:03:53 +0200 Subject: [PATCH 186/376] s3:vfs: streamline vfs_stat_fsp() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit e00e78cfeda99bd5374eff8fb4ba84873e4e46b7) --- source3/smbd/vfs.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 51a4aeb0f22..67f7d6356a2 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1413,13 +1413,11 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) } else { ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); } - if (ret == -1) { - return map_nt_error_from_unix(errno); - } } else { - if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { - return map_nt_error_from_unix(errno); - } + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); + } + if (ret == -1) { + return map_nt_error_from_unix(errno); } return NT_STATUS_OK; } -- 2.17.1 From d887047aa0c2489d1d6251ffcb9ce083e86866e1 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 08:08:06 +0200 Subject: [PATCH 187/376] vfs: restore stat fields in vfs_stat_fsp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures we preserve btime, itime and File-ID. As the Durable Handles code calls vfs_stat_fsp() in the DH disconnect function, previously the btime was lost and NOT stored in the cookie. With this change the cookie will store the correct btime (and iflags), which requires us to call dos_mode() in the reconnect function to ensure we pass vfs_default_durable_reconnect_check_stat(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Tue Sep 10 20:22:21 UTC 2019 on sn-devel-184 (cherry picked from commit 95655fe683d499d93f3844ed72ad332ef64adb96) Autobuild-User(v4-11-test): Stefan Metzmacher Autobuild-Date(v4-11-test): Tue Sep 10 22:29:08 UTC 2019 on sn-devel-184 --- selftest/knownfail.d/samba3.smb2.create | 1 - source3/smbd/durable.c | 2 ++ source3/smbd/vfs.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/samba3.smb2.create diff --git a/selftest/knownfail.d/samba3.smb2.create b/selftest/knownfail.d/samba3.smb2.create deleted file mode 100644 index 89455dacdf0..00000000000 --- a/selftest/knownfail.d/samba3.smb2.create +++ /dev/null @@ -1 +0,0 @@ -^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c index 4aa5a2d619e..89c4c1e8d14 100644 --- a/source3/smbd/durable.c +++ b/source3/smbd/durable.c @@ -842,6 +842,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } + (void)dos_mode(fsp->conn, fsp->fsp_name); + ok = vfs_default_durable_reconnect_check_stat(&cookie.stat_info, &fsp->fsp_name->st, fsp_str_dbg(fsp)); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 67f7d6356a2..c8437a0c6c9 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1406,6 +1406,7 @@ int vfs_stat_smb_basename(struct connection_struct *conn, NTSTATUS vfs_stat_fsp(files_struct *fsp) { int ret; + struct stat_ex saved_stat = fsp->fsp_name->st; if(fsp->fh->fd == -1) { if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { @@ -1419,6 +1420,7 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) if (ret == -1) { return map_nt_error_from_unix(errno); } + update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat); return NT_STATUS_OK; } -- 2.17.1 From 76eab3e6bc9631437719bf9a7fbabb8e77ceb20a Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 10 Sep 2019 13:02:12 +0200 Subject: [PATCH 188/376] WHATSNEW: Remove paragraph about rejoining DCs. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 904db5fefc3..9069ca664ab 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -33,11 +33,6 @@ When either upgrading or downgrading, users should also avoid making any database modifications between installing the new Samba packages and starting the samba executable. -Note that when moving between major Samba releases in general, we recommend -that the AD DC is rejoined to the domain. Using this approach avoids the need -to explicitly downgrade the database manually. For more details, see: -https://wiki.samba.org/index.php/Upgrading_a_Samba_AD_DC - SMB1 is disabled by default --------------------------- -- 2.17.1 From 70906342a77e431e0ea5b482b9f35aa26a5d64bc Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 10 Sep 2019 09:19:32 +0200 Subject: [PATCH 189/376] WHATSNEW: Add release notes for Samba 4.11.0rc4. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 9069ca664ab..74d1de4c021 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,7 +1,7 @@ Release Announcements ===================== -This is the third release candidate of Samba 4.11. This is *not* +This is the fourth release candidate of Samba 4.11. This is *not* intended for production environments and is designed for testing purposes only. Please report any defects via the Samba bug reporting system at https://bugzilla.samba.org/. @@ -368,6 +368,45 @@ smb.conf changes encrypt passwords Deprecated +CHANGES SINCE 4.11.0rc3 +======================= + +o Douglas Bagnall + * BUG 14049: ldb: Don't try to save a value that isn't there. + * ldb_dn: Free dn components on explode failure. + * ldb: Do not allow adding a DN as a base to itself. + +o Andrew Bartlett + * ldb: Release ldb 2.0.7. + * BUG 13695: ldb: Correct Pigeonhole principle validation in + ldb_filter_attrs(). + * BUG 14049: Fix ldb dn crash. + * BUG 14117: Deprecate "lanman auth = yes" and "encrypt passwords = no". + +o Ralph Boehme + * BUG 14038: Fix compiling ctdb on older systems lacking POSIX robust + mutexes. + * BUG 14121: smbd returns bad File-ID on filehandle used to create a file or + directory. + +o Poornima G + * BUG 14098: vfs_glusterfs: Use pthreadpool for scheduling aio operations. + +o Stefan Metzmacher + * BUG 14055: Add the target server name of SMB 3.1.1 connections as a hint to + load balancers or servers with "multi-tenancy" support. + * BUG 14113: Fix byte range locking bugs/regressions. + +o Swen Schillig + * ldb: Fix mem-leak if talloc_realloc fails. + +o Evgeny Sinelnikov + * BUG 14007: Fix join with don't exists machine account. + +o Martin Schwenke + * BUG 14085: ctdb-recoverd: Only check for LMASTER nodes in the VNN map. + + CHANGES SINCE 4.11.0rc2 ======================= -- 2.17.1 From b788d502cd187d1d71310ab9384e0b2445062491 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 10 Sep 2019 13:00:53 +0200 Subject: [PATCH 190/376] VERSION: Disable GIT_SNAPSHOT for the 4.11.0rc4 release. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ae98c26560f..792dd684a3c 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=4 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 4f2bbe2ed1d8d90c4c3311a8b77e1f695e66bea4 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 10 Sep 2019 13:19:03 +0200 Subject: [PATCH 191/376] VERSION: Bump version up to 4.11.0rc5... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 792dd684a3c..e3cbecc1d16 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=4 +SAMBA_VERSION_RC_RELEASE=5 ######################################################## # To mark SVN snapshots this should be set to 'yes' # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=4 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From e0886709582a12b37cec4299172570169f986056 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 17 Sep 2019 10:00:54 +0200 Subject: [PATCH 192/376] WHATSNEW: Add release notes for Samba 4.11.0. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 74d1de4c021..d573bb65819 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,12 +1,11 @@ -Release Announcements -===================== + ============================== + Release Notes for Samba 4.11.0 + September 17, 2019 + ============================== -This is the fourth release candidate of Samba 4.11. This is *not* -intended for production environments and is designed for testing -purposes only. Please report any defects via the Samba bug reporting -system at https://bugzilla.samba.org/. -Samba 4.11 will be the next version of the Samba suite. +This is the first stable release of the Samba 4.11 release series. +Please read the release notes carefully before upgrading. UPGRADING @@ -368,6 +367,10 @@ smb.conf changes encrypt passwords Deprecated +CHANGES SINCE 4.11.0rc4 +======================= + + CHANGES SINCE 4.11.0rc3 ======================= -- 2.17.1 From d60cf580825819f11de9e50ec4c4ce591d695ad9 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 17 Sep 2019 10:02:02 +0200 Subject: [PATCH 193/376] VERSION: Bump version up to 4.11.0... and disable GIT_SNAPSHOT for the 4.11.0 release. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index e3cbecc1d16..29a4ca4e959 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=5 +SAMBA_VERSION_RC_RELEASE= ######################################################## # To mark SVN snapshots this should be set to 'yes' # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=5 # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 872e03c2dc859759fe17228068701865023b16b5 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 17 Sep 2019 10:03:08 +0200 Subject: [PATCH 194/376] VERSION: Bump version up to 4.11.1... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 29a4ca4e959..137edf08bba 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=0 +SAMBA_VERSION_RELEASE=1 ######################################################## # If a official release has a serious bug # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From a0342e92f3a25fbf15ab0f3ad3f05e597726be81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Aug 2019 09:54:06 -0700 Subject: [PATCH 195/376] s3: libsmbclient: Ensure SMBC_readdir_ctx() also updates the readdirplus pointers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we are returning file entries, we have a duplicate list in dirplus. Update dirplus_next also so readdir and readdirplus are kept in sync. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme (cherry picked from commit 4bca8e097f5a909c628daa4dbfa932ddc1725ebc) --- source3/libsmb/libsmb_dir.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 886aa626509..a3ec9a8ff71 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1174,6 +1174,17 @@ SMBC_readdir_ctx(SMBCCTX *context, dir->dir_next = dir->dir_next->next; + /* + * If we are returning file entries, we + * have a duplicate list in dirplus. + * + * Update dirplus_next also so readdir and + * readdirplus are kept in sync. + */ + if (dir->dirplus_list != NULL) { + dir->dirplus_next = dir->dirplus_next->next; + } + TALLOC_FREE(frame); return dirp; } -- 2.17.1 From 0fbd2c08b548bd2588de960a5475ed5fc2de9bf7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Aug 2019 10:02:47 -0700 Subject: [PATCH 196/376] s3: libsmbclient: Ensure SMBC_readdirplus_ctx() also updates the readdir pointers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we are returning file entries, we have a duplicate list in dir_list. Update dir_next also so readdir and readdirplus are kept in sync. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme (cherry picked from commit 3d82b7d11cd7b78adc6b3642e64e3a8f251de869) --- source3/libsmb/libsmb_dir.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index a3ec9a8ff71..2f2117e8131 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1231,6 +1231,17 @@ SMBC_readdirplus_ctx(SMBCCTX *context, } dir->dirplus_next = dir->dirplus_next->next; + /* + * If we are returning file entries, we + * have a duplicate list in dir_list + * + * Update dir_next also so readdir and + * readdirplus are kept in sync. + */ + if (dir->dir_list) { + dir->dir_next = dir->dir_next->next; + } + TALLOC_FREE(frame); return smb_finfo; } -- 2.17.1 From a70eee31213189d9cf0e4b40d14e2c301ef4f2c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Aug 2019 10:07:32 -0700 Subject: [PATCH 197/376] s3: libsmbclient: Ensure SMBC_getdents_ctx() also updates the readdirplus pointers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we are returning file entries, we have a duplicate list in dirplus. Update dirplus_next also so readdir and readdirplus are kept in sync. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme (cherry picked from commit 754cec7756b2ddb1cfcc3984265f01cb366beb76) --- source3/libsmb/libsmb_dir.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 2f2117e8131..4447806c108 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1358,6 +1358,17 @@ SMBC_getdents_ctx(SMBCCTX *context, } dir->dir_next = dirlist = dirlist -> next; + + /* + * If we are returning file entries, we + * have a duplicate list in dirplus. + * + * Update dirplus_next also so readdir and + * readdirplus are kept in sync. + */ + if (dir->dirplus_list != NULL) { + dir->dirplus_next = dir->dirplus_next->next; + } } TALLOC_FREE(frame); -- 2.17.1 From 411eb45f2c9b9019d8a54c3c7092a3c0fc515e15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Aug 2019 10:18:28 -0700 Subject: [PATCH 198/376] s3: libsmbclient: Fix smbc_lseekdir() to work with smbc_readdirplus(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If returning files the dir_list and the dirplus_list have exactly the same entries, we just need to keep the next pointers in sync on seek. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme (cherry picked from commit 0d9b1645499ce12a79a137d3482434aa5d2eb47c) --- source3/libsmb/libsmb_dir.c | 69 +++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 4447806c108..df606c4adfe 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1672,35 +1672,43 @@ SMBC_telldir_ctx(SMBCCTX *context, /* * A routine to run down the list and see if the entry is OK + * Modifies the dir list and the dirplus list (if it exists) + * to point at the correct next entry on success. */ -static struct smbc_dir_list * -check_dir_ent(struct smbc_dir_list *list, - struct smbc_dirent *dirent) +static bool update_dir_ents(SMBCFILE *dir, struct smbc_dirent *dirent) { + struct smbc_dir_list *tmp_dir = dir->dir_list; + struct smbc_dirplus_list *tmp_dirplus = dir->dirplus_list; - /* Run down the list looking for what we want */ - - if (dirent) { - - struct smbc_dir_list *tmp = list; - - while (tmp) { - - if (tmp->dirent == dirent) - return tmp; - - tmp = tmp->next; + /* + * Run down the list looking for what we want. + * If we're enumerating files both dir_list + * and dirplus_list contain the same entry + * list, as they were seeded from the same + * cli_list callback. + * + * If we're enumerating servers then + * dirplus_list will be NULL, so don't + * update in that case. + */ + while (tmp_dir != NULL) { + if (tmp_dir->dirent == dirent) { + dir->dir_next = tmp_dir; + if (tmp_dirplus != NULL) { + dir->dirplus_next = tmp_dirplus; + } + return true; + } + tmp_dir = tmp_dir->next; + if (tmp_dirplus != NULL) { + tmp_dirplus = tmp_dirplus->next; } - } - - return NULL; /* Not found, or an error */ - + return false; } - /* * Routine to seek on a directory */ @@ -1712,8 +1720,8 @@ SMBC_lseekdir_ctx(SMBCCTX *context, { long int l_offset = offset; /* Handle problems of size */ struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; - struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; TALLOC_CTX *frame = talloc_stackframe(); + bool ok; if (!context || !context->internal->initialized) { @@ -1736,6 +1744,10 @@ SMBC_lseekdir_ctx(SMBCCTX *context, if (dirent == NULL) { /* Seek to the begining of the list */ dir->dir_next = dir->dir_list; + + /* Do the same for dirplus. */ + dir->dirplus_next = dir->dirplus_list; + TALLOC_FREE(frame); return 0; @@ -1743,21 +1755,26 @@ SMBC_lseekdir_ctx(SMBCCTX *context, if (offset == -1) { /* Seek to the end of the list */ dir->dir_next = NULL; + + /* Do the same for dirplus. */ + dir->dirplus_next = NULL; + TALLOC_FREE(frame); return 0; } - /* Now, run down the list and make sure that the entry is OK */ - /* This may need to be changed if we change the format of the list */ + /* + * Run down the list and make sure that the entry is OK. + * Update the position of both dir and dirplus lists. + */ - if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) { + ok = update_dir_ents(dir, dirent); + if (!ok) { errno = EINVAL; /* Bad entry */ TALLOC_FREE(frame); return -1; } - dir->dir_next = list_ent; - TALLOC_FREE(frame); return 0; } -- 2.17.1 From d702f66290159d72c8f3c5d08ec9e9f23772611f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Aug 2019 11:22:35 -0700 Subject: [PATCH 199/376] s3/4: libsmbclient test. Test using smbc_telldir/smbc_lseekdir with smbc_readdir/smbc_readdirplus/smbc_getdents. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure that for file access you can mix any of these three access methods for directory entries and the returned names/structs stay in sync across telldir/seekdir changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Sep 3 17:31:29 UTC 2019 on sn-devel-184 (cherry picked from commit 3355601fe8541994cc41f5ed800aab9b6a2294f4) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Sep 18 13:51:56 UTC 2019 on sn-devel-184 --- source3/selftest/tests.py | 3 +- source4/torture/libsmbclient/libsmbclient.c | 340 ++++++++++++++++++++ 2 files changed, 342 insertions(+), 1 deletion(-) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 20f2eea7661..5b5a1978988 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -495,7 +495,8 @@ nbt = ["nbt.dgram"] libsmbclient = ["libsmbclient.version", "libsmbclient.initialize", "libsmbclient.configuration", "libsmbclient.setConfiguration", "libsmbclient.options", "libsmbclient.opendir", - "libsmbclient.list_shares", "libsmbclient.readdirplus"] + "libsmbclient.list_shares", "libsmbclient.readdirplus", + "libsmbclient.readdirplus_seek"] vfs = [ "vfs.fruit", diff --git a/source4/torture/libsmbclient/libsmbclient.c b/source4/torture/libsmbclient/libsmbclient.c index f9154e8a19c..b74d87aabed 100644 --- a/source4/torture/libsmbclient/libsmbclient.c +++ b/source4/torture/libsmbclient/libsmbclient.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "system/dir.h" #include "torture/smbtorture.h" #include "auth/credentials/credentials.h" #include "lib/cmdline/popt_common.h" @@ -375,6 +376,343 @@ static bool torture_libsmbclient_readdirplus(struct torture_context *tctx) return true; } +static bool torture_libsmbclient_readdirplus_seek(struct torture_context *tctx) +{ + SMBCCTX *ctx; + int ret = -1; + int dhandle = -1; + int fhandle = -1; + const char *dname = NULL; + const char *full_filename[100] = {0}; + const char *filename[100] = {0}; + const struct libsmb_file_info *direntries[102] = {0}; + unsigned int i = 0; + const char *smburl = torture_setting_string(tctx, "smburl", NULL); + bool success = false; + off_t telldir_50 = (off_t)-1; + off_t telldir_20 = (off_t)-1; + size_t getdentries_size = 0; + struct smbc_dirent *getdentries = NULL; + struct smbc_dirent *dirent_20 = NULL; + const struct libsmb_file_info *direntries_20 = NULL; + + if (smburl == NULL) { + torture_fail(tctx, + "option --option=torture:smburl=" + "smb://user:password@server/share missing\n"); + } + + DEBUG(0,("torture_libsmbclient_readdirplus_seek start\n")); + + torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), ""); + smbc_set_context(ctx); + + dname = talloc_asprintf(tctx, + "%s/rd_seek", + smburl); + if (dname == NULL) { + torture_fail_goto(tctx, + done, + "talloc fail\n"); + } + + /* Ensure the files don't exist. */ + for (i = 0; i < 100; i++) { + filename[i] = talloc_asprintf(tctx, + "test_readdirplus_%u.txt", + i); + if (filename[i] == NULL) { + torture_fail_goto(tctx, + done, + "talloc fail\n"); + } + full_filename[i] = talloc_asprintf(tctx, + "%s/%s", + dname, + filename[i]); + if (full_filename[i] == NULL) { + torture_fail_goto(tctx, + done, + "talloc fail\n"); + } + (void)smbc_unlink(full_filename[i]); + } + /* Ensure the directory doesn't exist. */ + (void)smbc_rmdir(dname); + + /* Create containing directory. */ + ret = smbc_mkdir(dname, 0777); + if (ret != 0) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "failed to create directory '%s': %s", + dname, + strerror(errno))); + } + + DEBUG(0,("torture_libsmbclient_readdirplus_seek create\n")); + + /* Create them. */ + for (i = 0; i < 100; i++) { + fhandle = smbc_creat(full_filename[i], 0666); + if (fhandle < 0) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "failed to create file '%s': %s", + full_filename[i], + strerror(errno))); + } + ret = smbc_close(fhandle); + torture_assert_int_equal_goto(tctx, + ret, + 0, + success, + done, + talloc_asprintf(tctx, + "failed to close handle for '%s'", + full_filename[i])); + } + + DEBUG(0,("torture_libsmbclient_readdirplus_seek enum\n")); + + /* Now enumerate the directory. */ + dhandle = smbc_opendir(dname); + if (dhandle < 0) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "failed to obtain " + "directory handle for '%s' : %s", + dname, + strerror(errno))); + } + + /* Read all the files. 100 we created plus . and .. */ + for (i = 0; i < 102; i++) { + bool found = false; + unsigned int j; + + direntries[i] = smbc_readdirplus(dhandle); + if (direntries[i] == NULL) { + break; + } + + /* Store at offset 50. */ + if (i == 50) { + telldir_50 = smbc_telldir(dhandle); + if (telldir_50 == (off_t)-1) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "telldir failed file %s\n", + direntries[i]->name)); + } + } + + if (ISDOT(direntries[i]->name)) { + continue; + } + if (ISDOTDOT(direntries[i]->name)) { + continue; + } + + /* Ensure all our files exist. */ + for (j = 0; j < 100; j++) { + if (strcmp(direntries[i]->name, + filename[j]) == 0) { + found = true; + } + } + if (!found) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "failed to find file %s\n", + direntries[i]->name)); + } + } + + /* + * We're seeking on in-memory lists here, so + * whilst the handle is open we really should + * get the same files back in the same order. + */ + + ret = smbc_lseekdir(dhandle, telldir_50); + torture_assert_int_equal_goto(tctx, + ret, + 0, + success, + done, + talloc_asprintf(tctx, + "failed to seek (50) directory handle for '%s'", + dname)); + + DEBUG(0,("torture_libsmbclient_readdirplus_seek seek\n")); + + for (i = 51; i < 102; i++) { + const struct libsmb_file_info *entry = + smbc_readdirplus(dhandle); + if (entry != direntries[i]) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "after seek - failed to find " + "file %s - got %s\n", + direntries[i]->name, + entry->name)); + } + } + + /* Seek back to the start. */ + ret = smbc_lseekdir(dhandle, 0); + torture_assert_int_equal_goto(tctx, + ret, + 0, + success, + done, + talloc_asprintf(tctx, + "failed to seek directory handle to start for '%s'", + dname)); + + /* + * Mix getdents/readdir/readdirplus with lseek to ensure + * we get the same result. + */ + + /* Allocate the space for 20 entries. + * Tricky as we need to allocate 20 struct smbc_dirent's + space + * for the name lengths. + */ + getdentries_size = 20 * (sizeof(struct smbc_dirent) + + strlen("test_readdirplus_1000.txt") + 1); + + getdentries = (struct smbc_dirent *)talloc_array_size(tctx, + getdentries_size, + 1); + + ret = smbc_getdents(dhandle, getdentries, getdentries_size); + torture_assert_goto(tctx, + (ret != -1), + success, + done, + talloc_asprintf(tctx, + "smbd_getdents(1) for '%s' failed\n", + dname)); + + telldir_20 = smbc_telldir(dhandle); + if (telldir_20 == (off_t)-1) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "telldir (20) failed\n")); + } + /* Read another 20. */ + ret = smbc_getdents(dhandle, getdentries, getdentries_size); + torture_assert_goto(tctx, + (ret != -1), + success, + done, + talloc_asprintf(tctx, + "smbd_getdents(2) for '%s' failed\n", + dname)); + + /* Seek back to 20. */ + ret = smbc_lseekdir(dhandle, telldir_20); + torture_assert_int_equal_goto(tctx, + ret, + 0, + success, + done, + talloc_asprintf(tctx, + "failed to seek (20) directory handle for '%s'", + dname)); + + /* Read with readdir. */ + dirent_20 = smbc_readdir(dhandle); + if (dirent_20 == NULL) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "smbc_readdir (20) failed\n")); + } + + /* Ensure the getdents and readdir names are the same. */ + ret = strcmp(dirent_20->name, getdentries[0].name); + if (ret != 0) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "after seek (20) readdir name missmatch " + "file %s - got %s\n", + dirent_20->name, + getdentries[0].name)); + } + + /* Seek back to 20. */ + ret = smbc_lseekdir(dhandle, telldir_20); + torture_assert_int_equal_goto(tctx, + ret, + 0, + success, + done, + talloc_asprintf(tctx, + "failed to seek (20) directory handle for '%s'", + dname)); + /* Read with readdirplus. */ + direntries_20 = smbc_readdirplus(dhandle); + if (direntries_20 == NULL) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "smbc_readdirplus (20) failed\n")); + } + + /* Ensure the readdirplus and readdir names are the same. */ + ret = strcmp(dirent_20->name, direntries_20->name); + if (ret != 0) { + torture_fail_goto(tctx, + done, + talloc_asprintf(tctx, + "after seek (20) readdirplus name missmatch " + "file %s - got %s\n", + dirent_20->name, + direntries_20->name)); + } + + ret = smbc_closedir(dhandle); + torture_assert_int_equal(tctx, + ret, + 0, + talloc_asprintf(tctx, + "failed to close directory handle for '%s'", + dname)); + + dhandle = -1; + success = true; + + done: + + /* Clean up. */ + if (dhandle != -1) { + smbc_closedir(dhandle); + } + for (i = 0; i < 100; i++) { + if (full_filename[i] != NULL) { + smbc_unlink(full_filename[i]); + } + } + if (dname != NULL) { + smbc_rmdir(dname); + } + + smbc_free_context(ctx, 1); + + return success; +} + bool torture_libsmbclient_configuration(struct torture_context *tctx) { SMBCCTX *ctx; @@ -635,6 +973,8 @@ NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx) torture_suite_add_simple_test(suite, "list_shares", torture_libsmbclient_list_shares); torture_suite_add_simple_test(suite, "readdirplus", torture_libsmbclient_readdirplus); + torture_suite_add_simple_test(suite, "readdirplus_seek", + torture_libsmbclient_readdirplus_seek); suite->description = talloc_strdup(suite, "libsmbclient interface tests"); -- 2.17.1 From 4d41dc32653bd1ae7d87dcd5779c3586ae6561d3 Mon Sep 17 00:00:00 2001 From: Bryan Mason Date: Mon, 16 Sep 2019 12:35:06 -0700 Subject: [PATCH 200/376] s3:client:Use DEVICE_URI, instead of argv[0],for Device URI CUPS sanitizes argv[0] by removing username/password, so use DEVICE_URI environment variable first. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14128 Signed-off-by: Bryan Mason Reviewed-by: Alexander Bokovoy Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Wed Sep 18 12:31:11 UTC 2019 on sn-devel-184 (cherry picked from commit d65b17c3f7f9959ed95b03cc09e020d7387b7931) --- source3/client/smbspool.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c index ad988eb0df9..36f7f67ca94 100644 --- a/source3/client/smbspool.c +++ b/source3/client/smbspool.c @@ -256,13 +256,15 @@ main(int argc, /* I - Number of command-line arguments */ /* * Find the URI ... - */ - if (dev_uri == NULL) { - env = getenv("DEVICE_URI"); - if (env != NULL && env[0] != '\0') { - dev_uri = env; - } - } + * + * The URI in argv[0] is sanitized to remove username/password, so + * use DEVICE_URI if available. Otherwise keep the URI already + * discovered in argv. + */ + env = getenv("DEVICE_URI"); + if (env != NULL && env[0] != '\0') { + dev_uri = env; + } if (dev_uri == NULL) { fprintf(stderr, -- 2.17.1 From 361f4f5d24721d54558144a5905657d5cc7281a3 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 13 Aug 2019 21:42:15 +1000 Subject: [PATCH 201/376] ctdb-tools: Stop deleted nodes from influencing ctdb nodestatus exit code Deleted nodes should simply be ignored. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14129 RN: Stop deleted nodes from influencing ctdb nodestatus exit code Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 32b5ceb31936ec5447362236c1809db003561d29) --- ctdb/tools/ctdb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c index 2cc72eedc76..6a15b61ccd1 100644 --- a/ctdb/tools/ctdb.c +++ b/ctdb/tools/ctdb.c @@ -5611,7 +5611,13 @@ static int control_nodestatus(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb, ret = 0; for (i=0; inum; i++) { - ret |= nodemap->node[i].flags; + uint32_t flags = nodemap->node[i].flags; + + if ((flags & NODE_FLAGS_DELETED) != 0) { + continue; + } + + ret |= flags; } return ret; -- 2.17.1 From d42c7ffa6cbd90d0e777e39b12eda5c69e186a2f Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 18 Sep 2019 03:15:47 +0000 Subject: [PATCH 202/376] pod2man is no longer needed Since e24e344d0da58013fd5fa404529fe1d25ef403bf. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14131 Signed-off-by: Mathieu Parent Reviewed-by: Martin Schwenke Reviewed-by: Andrew Bartlett (cherry picked from commit 8df123e7f7cb591f6673ccffefffc30b946f1a5b) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Fri Sep 20 21:13:55 UTC 2019 on sn-devel-184 --- pidl/wscript | 1 - 1 file changed, 1 deletion(-) diff --git a/pidl/wscript b/pidl/wscript index 01b71bd8b27..d1b8278990a 100644 --- a/pidl/wscript +++ b/pidl/wscript @@ -34,7 +34,6 @@ def configure(conf): # yapp is used for building the parser conf.find_program('yapp', var='YAPP') - conf.find_program('pod2man', var='POD2MAN') def build(bld): -- 2.17.1 From 18963e909d75785b27ea2fd0323fa8514b3e3198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Sat, 21 Sep 2019 13:24:59 +0200 Subject: [PATCH 203/376] classicupgrade: fix a a bytes-like object is required, not 'str' error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=14136 Signed-off-by: Bjoern Jacke Reviewed-by: Björn Baumbach Autobuild-User(master): Björn Jacke Autobuild-Date(master): Mon Sep 23 12:58:20 UTC 2019 on sn-devel-184 (cherry picked from commit 465e518d6cc200eefa38643e720ce64e53abac2e) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Tue Sep 24 18:30:08 UTC 2019 on sn-devel-184 --- python/samba/upgrade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/upgrade.py b/python/samba/upgrade.py index 12555b7994e..8511bed2868 100644 --- a/python/samba/upgrade.py +++ b/python/samba/upgrade.py @@ -474,7 +474,7 @@ def upgrade_from_samba3(samba3, logger, targetdir, session_info=None, ldappass = secrets_db.get_ldap_bind_pw(ldapuser) if ldappass is None: raise ProvisioningError("ldapsam passdb backend detected but no LDAP Bind PW found in secrets.tdb for user %s. Please point this tool at the secrets.tdb that was used by the previous installation.") - ldappass = ldappass.strip('\x00') + ldappass = ldappass.decode('utf-8').strip('\x00') ldap = True else: ldapuser = None -- 2.17.1 From fa63860f7b1621e507c1950872444d366891384a Mon Sep 17 00:00:00 2001 From: Noel Power Date: Thu, 8 Aug 2019 15:06:28 +0100 Subject: [PATCH 204/376] s3/libads: clang: Fix Value stored to 'canon_princ' is never read Fixes: source3/libads/kerberos.c:192:2: warning: Value stored to 'canon_princ' is never read <--[clang] canon_princ = me; ^ ~~ 1 warning generated. Signed-off-by: Noel Power Reviewed-by: Gary Lockyer (cherry picked from commit 52d20087f620704549f5a5cdcbec79cb08a36290) --- source3/libads/kerberos.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 721c3c2a929..9fbe7dd0f07 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -189,9 +189,10 @@ int kerberos_kinit_password_ext(const char *principal, goto out; } - canon_princ = me; #ifndef SAMBA4_USES_HEIMDAL /* MIT */ canon_princ = my_creds.client; +#else + canon_princ = me; #endif /* MIT */ if ((code = krb5_cc_initialize(ctx, cc, canon_princ))) { -- 2.17.1 From ed3ac77dc22572132667df2f2ba717cc16a8daa7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 13:58:46 +0200 Subject: [PATCH 205/376] nsswitch: add logging to wbc_auth_error_to_pam_error() for non auth errors Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit acbf922fc2963a42d6cbe652bb32eee231020958) --- nsswitch/pam_winbind.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nsswitch/pam_winbind.c b/nsswitch/pam_winbind.c index 7841377fdd6..3ad70d3c4cd 100644 --- a/nsswitch/pam_winbind.c +++ b/nsswitch/pam_winbind.c @@ -862,6 +862,10 @@ static int wbc_auth_error_to_pam_error(struct pwb_context *ctx, } ret = wbc_error_to_pam_error(status); + _pam_log(ctx, LOG_ERR, + "request %s failed: %s, PAM error: %s (%d)!", + fn, wbcErrorString(status), + _pam_error_code_str(ret), ret); return pam_winbind_request_log(ctx, ret, username, fn); } -- 2.17.1 From 2ba8997d006eb6120ac3cf1917ba2b0e3b1a3d86 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2019 08:05:09 +0200 Subject: [PATCH 206/376] s4:auth: use the correct client realm in gensec_gssapi_update_internal() The function gensec_gssapi_client_creds() may call kinit and gets a TGT for the user. The principal provided by the user may not be canonicalized. The user may use 'given.last@example.com' but that may be mapped to glast@AD.EXAMPLE.PRIVATE in the background. It means we should use client_realm = AD.EXAMPLE.PRIVATE instead of client_realm = EXAMPLE.COM BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit db8fd3d6a315b140ebd6ccd0dcdfdcf27cd1bb38) --- source4/auth/gensec/gensec_gssapi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 4577c91c93a..045a0225741 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -437,8 +437,6 @@ static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_sec const char *target_principal = gensec_get_target_principal(gensec_security); const char *hostname = gensec_get_target_hostname(gensec_security); const char *service = gensec_get_target_service(gensec_security); - const char *client_realm = cli_credentials_get_realm(cli_creds); - const char *server_realm = NULL; gss_OID gss_oid_p = NULL; OM_uint32 time_req = 0; OM_uint32 time_rec = 0; @@ -457,6 +455,7 @@ static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_sec switch (gensec_security->gensec_role) { case GENSEC_CLIENT: { + const char *client_realm = NULL; #ifdef SAMBA4_USES_HEIMDAL struct gsskrb5_send_to_kdc send_to_kdc; krb5_error_code ret; @@ -532,6 +531,7 @@ static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_sec * transitive forest trusts, would have to do the * fallback ourself. */ + client_realm = cli_credentials_get_realm(cli_creds); #ifndef SAMBA4_USES_HEIMDAL if (gensec_gssapi_state->server_name == NULL) { nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, @@ -575,6 +575,8 @@ static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_sec } #endif /* !SAMBA4_USES_HEIMDAL */ if (gensec_gssapi_state->server_name == NULL) { + const char *server_realm = NULL; + server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state, hostname, client_realm); -- 2.17.1 From f5ea5a5e2a5479b993cea335b73194b1c4cc6e76 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2019 17:14:11 +0200 Subject: [PATCH 207/376] s3:libads: let kerberos_kinit_password_ext() return the canonicalized principal/realm BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit bc473e5cf088a137395842540ed8eb748373a236) --- source3/libads/authdata.c | 1 + source3/libads/kerberos.c | 46 ++++++++++++++++++++++---- source3/libads/kerberos_proto.h | 5 ++- source3/libads/kerberos_util.c | 3 +- source3/utils/net_ads.c | 3 ++ source3/winbindd/winbindd_cred_cache.c | 6 ++++ 6 files changed, 56 insertions(+), 8 deletions(-) diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 86a1be71bf9..6e6d5b397ff 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -170,6 +170,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, request_pac, add_netbios_addr, renewable_time, + NULL, NULL, NULL, &status); if (ret) { DEBUG(1,("kinit failed for '%s' with: %s (%d)\n", diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 9fbe7dd0f07..3e09d70268f 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -106,7 +106,7 @@ kerb_prompter(krb5_context ctx, void *data, place in default cache location. remus@snapserver.com */ -int kerberos_kinit_password_ext(const char *principal, +int kerberos_kinit_password_ext(const char *given_principal, const char *password, int time_offset, time_t *expire_time, @@ -115,8 +115,12 @@ int kerberos_kinit_password_ext(const char *principal, bool request_pac, bool add_netbios_addr, time_t renewable_time, + TALLOC_CTX *mem_ctx, + char **_canon_principal, + char **_canon_realm, NTSTATUS *ntstatus) { + TALLOC_CTX *frame = talloc_stackframe(); krb5_context ctx = NULL; krb5_error_code code = 0; krb5_ccache cc = NULL; @@ -125,6 +129,8 @@ int kerberos_kinit_password_ext(const char *principal, krb5_creds my_creds; krb5_get_init_creds_opt *opt = NULL; smb_krb5_addresses *addr = NULL; + char *canon_principal = NULL; + char *canon_realm = NULL; ZERO_STRUCT(my_creds); @@ -132,6 +138,7 @@ int kerberos_kinit_password_ext(const char *principal, if (code != 0) { DBG_ERR("kerberos init context failed (%s)\n", error_message(code)); + TALLOC_FREE(frame); return code; } @@ -139,16 +146,16 @@ int kerberos_kinit_password_ext(const char *principal, krb5_set_real_time(ctx, time(NULL) + time_offset, 0); } - DEBUG(10,("kerberos_kinit_password: as %s using [%s] as ccache and config [%s]\n", - principal, - cache_name ? cache_name: krb5_cc_default_name(ctx), - getenv("KRB5_CONFIG"))); + DBG_DEBUG("as %s using [%s] as ccache and config [%s]\n", + given_principal, + cache_name ? cache_name: krb5_cc_default_name(ctx), + getenv("KRB5_CONFIG")); if ((code = krb5_cc_resolve(ctx, cache_name ? cache_name : krb5_cc_default_name(ctx), &cc))) { goto out; } - if ((code = smb_krb5_parse_name(ctx, principal, &me))) { + if ((code = smb_krb5_parse_name(ctx, given_principal, &me))) { goto out; } @@ -195,6 +202,22 @@ int kerberos_kinit_password_ext(const char *principal, canon_princ = me; #endif /* MIT */ + code = smb_krb5_unparse_name(frame, + ctx, + canon_princ, + &canon_principal); + if (code != 0) { + goto out; + } + + DBG_DEBUG("%s mapped to %s\n", given_principal, canon_principal); + + canon_realm = smb_krb5_principal_get_realm(frame, ctx, canon_princ); + if (canon_realm == NULL) { + code = ENOMEM; + goto out; + } + if ((code = krb5_cc_initialize(ctx, cc, canon_princ))) { goto out; } @@ -210,6 +233,13 @@ int kerberos_kinit_password_ext(const char *principal, if (renew_till_time) { *renew_till_time = (time_t) my_creds.times.renew_till; } + + if (_canon_principal != NULL) { + *_canon_principal = talloc_move(mem_ctx, &canon_principal); + } + if (_canon_realm != NULL) { + *_canon_realm = talloc_move(mem_ctx, &canon_realm); + } out: if (ntstatus) { /* fast path */ @@ -239,6 +269,7 @@ int kerberos_kinit_password_ext(const char *principal, if (ctx) { krb5_free_context(ctx); } + TALLOC_FREE(frame); return code; } @@ -328,6 +359,9 @@ int kerberos_kinit_password(const char *principal, False, False, 0, + NULL, + NULL, + NULL, NULL); } diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h index f92cabd757e..433bce9e0ec 100644 --- a/source3/libads/kerberos_proto.h +++ b/source3/libads/kerberos_proto.h @@ -45,7 +45,7 @@ struct PAC_DATA_CTR { /* The following definitions come from libads/kerberos.c */ -int kerberos_kinit_password_ext(const char *principal, +int kerberos_kinit_password_ext(const char *given_principal, const char *password, int time_offset, time_t *expire_time, @@ -54,6 +54,9 @@ int kerberos_kinit_password_ext(const char *principal, bool request_pac, bool add_netbios_addr, time_t renewable_time, + TALLOC_CTX *mem_ctx, + char **_canon_principal, + char **_canon_realm, NTSTATUS *ntstatus); int ads_kdestroy(const char *cc_name); diff --git a/source3/libads/kerberos_util.c b/source3/libads/kerberos_util.c index 68c0f302239..bfe53820aff 100644 --- a/source3/libads/kerberos_util.c +++ b/source3/libads/kerberos_util.c @@ -66,7 +66,8 @@ int ads_kinit_password(ADS_STRUCT *ads) ads->auth.time_offset, &ads->auth.tgt_expire, NULL, ads->auth.ccache_name, false, false, - ads->auth.renewable, NULL); + ads->auth.renewable, + NULL, NULL, NULL, NULL); if (ret) { DEBUG(0,("kerberos_kinit_password %s failed: %s\n", diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 6b4cd3591b0..4a0f59a1e80 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -3353,6 +3353,9 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char ** true, true, 2592000, /* one month */ + NULL, + NULL, + NULL, &status); if (ret) { d_printf(_("failed to kinit password: %s\n"), diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index 85ad426446a..5baecf906b9 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -146,6 +146,9 @@ rekinit: False, /* no PAC required anymore */ True, WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL, + NULL, + NULL, NULL); gain_root_privilege(); @@ -343,6 +346,9 @@ static void krb5_ticket_gain_handler(struct tevent_context *event_ctx, False, /* no PAC required anymore */ True, WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL, + NULL, + NULL, NULL); gain_root_privilege(); -- 2.17.1 From 7ed225544705ad3b6f66122fe335bb8e47569d95 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2019 10:08:10 +0200 Subject: [PATCH 208/376] s3:libsmb: avoid wrong debug message in cli_session_creds_prepare_krb5() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 361fb0efabfb189526c851107eee49161da2293c) --- source3/libsmb/cliconnect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 3a116b6c7e6..7b6adfd6975 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -375,6 +375,8 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, /* * Ignore the error and hope that NTLM will work */ + TALLOC_FREE(frame); + return NT_STATUS_OK; } DBG_DEBUG("Successfully authenticated as %s to access %s using " -- 2.17.1 From 5628c4ffd328634014b5cc97f2717ff829bab8e3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2019 08:49:13 +0200 Subject: [PATCH 209/376] s3:libsmb: let cli_session_creds_prepare_krb5() update the canonicalized principal to cli_credentials BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 6ed18c12c57efb2a010e0ce5196c51b48e57a4b9) --- source3/libsmb/cliconnect.c | 39 ++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 7b6adfd6975..94cec062881 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -229,6 +229,8 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, const char *user_account = NULL; const char *user_domain = NULL; const char *pass = NULL; + char *canon_principal = NULL; + char *canon_realm = NULL; const char *target_hostname = NULL; const DATA_BLOB *server_blob = NULL; bool got_kerberos_mechanism = false; @@ -237,6 +239,7 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, bool need_kinit = false; bool auth_requested = true; int ret; + bool ok; target_hostname = smbXcli_conn_remote_name(cli->conn); server_blob = smbXcli_conn_server_gss_blob(cli->conn); @@ -245,7 +248,6 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, if (server_blob != NULL && server_blob->length != 0) { char *OIDs[ASN1_MAX_OIDS] = { NULL, }; size_t i; - bool ok; /* * The server sent us the first part of the SPNEGO exchange in the @@ -354,9 +356,19 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, * only if required! */ setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1); - ret = kerberos_kinit_password(user_principal, pass, - 0 /* no time correction for now */, - NULL); + ret = kerberos_kinit_password_ext(user_principal, + pass, + 0, + 0, + 0, + NULL, + false, + false, + 0, + frame, + &canon_principal, + &canon_realm, + NULL); if (ret != 0) { int dbglvl = DBGLVL_NOTICE; @@ -379,9 +391,26 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, return NT_STATUS_OK; } - DBG_DEBUG("Successfully authenticated as %s to access %s using " + ok = cli_credentials_set_principal(creds, + canon_principal, + CRED_SPECIFIED); + if (!ok) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + ok = cli_credentials_set_realm(creds, + canon_realm, + CRED_SPECIFIED); + if (!ok) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using " "Kerberos\n", user_principal, + canon_principal, target_hostname); TALLOC_FREE(frame); -- 2.17.1 From 35e3f1a4054dd55e53e229fd78fe85433f577d95 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Sep 2019 16:04:30 +0200 Subject: [PATCH 210/376] s3:libads/kerberos: always use the canonicalized principal after kinit We should always use krb5_get_init_creds_opt_set_canonicalize() and krb5_get_init_creds_opt_set_win2k() for heimdal and expect the client principal to be changed. There's no reason to have a different logic between MIT and Heimdal. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 0bced73bed481a8846a6b3e68be85941914390ba) --- source3/libads/kerberos.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 3e09d70268f..559ec3b7f53 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -167,7 +167,10 @@ int kerberos_kinit_password_ext(const char *given_principal, krb5_get_init_creds_opt_set_forwardable(opt, True); /* Turn on canonicalization for lower case realm support */ -#ifndef SAMBA4_USES_HEIMDAL /* MIT */ +#ifdef SAMBA4_USES_HEIMDAL + krb5_get_init_creds_opt_set_win2k(ctx, opt, true); + krb5_get_init_creds_opt_set_canonicalize(ctx, opt, true); +#else /* MIT */ krb5_get_init_creds_opt_set_canonicalize(opt, true); #endif /* MIT */ #if 0 @@ -196,11 +199,7 @@ int kerberos_kinit_password_ext(const char *given_principal, goto out; } -#ifndef SAMBA4_USES_HEIMDAL /* MIT */ canon_princ = my_creds.client; -#else - canon_princ = me; -#endif /* MIT */ code = smb_krb5_unparse_name(frame, ctx, -- 2.17.1 From d3d951f4240c543162976e18da9e0090254d72b6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Sep 2019 16:04:30 +0200 Subject: [PATCH 211/376] krb5_wrap: smb_krb5_kinit_password_ccache() should always use the canonicalized principal We should always use krb5_get_init_creds_opt_set_canonicalize() and krb5_get_init_creds_opt_set_win2k() for heimdal and expect the client principal to be changed. There's no reason to have a different logic between MIT and Heimdal. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 5d0bf32ec0ad21d49587e3a1520ffdc8b5ae7614) --- lib/krb5_wrap/krb5_samba.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index 72889fffcf0..55c17d481f4 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -2114,14 +2114,12 @@ krb5_error_code smb_krb5_kinit_password_ccache(krb5_context ctx, return code; } -#ifndef SAMBA4_USES_HEIMDAL /* MIT */ /* * We need to store the principal as returned from the KDC to the * credentials cache. If we don't do that the KRB5 library is not * able to find the tickets it is looking for */ principal = my_creds.client; -#endif code = krb5_cc_initialize(ctx, cc, principal); if (code) { goto done; -- 2.17.1 From 5d9961e64542ff1a7d360441db62ef6af3118292 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Sep 2019 16:04:30 +0200 Subject: [PATCH 212/376] s4:auth: kinit_to_ccache() should always use the canonicalized principal We should always use krb5_get_init_creds_opt_set_canonicalize() and krb5_get_init_creds_opt_set_win2k() for heimdal and expect the client principal to be changed. There's no reason to have a different logic between MIT and Heimdal. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 162b4199493c1f179e775a325a19ae7a136c418b) --- source4/auth/kerberos/kerberos_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c index 50bf8feec96..950d91f1737 100644 --- a/source4/auth/kerberos/kerberos_util.c +++ b/source4/auth/kerberos/kerberos_util.c @@ -313,6 +313,8 @@ done: */ krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context, krb_options, true); + krb5_get_init_creds_opt_set_canonicalize(smb_krb5_context->krb5_context, + krb_options, true); #else /* MIT */ krb5_get_init_creds_opt_set_canonicalize(krb_options, true); #endif -- 2.17.1 From 2fd31d85701a4f05c306eb47791c65fd7e39d66d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Sep 2019 16:04:30 +0200 Subject: [PATCH 213/376] s3:libads: ads_krb5_chg_password() should always use the canonicalized principal We should always use krb5_get_init_creds_opt_set_canonicalize() and krb5_get_init_creds_opt_set_win2k() for heimdal and expect the client principal to be changed. There's no reason to have a different logic between MIT and Heimdal. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 303b7e59a286896888ee2473995fc50bb2b5ce5e) --- source3/libads/krb5_setpw.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index c3c9477c4cf..67bc2f4640d 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -203,6 +203,12 @@ static ADS_STATUS ads_krb5_chg_password(const char *kdc_host, krb5_get_init_creds_opt_set_renew_life(opts, 0); krb5_get_init_creds_opt_set_forwardable(opts, 0); krb5_get_init_creds_opt_set_proxiable(opts, 0); +#ifdef SAMBA4_USES_HEIMDAL + krb5_get_init_creds_opt_set_win2k(context, opts, true); + krb5_get_init_creds_opt_set_canonicalize(context, opts, true); +#else /* MIT */ + krb5_get_init_creds_opt_set_canonicalize(opts, true); +#endif /* MIT */ /* note that heimdal will fill in the local addresses if the addresses * in the creds_init_opt are all empty and then later fail with invalid -- 2.17.1 From 9de64feb1ec94ccef89931ce41ffebb18d80d921 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Sep 2019 15:52:25 +0200 Subject: [PATCH 214/376] krb5_wrap: let smb_krb5_parse_name() accept enterprise principals BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 3bdf023956e861485be70430112ed38d0a5424f7) --- lib/krb5_wrap/krb5_samba.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index 55c17d481f4..a4e73c64f00 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -701,6 +701,11 @@ krb5_error_code smb_krb5_parse_name(krb5_context context, } ret = krb5_parse_name(context, utf8_name, principal); + if (ret == KRB5_PARSE_MALFORMED) { + ret = krb5_parse_name_flags(context, utf8_name, + KRB5_PRINCIPAL_PARSE_ENTERPRISE, + principal); + } TALLOC_FREE(frame); return ret; } -- 2.17.1 From 82fb0291f1fe69143b093a4b3cb47fc36d964c22 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 Sep 2019 16:44:43 +0200 Subject: [PATCH 215/376] docs-xml: add "winbind use krb5 enterprise principals" option BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 9520652399696010c333a3ce7247809ce5337a91) --- .../winbindusekrb5enterpriseprincipals.xml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs-xml/smbdotconf/winbind/winbindusekrb5enterpriseprincipals.xml diff --git a/docs-xml/smbdotconf/winbind/winbindusekrb5enterpriseprincipals.xml b/docs-xml/smbdotconf/winbind/winbindusekrb5enterpriseprincipals.xml new file mode 100644 index 00000000000..bfc11c8636c --- /dev/null +++ b/docs-xml/smbdotconf/winbind/winbindusekrb5enterpriseprincipals.xml @@ -0,0 +1,34 @@ + + + winbindd is able to get kerberos tickets for + pam_winbind with krb5_auth or wbinfo -K/--krb5auth=. + + + winbindd (at least on a domain member) is never be able + to have a complete picture of the trust topology (which is managed by the DCs). + There might be uPNSuffixes and msDS-SPNSuffixes values, + which don't belong to any AD domain at all. + + + With no + winbindd don't even get an incomplete picture of the topology. + + + It is not really required to know about the trust topology. + We can just rely on the [K]DCs of our primary domain (e.g. PRIMARY.A.EXAMPLE.COM) + and use enterprise principals e.g. upnfromB@B.EXAMPLE.COM@PRIMARY.A.EXAMPLE.COM + and follow the WRONG_REALM referrals in order to find the correct DC. + The final principal might be userfromB@INTERNALB.EXAMPLE.PRIVATE. + + + With yes + winbindd enterprise principals will be used. + + + +no +yes + -- 2.17.1 From e8c701673a8b0378e95f501c5ccb4f3cb661460e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 19 Jul 2019 15:10:09 +0000 Subject: [PATCH 216/376] s3:winbindd: implement the "winbind use krb5 enterprise principals" logic We can use enterprise principals (e.g. upnfromB@B.EXAMPLE.COM@PRIMARY.A.EXAMPLE.COM) and delegate the routing decisions to the KDCs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit a77be15d28390c5d12202278adbe6b50200a2c1b) --- source3/winbindd/winbindd_pam.c | 57 +++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index eaf16d0dced..c5b7c09b5c1 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -419,6 +419,15 @@ struct winbindd_domain *find_auth_domain(uint8_t flags, return find_domain_from_name_noinit(domain_name); } + if (lp_winbind_use_krb5_enterprise_principals()) { + /* + * If we use enterprise principals + * we always go trough our primary domain + * and follow the WRONG_REALM replies. + */ + flags &= ~WBFLAG_PAM_CONTACT_TRUSTDOM; + } + /* we can auth against trusted domains */ if (flags & WBFLAG_PAM_CONTACT_TRUSTDOM) { domain = find_domain_from_name_noinit(domain_name); @@ -723,7 +732,20 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_PARAMETER; } - principal_s = talloc_asprintf(mem_ctx, "%s@%s", name_user, realm); + if (lp_winbind_use_krb5_enterprise_principals() && + name_namespace[0] != '\0') + { + principal_s = talloc_asprintf(mem_ctx, + "%s@%s@%s", + name_user, + name_namespace, + realm); + } else { + principal_s = talloc_asprintf(mem_ctx, + "%s@%s", + name_user, + realm); + } if (principal_s == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1290,30 +1312,16 @@ static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, /* what domain should we contact? */ - if ( IS_DC ) { - contact_domain = find_domain_from_name(name_namespace); - if (contact_domain == NULL) { - DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", - state->request->data.auth.user, name_domain, name_user, name_domain)); - result = NT_STATUS_NO_SUCH_USER; - goto done; - } - + if (lp_winbind_use_krb5_enterprise_principals()) { + contact_domain = find_auth_domain(0, name_namespace); } else { - if (is_myname(name_domain)) { - DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); - result = NT_STATUS_NO_SUCH_USER; - goto done; - } - contact_domain = find_domain_from_name(name_namespace); - if (contact_domain == NULL) { - DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", - state->request->data.auth.user, name_domain, name_user, name_domain)); - - result = NT_STATUS_NO_SUCH_USER; - goto done; - } + } + if (contact_domain == NULL) { + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request->data.auth.user, name_domain, name_user, name_namespace)); + result = NT_STATUS_NO_SUCH_USER; + goto done; } if (contact_domain->initialized && @@ -1326,7 +1334,8 @@ static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, } if (!contact_domain->active_directory) { - DEBUG(3,("krb5 auth requested but domain is not Active Directory\n")); + DEBUG(3,("krb5 auth requested but domain (%s) is not Active Directory\n", + contact_domain->name)); return NT_STATUS_INVALID_LOGON_TYPE; } try_login: -- 2.17.1 From 5583d045a259a54f3f9000e747a713fa97effe15 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 08:04:42 +0200 Subject: [PATCH 217/376] tests/pam_winbind.py: turn pypamtest.PamTestError into a failure A failure generated by the AssertionError() checks can be added to selftest/knownfail.d/*. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit cd3ffaabb568db26e0de5e83178487e5947c4f09) --- python/samba/tests/pam_winbind.py | 15 ++++++++++++--- python/samba/tests/pam_winbind_chauthtok.py | 5 ++++- python/samba/tests/pam_winbind_warn_pwd_expire.py | 5 ++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/pam_winbind.py b/python/samba/tests/pam_winbind.py index 68b05b30d7d..b05e8af6ffb 100644 --- a/python/samba/tests/pam_winbind.py +++ b/python/samba/tests/pam_winbind.py @@ -30,7 +30,10 @@ class SimplePamTests(samba.tests.TestCase): expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) - res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + try: + res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + except pypamtest.PamTestError as e: + raise AssertionError(str(e)) self.assertTrue(res is not None) @@ -42,7 +45,10 @@ class SimplePamTests(samba.tests.TestCase): expected_rc = 7 # PAM_AUTH_ERR tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) - res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + try: + res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + except pypamtest.PamTestError as e: + raise AssertionError(str(e)) self.assertTrue(res is not None) @@ -52,6 +58,9 @@ class SimplePamTests(samba.tests.TestCase): expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) - res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + try: + res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + except pypamtest.PamTestError as e: + raise AssertionError(str(e)) self.assertTrue(res is not None) diff --git a/python/samba/tests/pam_winbind_chauthtok.py b/python/samba/tests/pam_winbind_chauthtok.py index e5be3a83ce7..18c2705127a 100644 --- a/python/samba/tests/pam_winbind_chauthtok.py +++ b/python/samba/tests/pam_winbind_chauthtok.py @@ -31,6 +31,9 @@ class PamChauthtokTests(samba.tests.TestCase): expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_CHAUTHTOK, expected_rc) - res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password, newpassword, newpassword]) + try: + res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password, newpassword, newpassword]) + except pypamtest.PamTestError as e: + raise AssertionError(str(e)) self.assertTrue(res is not None) diff --git a/python/samba/tests/pam_winbind_warn_pwd_expire.py b/python/samba/tests/pam_winbind_warn_pwd_expire.py index df60bc5ace6..1af2f9befe1 100644 --- a/python/samba/tests/pam_winbind_warn_pwd_expire.py +++ b/python/samba/tests/pam_winbind_warn_pwd_expire.py @@ -31,7 +31,10 @@ class PasswordExpirePamTests(samba.tests.TestCase): expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) - res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + try: + res = pypamtest.run_pamtest(unix_username, "samba", [tc], [password]) + except pypamtest.PamTestError as e: + raise AssertionError(str(e)) self.assertTrue(res is not None) if warn_pwd_expire == 0: -- 2.17.1 From 913c79d2e06acf93b7a3fedab6b0c30a0c1272bf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Sep 2019 08:13:28 +0200 Subject: [PATCH 218/376] tests/pam_winbind.py: allow upn names to be used in USERNAME with an empty DOMAIN value BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 653e90485854d978dc522e689cd78c19dcc22a70) --- python/samba/tests/pam_winbind.py | 10 ++++++++-- python/samba/tests/pam_winbind_chauthtok.py | 5 ++++- python/samba/tests/pam_winbind_warn_pwd_expire.py | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/pam_winbind.py b/python/samba/tests/pam_winbind.py index b05e8af6ffb..708f408f768 100644 --- a/python/samba/tests/pam_winbind.py +++ b/python/samba/tests/pam_winbind.py @@ -26,7 +26,10 @@ class SimplePamTests(samba.tests.TestCase): domain = os.environ["DOMAIN"] username = os.environ["USERNAME"] password = os.environ["PASSWORD"] - unix_username = "%s/%s" % (domain, username) + if domain != "": + unix_username = "%s/%s" % (domain, username) + else: + unix_username = "%s" % username expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) @@ -41,7 +44,10 @@ class SimplePamTests(samba.tests.TestCase): domain = os.environ["DOMAIN"] username = os.environ["USERNAME"] password = "WrongPassword" - unix_username = "%s/%s" % (domain, username) + if domain != "": + unix_username = "%s/%s" % (domain, username) + else: + unix_username = "%s" % username expected_rc = 7 # PAM_AUTH_ERR tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) diff --git a/python/samba/tests/pam_winbind_chauthtok.py b/python/samba/tests/pam_winbind_chauthtok.py index 18c2705127a..c1d569b3cd0 100644 --- a/python/samba/tests/pam_winbind_chauthtok.py +++ b/python/samba/tests/pam_winbind_chauthtok.py @@ -27,7 +27,10 @@ class PamChauthtokTests(samba.tests.TestCase): username = os.environ["USERNAME"] password = os.environ["PASSWORD"] newpassword = os.environ["NEWPASSWORD"] - unix_username = "%s/%s" % (domain, username) + if domain != "": + unix_username = "%s/%s" % (domain, username) + else: + unix_username = "%s" % username expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_CHAUTHTOK, expected_rc) diff --git a/python/samba/tests/pam_winbind_warn_pwd_expire.py b/python/samba/tests/pam_winbind_warn_pwd_expire.py index 1af2f9befe1..56f5da94f98 100644 --- a/python/samba/tests/pam_winbind_warn_pwd_expire.py +++ b/python/samba/tests/pam_winbind_warn_pwd_expire.py @@ -27,7 +27,10 @@ class PasswordExpirePamTests(samba.tests.TestCase): username = os.environ["USERNAME"] password = os.environ["PASSWORD"] warn_pwd_expire = int(os.environ["WARN_PWD_EXPIRE"]) - unix_username = "%s/%s" % (domain, username) + if domain != "": + unix_username = "%s/%s" % (domain, username) + else: + unix_username = "%s" % username expected_rc = 0 # PAM_SUCCESS tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rc) -- 2.17.1 From 8aae6dd753b51bc54042c8cbc9308e08cdeef089 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 01:25:58 +0200 Subject: [PATCH 219/376] test_pam_winbind.sh: allow different pam_winbindd config options to be specified BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 3d38a8e9135bb72bc4ca079fab0eb5358942b3f1) --- python/samba/tests/test_pam_winbind.sh | 12 +++++++---- .../samba/tests/test_pam_winbind_chauthtok.sh | 4 ++-- .../tests/test_pam_winbind_warn_pwd_expire.sh | 20 +++++++++++-------- selftest/tests.py | 6 +++--- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/python/samba/tests/test_pam_winbind.sh b/python/samba/tests/test_pam_winbind.sh index 0406b108b31..755e67280fa 100755 --- a/python/samba/tests/test_pam_winbind.sh +++ b/python/samba/tests/test_pam_winbind.sh @@ -12,6 +12,10 @@ PASSWORD="$3" export PASSWORD shift 3 +PAM_OPTIONS="$1" +export PAM_OPTIONS +shift 1 + PAM_WRAPPER_PATH="$BINDIR/default/third_party/pam_wrapper" pam_winbind="$BINDIR/shared/pam_winbind.so" @@ -19,10 +23,10 @@ service_dir="$SELFTEST_TMPDIR/pam_services" service_file="$service_dir/samba" mkdir $service_dir -echo "auth required $pam_winbind debug debug_state" > $service_file -echo "account required $pam_winbind debug debug_state" >> $service_file -echo "password required $pam_winbind debug debug_state" >> $service_file -echo "session required $pam_winbind debug debug_state" >> $service_file +echo "auth required $pam_winbind debug debug_state $PAM_OPTIONS" > $service_file +echo "account required $pam_winbind debug debug_state $PAM_OPTIONS" >> $service_file +echo "password required $pam_winbind debug debug_state $PAM_OPTIONS" >> $service_file +echo "session required $pam_winbind debug debug_state $PAM_OPTIONS" >> $service_file PAM_WRAPPER="1" export PAM_WRAPPER diff --git a/python/samba/tests/test_pam_winbind_chauthtok.sh b/python/samba/tests/test_pam_winbind_chauthtok.sh index 5887699300a..48adc81859d 100755 --- a/python/samba/tests/test_pam_winbind_chauthtok.sh +++ b/python/samba/tests/test_pam_winbind_chauthtok.sh @@ -53,11 +53,11 @@ PAM_WRAPPER_DEBUGLEVEL=${PAM_WRAPPER_DEBUGLEVEL:="2"} export PAM_WRAPPER_DEBUGLEVEL case $PAM_OPTIONS in - use_authtok) + *use_authtok*) PAM_AUTHTOK="$NEWPASSWORD" export PAM_AUTHTOK ;; - try_authtok) + *try_authtok*) PAM_AUTHTOK="$NEWPASSWORD" export PAM_AUTHTOK ;; diff --git a/python/samba/tests/test_pam_winbind_warn_pwd_expire.sh b/python/samba/tests/test_pam_winbind_warn_pwd_expire.sh index 16dede44227..348d2ae8387 100755 --- a/python/samba/tests/test_pam_winbind_warn_pwd_expire.sh +++ b/python/samba/tests/test_pam_winbind_warn_pwd_expire.sh @@ -12,6 +12,10 @@ PASSWORD="$3" export PASSWORD shift 3 +PAM_OPTIONS="$1" +export PAM_OPTIONS +shift 1 + PAM_WRAPPER_PATH="$BINDIR/default/third_party/pam_wrapper" pam_winbind="$BINDIR/shared/pam_winbind.so" @@ -37,10 +41,10 @@ export PAM_WRAPPER_DEBUGLEVEL WARN_PWD_EXPIRE="50" export WARN_PWD_EXPIRE -echo "auth required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" > $service_file -echo "account required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" >> $service_file -echo "password required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" >> $service_file -echo "session required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" >> $service_file +echo "auth required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" > $service_file +echo "account required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" >> $service_file +echo "password required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" >> $service_file +echo "session required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" >> $service_file PYTHONPATH="$PYTHONPATH:$PAM_WRAPPER_PATH:$(dirname $0)" $PYTHON -m samba.subunit.run samba.tests.pam_winbind_warn_pwd_expire exit_code=$? @@ -54,10 +58,10 @@ fi WARN_PWD_EXPIRE="0" export WARN_PWD_EXPIRE -echo "auth required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" > $service_file -echo "account required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" >> $service_file -echo "password required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" >> $service_file -echo "session required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE" >> $service_file +echo "auth required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" > $service_file +echo "account required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" >> $service_file +echo "password required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" >> $service_file +echo "session required $pam_winbind debug debug_state warn_pwd_expire=$WARN_PWD_EXPIRE $PAM_OPTIONS" >> $service_file PYTHONPATH="$PYTHONPATH:$PAM_WRAPPER_PATH:$(dirname $0)" $PYTHON -m samba.subunit.run samba.tests.pam_winbind_warn_pwd_expire exit_code=$? diff --git a/selftest/tests.py b/selftest/tests.py index 1568f29b212..2d3587837a3 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -216,11 +216,11 @@ if with_pam: plantestsuite("samba.tests.pam_winbind(local)", "ad_member", [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), valgrindify(python), pam_wrapper_so_path, - "$SERVER", "$USERNAME", "$PASSWORD"]) + "$SERVER", "$USERNAME", "$PASSWORD", "''"]) plantestsuite("samba.tests.pam_winbind(domain)", "ad_member", [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), valgrindify(python), pam_wrapper_so_path, - "$DOMAIN", "$DC_USERNAME", "$DC_PASSWORD"]) + "$DOMAIN", "$DC_USERNAME", "$DC_PASSWORD", "''"]) for pam_options in ["''", "use_authtok", "try_authtok"]: plantestsuite("samba.tests.pam_winbind_chauthtok with options %s" % pam_options, "ad_member", @@ -233,7 +233,7 @@ if with_pam: plantestsuite("samba.tests.pam_winbind_warn_pwd_expire(domain)", "ad_member", [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind_warn_pwd_expire.sh"), valgrindify(python), pam_wrapper_so_path, - "$DOMAIN", "alice", "Secret007"]) + "$DOMAIN", "alice", "Secret007", "''"]) plantestsuite("samba.unittests.krb5samba", "none", -- 2.17.1 From cfee90317203e174c4553c264f47387afef7aeaa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 01:25:23 +0200 Subject: [PATCH 220/376] selftest/tests.py: prepare looping over pam_winbindd tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 72daf99fd1ffd8269fce25d69458de35e2ae32cc) --- selftest/tests.py | 58 ++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/selftest/tests.py b/selftest/tests.py index 2d3587837a3..95d027f9521 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -213,27 +213,43 @@ planpythontestsuite("none", "samba.tests.tdb_util") planpythontestsuite("none", "samba.tests.samdb_api") if with_pam: - plantestsuite("samba.tests.pam_winbind(local)", "ad_member", - [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), - valgrindify(python), pam_wrapper_so_path, - "$SERVER", "$USERNAME", "$PASSWORD", "''"]) - plantestsuite("samba.tests.pam_winbind(domain)", "ad_member", - [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), - valgrindify(python), pam_wrapper_so_path, - "$DOMAIN", "$DC_USERNAME", "$DC_PASSWORD", "''"]) - - for pam_options in ["''", "use_authtok", "try_authtok"]: - plantestsuite("samba.tests.pam_winbind_chauthtok with options %s" % pam_options, "ad_member", - [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind_chauthtok.sh"), - valgrindify(python), pam_wrapper_so_path, pam_set_items_so_path, - "$DOMAIN", "TestPamOptionsUser", "oldp@ssword0", "newp@ssword0", - pam_options, 'yes', - "$DC_SERVER", "$DC_USERNAME", "$DC_PASSWORD"]) - - plantestsuite("samba.tests.pam_winbind_warn_pwd_expire(domain)", "ad_member", - [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind_warn_pwd_expire.sh"), - valgrindify(python), pam_wrapper_so_path, - "$DOMAIN", "alice", "Secret007", "''"]) + env = "ad_member" + options = [ + { + "description": "default", + "pam_options": "", + }, + ] + for o in options: + description = o["description"] + pam_options = "'%s'" % o["pam_options"] + + plantestsuite("samba.tests.pam_winbind(local+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$SERVER", "$USERNAME", "$PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(domain+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$DOMAIN", "$DC_USERNAME", "$DC_PASSWORD", + pam_options]) + + for authtok_options in ["", "use_authtok", "try_authtok"]: + _pam_options = "'%s %s'" % (o["pam_options"], authtok_options) + _description = "%s %s" % (description, authtok_options) + plantestsuite("samba.tests.pam_winbind_chauthtok(domain+%s)" % _description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind_chauthtok.sh"), + valgrindify(python), pam_wrapper_so_path, pam_set_items_so_path, + "$DOMAIN", "TestPamOptionsUser", "oldp@ssword0", "newp@ssword0", + _pam_options, 'yes', + "$DC_SERVER", "$DC_USERNAME", "$DC_PASSWORD"]) + + plantestsuite("samba.tests.pam_winbind_warn_pwd_expire(domain+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind_warn_pwd_expire.sh"), + valgrindify(python), pam_wrapper_so_path, + "$DOMAIN", "alice", "Secret007", + pam_options]) plantestsuite("samba.unittests.krb5samba", "none", -- 2.17.1 From e7b84754510b5850891752c5fc943714f0a46a4d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 08:08:57 +0200 Subject: [PATCH 221/376] selftest/tests.py: test pam_winbind with krb5_auth BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 36e95e42ea8a7e5a4091a647215d06d2ab47fab6) --- selftest/tests.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/selftest/tests.py b/selftest/tests.py index 95d027f9521..0bcb826071c 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -215,6 +215,10 @@ planpythontestsuite("none", "samba.tests.samdb_api") if with_pam: env = "ad_member" options = [ + { + "description": "krb5", + "pam_options": "krb5_auth krb5_ccache_type=FILE", + }, { "description": "default", "pam_options": "", -- 2.17.1 From 2290dfe49bf267784d3bec491cb9b8978c3d66dc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 14:03:34 +0200 Subject: [PATCH 222/376] selftest/tests.py: test pam_winbind with a lot of username variations BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit f07b542c61f84a97c097208e10bf9375ddfa9a15) --- selftest/tests.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/selftest/tests.py b/selftest/tests.py index 0bcb826071c..e37cb9e7b96 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -233,11 +233,36 @@ if with_pam: valgrindify(python), pam_wrapper_so_path, "$SERVER", "$USERNAME", "$PASSWORD", pam_options]) - plantestsuite("samba.tests.pam_winbind(domain+%s)" % description, env, + plantestsuite("samba.tests.pam_winbind(domain1+%s)" % description, env, [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), valgrindify(python), pam_wrapper_so_path, "$DOMAIN", "$DC_USERNAME", "$DC_PASSWORD", pam_options]) + plantestsuite("samba.tests.pam_winbind(domain2+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$REALM", "$DC_USERNAME", "$DC_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(domain3+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "''", "${DC_USERNAME}@${DOMAIN}", "$DC_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(domain4+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "''", "${DC_USERNAME}@${REALM}", "$DC_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(domain5+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$REALM", "${DC_USERNAME}@${DOMAIN}", "$DC_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(domain6+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$DOMAIN", "${DC_USERNAME}@${REALM}", "$DC_PASSWORD", + pam_options]) for authtok_options in ["", "use_authtok", "try_authtok"]: _pam_options = "'%s %s'" % (o["pam_options"], authtok_options) -- 2.17.1 From e3760d6e3a3d141719e47eed755805a330609cac Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 20 Mar 2017 11:39:41 +0100 Subject: [PATCH 223/376] selftest: Export TRUST information in the ad_member target environment BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Andreas Schneider Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit 13e3811c9510cf213881527877bed40092e0b33c) --- selftest/target/Samba.pm | 22 ++++++++++++++++++++++ selftest/target/Samba3.pm | 24 ++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index ca3099c9d05..c30f6fe33ce 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -724,6 +724,28 @@ my @exported_envvars = ( "TRUST_REALM", "TRUST_DOMSID", + # stuff related to a trusted domain, on a trust_member + # the domain behind a forest trust (two-way) + "TRUST_F_BOTH_SERVER", + "TRUST_F_BOTH_SERVER_IP", + "TRUST_F_BOTH_SERVER_IPV6", + "TRUST_F_BOTH_NETBIOSNAME", + "TRUST_F_BOTH_USERNAME", + "TRUST_F_BOTH_PASSWORD", + "TRUST_F_BOTH_DOMAIN", + "TRUST_F_BOTH_REALM", + + # stuff related to a trusted domain, on a trust_member + # the domain behind an external trust (two-way) + "TRUST_E_BOTH_SERVER", + "TRUST_E_BOTH_SERVER_IP", + "TRUST_E_BOTH_SERVER_IPV6", + "TRUST_E_BOTH_NETBIOSNAME", + "TRUST_E_BOTH_USERNAME", + "TRUST_E_BOTH_PASSWORD", + "TRUST_E_BOTH_DOMAIN", + "TRUST_E_BOTH_REALM", + # domain controller stuff "DC_SERVER", "DC_SERVER_IP", diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 131d576a767..52d78ea51c0 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -181,7 +181,7 @@ sub check_env($$) nt4_member => ["nt4_dc"], - ad_member => ["ad_dc"], + ad_member => ["ad_dc", "fl2008r2dc", "fl2003dc"], ad_member_rfc2307 => ["ad_dc_ntvfs"], ad_member_idmap_rid => ["ad_dc"], ad_member_idmap_ad => ["fl2008r2dc"], @@ -369,7 +369,7 @@ sub setup_nt4_member sub setup_ad_member { - my ($self, $prefix, $dcvars) = @_; + my ($self, $prefix, $dcvars, $trustvars_f, $trustvars_e) = @_; my $prefix_abs = abs_path($prefix); my @dirs = (); @@ -493,6 +493,26 @@ sub setup_ad_member $ret->{DC_USERNAME} = $dcvars->{USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{PASSWORD}; + # forest trust + $ret->{TRUST_F_BOTH_SERVER} = $trustvars_f->{SERVER}; + $ret->{TRUST_F_BOTH_SERVER_IP} = $trustvars_f->{SERVER_IP}; + $ret->{TRUST_F_BOTH_SERVER_IPV6} = $trustvars_f->{SERVER_IPV6}; + $ret->{TRUST_F_BOTH_NETBIOSNAME} = $trustvars_f->{NETBIOSNAME}; + $ret->{TRUST_F_BOTH_USERNAME} = $trustvars_f->{USERNAME}; + $ret->{TRUST_F_BOTH_PASSWORD} = $trustvars_f->{PASSWORD}; + $ret->{TRUST_F_BOTH_DOMAIN} = $trustvars_f->{DOMAIN}; + $ret->{TRUST_F_BOTH_REALM} = $trustvars_f->{REALM}; + + # external trust + $ret->{TRUST_E_BOTH_SERVER} = $trustvars_e->{SERVER}; + $ret->{TRUST_E_BOTH_SERVER_IP} = $trustvars_e->{SERVER_IP}; + $ret->{TRUST_E_BOTH_SERVER_IPV6} = $trustvars_e->{SERVER_IPV6}; + $ret->{TRUST_E_BOTH_NETBIOSNAME} = $trustvars_e->{NETBIOSNAME}; + $ret->{TRUST_E_BOTH_USERNAME} = $trustvars_e->{USERNAME}; + $ret->{TRUST_E_BOTH_PASSWORD} = $trustvars_e->{PASSWORD}; + $ret->{TRUST_E_BOTH_DOMAIN} = $trustvars_e->{DOMAIN}; + $ret->{TRUST_E_BOTH_REALM} = $trustvars_e->{REALM}; + return $ret; } -- 2.17.1 From f0f2ce68e450dbf9f8f7e2257dee9e5e00c29567 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 10 Jun 2017 14:38:40 +0200 Subject: [PATCH 224/376] selftest/tests.py: test pam_winbind for trusts domains BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit ad6f0e056ac27ab5c078dbdbff44372da05caab2) --- selftest/tests.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/selftest/tests.py b/selftest/tests.py index e37cb9e7b96..e767f276353 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -263,6 +263,90 @@ if with_pam: valgrindify(python), pam_wrapper_so_path, "$DOMAIN", "${DC_USERNAME}@${REALM}", "$DC_PASSWORD", pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_f_both1+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$TRUST_F_BOTH_DOMAIN", + "$TRUST_F_BOTH_USERNAME", + "$TRUST_F_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_f_both2+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$TRUST_F_BOTH_REALM", + "$TRUST_F_BOTH_USERNAME", + "$TRUST_F_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_f_both3+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "''", + "${TRUST_F_BOTH_USERNAME}@${TRUST_F_BOTH_DOMAIN}", + "$TRUST_F_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_f_both4+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "''", + "${TRUST_F_BOTH_USERNAME}@${TRUST_F_BOTH_REALM}", + "$TRUST_F_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_f_both5+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "${TRUST_F_BOTH_REALM}", + "${TRUST_F_BOTH_USERNAME}@${TRUST_F_BOTH_DOMAIN}", + "$TRUST_F_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_f_both6+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "${TRUST_F_BOTH_DOMAIN}", + "${TRUST_F_BOTH_USERNAME}@${TRUST_F_BOTH_REALM}", + "$TRUST_F_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_e_both1+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$TRUST_E_BOTH_DOMAIN", + "$TRUST_E_BOTH_USERNAME", + "$TRUST_E_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_e_both2+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "$TRUST_E_BOTH_REALM", + "$TRUST_E_BOTH_USERNAME", + "$TRUST_E_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_e_both3+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "''", + "${TRUST_E_BOTH_USERNAME}@${TRUST_E_BOTH_DOMAIN}", + "$TRUST_E_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_e_both4+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "''", + "${TRUST_E_BOTH_USERNAME}@${TRUST_E_BOTH_REALM}", + "$TRUST_E_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_e_both5+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "${TRUST_E_BOTH_REALM}", + "${TRUST_E_BOTH_USERNAME}@${TRUST_E_BOTH_DOMAIN}", + "$TRUST_E_BOTH_PASSWORD", + pam_options]) + plantestsuite("samba.tests.pam_winbind(trust_e_both6+%s)" % description, env, + [os.path.join(srcdir(), "python/samba/tests/test_pam_winbind.sh"), + valgrindify(python), pam_wrapper_so_path, + "${TRUST_E_BOTH_DOMAIN}", + "${TRUST_E_BOTH_USERNAME}@${TRUST_E_BOTH_REALM}", + "$TRUST_E_BOTH_PASSWORD", + pam_options]) for authtok_options in ["", "use_authtok", "try_authtok"]: _pam_options = "'%s %s'" % (o["pam_options"], authtok_options) -- 2.17.1 From f836385629c097ec8564ac19045c5906fdb13f64 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 08:02:38 +0200 Subject: [PATCH 225/376] selftest/Samba3.pm: use "winbind scan trusted domains = no" for ad_member This demonstrates that we rely on knowning about trusted domains before we can do krb5_auth in winbindd. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit e2737a74d4453a3d65e5466ddc4405d68444df27) --- selftest/knownfail.d/pam_winbind_krb5 | 1 + selftest/target/Samba3.pm | 1 + 2 files changed, 2 insertions(+) create mode 100644 selftest/knownfail.d/pam_winbind_krb5 diff --git a/selftest/knownfail.d/pam_winbind_krb5 b/selftest/knownfail.d/pam_winbind_krb5 new file mode 100644 index 00000000000..1dd0c7d3f1c --- /dev/null +++ b/selftest/knownfail.d/pam_winbind_krb5 @@ -0,0 +1 @@ +^samba.tests.pam_winbind.trust_._both..krb5..samba.tests.pam_winbind.SimplePamTests.test_authenticate diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 52d78ea51c0..a75ec094b5e 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -416,6 +416,7 @@ sub setup_ad_member template homedir = /home/%D/%G/%U auth event notification = true password server = $dcvars->{SERVER} + winbind scan trusted domains = no [sub_dug] path = $share_dir/D_%D/U_%U/G_%G -- 2.17.1 From fcb247f41478e8b1f8ff504e901cefc047bdf197 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Sep 2019 08:10:26 +0200 Subject: [PATCH 226/376] selftest/Samba3.pm: use "winbind use krb5 enterprise principals = yes" for ad_member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This demonstrates that can do krb5_auth in winbindd without knowning about trusted domains. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14124 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner Autobuild-User(master): Günther Deschner Autobuild-Date(master): Tue Sep 24 19:51:29 UTC 2019 on sn-devel-184 (cherry picked from commit 0ee085b594878f5e0e83839f465303754f015459) --- selftest/knownfail.d/pam_winbind_krb5 | 1 - selftest/target/Samba3.pm | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/pam_winbind_krb5 diff --git a/selftest/knownfail.d/pam_winbind_krb5 b/selftest/knownfail.d/pam_winbind_krb5 deleted file mode 100644 index 1dd0c7d3f1c..00000000000 --- a/selftest/knownfail.d/pam_winbind_krb5 +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.pam_winbind.trust_._both..krb5..samba.tests.pam_winbind.SimplePamTests.test_authenticate diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index a75ec094b5e..32bd8698df2 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -417,6 +417,7 @@ sub setup_ad_member auth event notification = true password server = $dcvars->{SERVER} winbind scan trusted domains = no + winbind use krb5 enterprise principals = yes [sub_dug] path = $share_dir/D_%D/U_%U/G_%G -- 2.17.1 From 75702977dde834f06460e8434ea98b81020efbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Mon, 23 Sep 2019 08:57:33 +0200 Subject: [PATCH 227/376] fault.c: improve fault_report message text pointing to our wiki BUG: https://bugzilla.samba.org/show_bug.cgi?id=14139 Signed-off-by: Bjoern Jacke Reviewed-by: Alexander Bokovoy (cherry picked from commit ec4c5975528f3d3ab9c8813e176c6d1a2f1ca506) --- lib/util/fault.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/util/fault.c b/lib/util/fault.c index 5be9162679e..c42bc51789a 100644 --- a/lib/util/fault.c +++ b/lib/util/fault.c @@ -78,7 +78,11 @@ static void fault_report(int sig) DEBUGSEP(0); DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING)); - DEBUG(0,("\nPlease read the Trouble-Shooting section of the Samba HOWTO\n")); + DEBUG(0,("\nIf you are running a recent Samba version, and " + "if you think this problem is not yet fixed in the " + "latest versions, please consider reporting this " + "bug, see " + "https://wiki.samba.org/index.php/Bug_Reporting\n")); DEBUGSEP(0); smb_panic("internal error"); -- 2.17.1 From a89e8588449a09f47250e81d87828de74d4c5106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 12 Sep 2019 16:39:10 +0200 Subject: [PATCH 228/376] s3-winbindd: fix forest trusts with additional trust attributes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14130 Guenther Signed-off-by: Guenther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit d78c87e665e23e6470a19a69383ede7137172c26) --- source3/winbindd/winbindd_ads.c | 2 +- source3/winbindd/winbindd_util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 5f20cfb7f76..485ca831be9 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1457,7 +1457,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, */ if ((trust->trust_attributes - == LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) && + & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) && !domain->primary ) { DEBUG(10,("trusted_domains: Skipping external trusted " diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index cc4c3f7391a..ee7651c9639 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -723,7 +723,7 @@ static void rescan_forest_trusts( void ) if ( (flags & NETR_TRUST_FLAG_INBOUND) && (type == LSA_TRUST_TYPE_UPLEVEL) && - (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) ) + (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) ) { /* add the trusted domain if we don't know about it */ -- 2.17.1 From 4709a848c550e6b56a8a94ca722fa6ab091e3725 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 15:18:55 +0200 Subject: [PATCH 229/376] s3:waf: Do not check for nanosleep() as we don't use it anywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use usleep() in the meantime. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit 952e1812fa9bdc1bac2a7ae5ebb5532f1ea31447) --- source3/wscript | 1 - 1 file changed, 1 deletion(-) diff --git a/source3/wscript b/source3/wscript index 4a3e75605e7..7b257bcb845 100644 --- a/source3/wscript +++ b/source3/wscript @@ -116,7 +116,6 @@ def configure(conf): conf.CHECK_FUNCS('fstatat') conf.CHECK_FUNCS('getpwent_r setenv clearenv strcasecmp fcvt fcvtl') conf.CHECK_FUNCS('syslog vsyslog timegm setlocale') - conf.CHECK_FUNCS_IN('nanosleep', 'rt') conf.CHECK_FUNCS('lutimes futimes utimensat futimens') conf.CHECK_FUNCS('mlock munlock mlockall munlockall') conf.CHECK_FUNCS('memalign posix_memalign hstrerror') -- 2.17.1 From 7ec980b991fd5b62e5739a5fdb2dcbb1306c52d9 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 15:14:24 +0200 Subject: [PATCH 230/376] replace: Only link against librt if really needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fdatasync() and clock_gettime() are provided by glibc on Linux, so there is no need to link against librt. Checks have been added so if there are platforms which require it are still functional. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit 480152dd6729d4c58faca6f3e4fa91ff4614c272) --- lib/replace/wscript | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/replace/wscript b/lib/replace/wscript index 4df1b4d77c4..ec5e085a350 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -458,11 +458,28 @@ def configure(conf): conf.CHECK_C_PROTOTYPE('dlopen', 'void *dlopen(const char* filename, unsigned int flags)', define='DLOPEN_TAKES_UNSIGNED_FLAGS', headers='dlfcn.h dl.h') - if conf.CHECK_FUNCS_IN('fdatasync', 'rt', checklibc=True): + # + # Check for clock_gettime and fdatasync + # + # First check libc to avoid linking libreplace against librt. + # + if conf.CHECK_FUNCS('fdatasync'): # some systems are missing the declaration conf.CHECK_DECLS('fdatasync') + else: + if conf.CHECK_FUNCS_IN('fdatasync', 'rt'): + # some systems are missing the declaration + conf.CHECK_DECLS('fdatasync') + + has_clock_gettime = False + if conf.CHECK_FUNCS('clock_gettime'): + has_clock_gettime = True + + if not has_clock_gettime: + if conf.CHECK_FUNCS_IN('clock_gettime', 'rt', checklibc=True): + has_clock_gettime = True - if conf.CHECK_FUNCS_IN('clock_gettime', 'rt', checklibc=True): + if has_clock_gettime: for c in ['CLOCK_MONOTONIC', 'CLOCK_PROCESS_CPUTIME_ID', 'CLOCK_REALTIME']: conf.CHECK_CODE(''' #if TIME_WITH_SYS_TIME @@ -816,6 +833,7 @@ def build(bld): extra_libs = '' if bld.CONFIG_SET('HAVE_LIBBSD'): extra_libs += ' bsd' + if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' bld.SAMBA_SUBSYSTEM('LIBREPLACE_HOSTCC', REPLACE_HOSTCC_SOURCE, @@ -856,7 +874,7 @@ def build(bld): # at the moment: # hide_symbols=bld.BUILTIN_LIBRARY('replace'), private_library=True, - deps='crypt dl nsl socket rt attr' + extra_libs) + deps='crypt dl nsl socket attr' + extra_libs) replace_test_cflags = '' if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): -- 2.17.1 From 82c9a6c4b0adfc472b342c898c2cb3b382132c53 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 16:10:35 +0200 Subject: [PATCH 231/376] pthreadpool: Only link pthreadpool against librt if we have to MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This calls clock_gettime() which is available in glibc on Linux. If the wscript in libreplace detected that librt is needed for clock_gettime() we have to link against it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit 4b28239d13b17e42eb5aa4b405342f46347f3de4) --- lib/pthreadpool/wscript_build | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pthreadpool/wscript_build b/lib/pthreadpool/wscript_build index 57df25548b1..70aa7cbf041 100644 --- a/lib/pthreadpool/wscript_build +++ b/lib/pthreadpool/wscript_build @@ -1,12 +1,17 @@ #!/usr/bin/env python if bld.env.WITH_PTHREADPOOL: + extra_libs='' + + # Link to librt if needed for clock_gettime() + if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' + bld.SAMBA_SUBSYSTEM('PTHREADPOOL', source='''pthreadpool.c pthreadpool_pipe.c pthreadpool_tevent.c ''', - deps='pthread rt replace tevent-util') + deps='pthread replace tevent-util' + extra_libs) else: bld.SAMBA_SUBSYSTEM('PTHREADPOOL', source='''pthreadpool_sync.c -- 2.17.1 From 62f0ce14a1b8e03e4c4fd8710df86a9a58bca73b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 17:04:57 +0200 Subject: [PATCH 232/376] third_party: Only link cmocka against librt if really needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cmocka also uses clock_gettime(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit 36e8d715bc8dc1e8466f5a5c9798df76310b7572) --- third_party/cmocka/wscript | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/third_party/cmocka/wscript b/third_party/cmocka/wscript index 9ebdd7cfbe9..3c2ad50801a 100644 --- a/third_party/cmocka/wscript +++ b/third_party/cmocka/wscript @@ -12,8 +12,13 @@ def build(bld): if bld.CONFIG_SET('USING_SYSTEM_CMOCKA'): return + extra_libs='' + + # Link to librt if needed for clock_gettime() + if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' + bld.SAMBA_LIBRARY('cmocka', source='cmocka.c', - deps='rt', + deps=extra_libs, allow_warnings=True, private_library=True) -- 2.17.1 From 48cd645d1d81fae6f528e3cc7e83b3d9ad1caefd Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 17:39:29 +0200 Subject: [PATCH 233/376] third_party: Link nss_wrapper against pthread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nss_wrapper uses pthread_atfork() which is only provided by libpthread. So we need an explicit dependency. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit 68d8a02ef57cce29e4ff3ef1b792adfc10d0b916) --- third_party/nss_wrapper/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/nss_wrapper/wscript b/third_party/nss_wrapper/wscript index 127b5207c5e..7a2f53ad299 100644 --- a/third_party/nss_wrapper/wscript +++ b/third_party/nss_wrapper/wscript @@ -90,6 +90,6 @@ def build(bld): # breaks preloading! bld.SAMBA_LIBRARY('nss_wrapper', source='nss_wrapper.c', - deps='dl', + deps='dl pthread', install=False, realname='libnss-wrapper.so') -- 2.17.1 From b5dfe882ecbe5317c12971d83140b59a0d24da6b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 17:40:13 +0200 Subject: [PATCH 234/376] third_party: Link uid_wrapper against pthread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uid_wrapper uses pthread_atfork() which is only provided by libpthread. │···················· So we need an explicit dependency. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit bd0cd8e13234d684da77a65f6fdaea2572625369) --- third_party/uid_wrapper/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/uid_wrapper/wscript b/third_party/uid_wrapper/wscript index 61d8a189625..738343f49e4 100644 --- a/third_party/uid_wrapper/wscript +++ b/third_party/uid_wrapper/wscript @@ -119,6 +119,6 @@ def build(bld): # breaks preloading! bld.SAMBA_LIBRARY('uid_wrapper', source='uid_wrapper.c', - deps='dl', + deps='dl pthread', install=False, realname='libuid-wrapper.so') -- 2.17.1 From 0182ccfd22bfd002d9c1d1f04372fccd642cfc0e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 23 Sep 2019 16:53:12 +0200 Subject: [PATCH 235/376] waf:replace: Do not link against libpthread if not necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Linux we should avoid linking everything against libpthread. Symbols used my most application are provided by glibc and code which deals with threads has to explicitly link against libpthread. This avoids setting LDFLAGS=-pthread globally. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Pair-Programmed-With: Isaac Boukris Reviewed-by: Matthias Dieter Wallnöfer Reviewed-by: Alexander Bokovoy (cherry picked from commit 9499db075b72b147e2ff9bb78e9d5edbaac14e69) --- lib/replace/wscript | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/replace/wscript b/lib/replace/wscript index ec5e085a350..240d730cbee 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -552,6 +552,11 @@ def configure(conf): PTHREAD_CFLAGS='error' PTHREAD_LDFLAGS='error' + if PTHREAD_LDFLAGS == 'error': + # Check if pthread_attr_init() is provided by libc first! + if conf.CHECK_FUNCS('pthread_attr_init'): + PTHREAD_CFLAGS='-D_REENTRANT' + PTHREAD_LDFLAGS='' if PTHREAD_LDFLAGS == 'error': if conf.CHECK_FUNCS_IN('pthread_attr_init', 'pthread'): PTHREAD_CFLAGS='-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS' @@ -564,10 +569,7 @@ def configure(conf): if conf.CHECK_FUNCS_IN('pthread_attr_init', 'c_r'): PTHREAD_CFLAGS='-D_THREAD_SAFE -pthread' PTHREAD_LDFLAGS='-pthread' - if PTHREAD_LDFLAGS == 'error': - if conf.CHECK_FUNCS('pthread_attr_init'): - PTHREAD_CFLAGS='-D_REENTRANT' - PTHREAD_LDFLAGS='-lpthread' + # especially for HP-UX, where the CHECK_FUNC macro fails to test for # pthread_attr_init. On pthread_mutex_lock it works there... if PTHREAD_LDFLAGS == 'error': -- 2.17.1 From 4a43d8b996b1ce444596ed41a686be5ae526113d Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 25 Sep 2019 17:19:27 -0700 Subject: [PATCH 236/376] selftest: Test ID_TYPE_BOTH with idmap_rid module ID_TYPE_BOTH means that each user and group has two mappings, a uid and gid. In addition the calls to getpwent, getpwuid, getgrent and getgrgid always return some information, so that uid and gid can be mapped to a name. Establish a test to verify that the expected information is returned. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14141 Signed-off-by: Christof Schmitt Reviewed-by: Stefan Metzmacher (cherry picked from commit 485874d6bb328c50c9a98785e85270f28ade7497) --- nsswitch/tests/test_idmap_rid.sh | 132 +++++++++++++++++++++++ selftest/knownfail.d/passwd-id-type-both | 4 + 2 files changed, 136 insertions(+) create mode 100644 selftest/knownfail.d/passwd-id-type-both diff --git a/nsswitch/tests/test_idmap_rid.sh b/nsswitch/tests/test_idmap_rid.sh index 8209a50a4fc..4e6477f666e 100755 --- a/nsswitch/tests/test_idmap_rid.sh +++ b/nsswitch/tests/test_idmap_rid.sh @@ -63,4 +63,136 @@ test "$out" = "$SID -> unmapped" ret=$? testit "Bogus SID returns unmapped" test $ret -eq 0 || failed=$(expr $failed + 1) +# +# Test 3: ID_TYPE_BOTH mappings for group +# + +GROUP="$DOMAIN/Domain Users" +GROUP_SID=$($wbinfo --name-to-sid="$GROUP" | sed -e 's/ .*//') + +uid=$($wbinfo --sid-to-uid=$GROUP_SID) +ret=$? +testit "ID_TYPE_BOTH group map to uid succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +testit "ID_TYPE_BOTH group map to uid has result" test -n $uid ||\ + failed=$(expr $failed + 1) + +gid=$($wbinfo --sid-to-gid=$GROUP_SID) +ret=$? +testit "ID_TYPE_BOTH group map to gid succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +testit "ID_TYPE_BOTH group map to gid has result" test -n $gid ||\ + failed=$(expr $failed + 1) + +testit "ID_TYPE_BOTH group uid equals gid" test $uid -eq $gid ||\ + failed=$(expr $failed + 1) + +group_pw="$DOMAIN/domain users:*:$uid:$gid::/home/$DOMAIN/domain users:/bin/false" + +out=$(getent passwd "$GROUP") +ret=$? +testit "getpwnam for ID_TYPE_BOTH group succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +test "$out" = "$group_pw" +ret=$? +testit "getpwnam for ID_TYPE_BOTH group output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +out=$(getent passwd $uid) +ret=$? +testit "getpwuid for ID_TYPE_BOTH group succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +test "$out" = "$group_pw" +ret=$? +testit "getpwuid for ID_TYPE_BOTH group output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +group_gr="$DOMAIN/domain users:x:$gid:" + +out=$(getent group "$GROUP") +ret=$? +testit "getgrnam for ID_TYPE_BOTH group succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +test "$out" = "$group_gr" +ret=$? +testit "getgrnam for ID_TYPE_BOTH group output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +out=$(getent group "$gid") +ret=$? +testit "getgrgid for ID_TYPE_BOTH group succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +test "$out" = "$group_gr" +ret=$? +testit "getgrgid for ID_TYPE_BOTH group output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +# +# Test 4: ID_TYPE_BOTH mappings for user +# + +dom_users_gid=$gid + +USER="$DOMAIN/Administrator" +USER_SID=$($wbinfo --name-to-sid="$USER" | sed -e 's/ .*//') + +uid=$($wbinfo --sid-to-uid=$USER_SID) +ret=$? +testit "ID_TYPE_BOTH user map to uid succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +testit "ID_TYPE_BOTH user map to uid has result" test -n $uid ||\ + failed=$(expr $failed + 1) + +gid=$($wbinfo --sid-to-gid=$USER_SID) +ret=$? +testit "ID_TYPE_BOTH user map to gid succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +testit "ID_TYPE_BOTH user map to gid has result" test -n $gid ||\ + failed=$(expr $failed + 1) + +testit "ID_TYPE_BOTH user uid equals gid" test $uid -eq $gid ||\ + failed=$(expr $failed + 1) + +user_pw="$DOMAIN/administrator:*:$uid:$dom_users_gid::/home/$DOMAIN/administrator:/bin/false" + +out=$(getent passwd "$USER") +ret=$? +testit "getpwnam for ID_TYPE_BOTH user succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +test "$out" = "$user_pw" +ret=$? +testit "getpwnam for ID_TYPE_BOTH user output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +out=$(getent passwd $uid) +ret=$? +testit "getpwuid for ID_TYPE_BOTH user succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +test "$out" = "$user_pw" +ret=$? +testit "getpwuid for ID_TYPE_BOTH user output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +user_gr="$DOMAIN/administrator:x:$gid:$DOMAIN/administrator" + +out=$(getent group "$USER") +ret=$? +testit "getgrnam for ID_TYPE_BOTH user succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +test "$out" = "$user_gr" +ret=$? +testit "getgrnam for ID_TYPE_BOTH user output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + +out=$(getent group "$gid") +ret=$? +testit "getgrgid for ID_TYPE_BOTH user succeeds" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) +test "$out" = "$user_gr" +ret=$? +testit "getgrgid for ID_TYPE_BOTH user output" test $ret -eq 0 ||\ + failed=$(expr $failed + 1) + exit $failed diff --git a/selftest/knownfail.d/passwd-id-type-both b/selftest/knownfail.d/passwd-id-type-both new file mode 100644 index 00000000000..e969ef8d165 --- /dev/null +++ b/selftest/knownfail.d/passwd-id-type-both @@ -0,0 +1,4 @@ +idmap\.rid.getpwnam for ID_TYPE_BOTH group succeeds\(ad_member_idmap_rid\) +idmap\.rid.getpwnam for ID_TYPE_BOTH group output\(ad_member_idmap_rid\) +idmap\.rid.getpwuid for ID_TYPE_BOTH group succeeds\(ad_member_idmap_rid\) +idmap\.rid.getpwuid for ID_TYPE_BOTH group output\(ad_member_idmap_rid\) -- 2.17.1 From 42d530b0dbc1b1389b393c648357de31e4c11e9f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2019 10:44:30 +0100 Subject: [PATCH 237/376] winbind: provide passwd struct for group sid with ID_TYPE_BOTH mapping (again) https://git.samba.org/?p=samba.git;a=commitdiff;h=394622ef8c916cf361f8596dba4664dc8d6bfc9e originally introduced the above feature. This functionality was undone as part of "winbind: Restructure get_pwsid" https://git.samba.org/?p=samba.git;a=commitdiff;h=bce19a6efe11980933531f0349c8f5212419366a I think that this semantic change was accidential. This patch undoes the semantic change and re-establishes the functionality. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14141 Signed-off-by: Michael Adam Reviewed-by: Christof Schmitt Reviewed-by: Stefan Metzmacher Autobuild-User(master): Christof Schmitt Autobuild-Date(master): Fri Sep 27 17:25:29 UTC 2019 on sn-devel-184 (cherry picked from commit 63c9147f8631d73b52bdd36ff407e0361dcf5178) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Oct 2 11:06:20 UTC 2019 on sn-devel-184 --- selftest/knownfail.d/passwd-id-type-both | 4 ---- source3/winbindd/wb_queryuser.c | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) delete mode 100644 selftest/knownfail.d/passwd-id-type-both diff --git a/selftest/knownfail.d/passwd-id-type-both b/selftest/knownfail.d/passwd-id-type-both deleted file mode 100644 index e969ef8d165..00000000000 --- a/selftest/knownfail.d/passwd-id-type-both +++ /dev/null @@ -1,4 +0,0 @@ -idmap\.rid.getpwnam for ID_TYPE_BOTH group succeeds\(ad_member_idmap_rid\) -idmap\.rid.getpwnam for ID_TYPE_BOTH group output\(ad_member_idmap_rid\) -idmap\.rid.getpwuid for ID_TYPE_BOTH group succeeds\(ad_member_idmap_rid\) -idmap\.rid.getpwuid for ID_TYPE_BOTH group output\(ad_member_idmap_rid\) diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c index 17170c3352a..2eb61406fc5 100644 --- a/source3/winbindd/wb_queryuser.c +++ b/source3/winbindd/wb_queryuser.c @@ -166,8 +166,22 @@ static void wb_queryuser_got_domain(struct tevent_req *subreq) return; } - if (type != SID_NAME_USER) { - /* allow SID_NAME_COMPUTER? */ + switch (type) { + case SID_NAME_USER: + case SID_NAME_COMPUTER: + /* + * user case: we only need the account name from lookup_sids + */ + break; + case SID_NAME_DOM_GRP: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + /* + * also treat group-type SIDs (they might map to ID_TYPE_BOTH) + */ + sid_copy(&info->group_sid, &info->user_sid); + break; + default: tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); return; } -- 2.17.1 From e8cba5a8a88b47274305b56132a399117d074476 Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Mon, 30 Sep 2019 16:34:35 +1000 Subject: [PATCH 238/376] ctdb-vacuum: Process all records not deleted on a remote node This currently skips the last record. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14147 RN: Avoid potential data loss during recovery after vacuuming error Signed-off-by: Amitay Isaacs Reviewed-by: Martin Schwenke (cherry picked from commit 33f1c9d9654fbdcb99c23f9d23c4bbe2cc596b98) --- ctdb/server/ctdb_vacuum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctdb/server/ctdb_vacuum.c b/ctdb/server/ctdb_vacuum.c index 0c3770267bc..4fd11e3738c 100644 --- a/ctdb/server/ctdb_vacuum.c +++ b/ctdb/server/ctdb_vacuum.c @@ -814,7 +814,7 @@ static void ctdb_process_delete_list(struct ctdb_db_context *ctdb_db, */ records = (struct ctdb_marshall_buffer *)outdata.dptr; rec = (struct ctdb_rec_data_old *)&records->data[0]; - while (records->count-- > 1) { + while (records->count-- > 0) { TDB_DATA reckey, recdata; struct ctdb_ltdb_header *rechdr; struct delete_record_data *dd; -- 2.17.1 From 2ce14ef46a5d5d9ab6b9c30f1fb00debc1be71a4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Oct 2019 14:02:13 -0700 Subject: [PATCH 239/376] s3: smbclient: Stop an SMB2-connection from blundering into SMB1-specific calls. Fix in the same way this was done in SMBC_opendir_ctx() for libsmbclient. This fix means the admin no longer has to remember to set 'min client protocol =' when connecting to an SMB2-only server (MacOSX for example) and trying to list shares. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14152 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit ea82bca8cef0d736305a7a40b3198fc55ea66af8) --- source3/client/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/client/client.c b/source3/client/client.c index 7a7ecd92eb6..e1de711c8e4 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4918,6 +4918,10 @@ static bool browse_host(bool sort) return false; } + if (smbXcli_conn_protocol(cli->conn) > PROTOCOL_NT1) { + return false; + } + ret = cli_RNetShareEnum(cli, browse_fn, NULL); if (ret == -1) { NTSTATUS status = cli_nt_error(cli); -- 2.17.1 From adfcddc681564ff278cbbf243f1a245ec62f0dbe Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 8 Aug 2019 14:35:38 +0200 Subject: [PATCH 240/376] testprogs: Fix failure count in test_net_ads.sh There are missing ` at the end of the line. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13884 Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 320b5be4dce95d8dac4b3c0847faf5b730754a37) --- testprogs/blackbox/test_net_ads.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh index d3c4de5b741..512aa9d2952 100755 --- a/testprogs/blackbox/test_net_ads.sh +++ b/testprogs/blackbox/test_net_ads.sh @@ -141,10 +141,10 @@ testit "test spn service doensn't exist in AD but is present in keytab file afte # SPN parser is very basic but does detect some illegal combination windows_spn="$spn_service/$spn_host:" -testit_expect_failure "test (dedicated keytab) fail to parse windows spn with missing port" $VALGRIND $net_tool ads keytab add $windows_spn -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1 +testit_expect_failure "test (dedicated keytab) fail to parse windows spn with missing port" $VALGRIND $net_tool ads keytab add $windows_spn -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1` windows_spn="$spn_service/$spn_host/" -testit_expect_failure "test (dedicated keytab) fail to parse windows spn with missing servicename" $VALGRIND $net_tool ads keytab add $windows_spn -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1 +testit_expect_failure "test (dedicated keytab) fail to parse windows spn with missing servicename" $VALGRIND $net_tool ads keytab add $windows_spn -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1` testit "changetrustpw (dedicated keytab)" $VALGRIND $net_tool ads changetrustpw || failed=`expr $failed + 1` -- 2.17.1 From 90566a8ef442fefbd9b8b10789eaebd6349ef266 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 13 Aug 2019 17:06:58 +0200 Subject: [PATCH 241/376] s3:libads: Use ldap_add_ext_s() in ads_gen_add() ldap_add_s() is marked as deprecated. Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 456322a61319a10aaedda5244488ea4e5aa5cb64) --- source3/libads/ldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 2110390b65f..66aea348e23 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1596,7 +1596,7 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods) /* make sure the end of the list is NULL */ mods[i] = NULL; - ret = ldap_add_s(ads->ldap.ld, utf8_dn, (LDAPMod**)mods); + ret = ldap_add_ext_s(ads->ldap.ld, utf8_dn, (LDAPMod**)mods, NULL, NULL); ads_print_error(ret, ads->ldap.ld); TALLOC_FREE(utf8_dn); return ADS_ERROR(ret); -- 2.17.1 From 2fa6dc27f37652a4ccc9cd0e5e159e69364b7064 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 13 Aug 2019 17:41:40 +0200 Subject: [PATCH 242/376] s3:libnet: Require sealed LDAP SASL connections for joining Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit b84abb3a46211dc84e52ef95750627e4dd081f2f) --- libgpo/pygpo.c | 2 +- source3/lib/netapi/joindomain.c | 5 ++++- source3/libads/ads_proto.h | 9 ++++++++- source3/libads/ads_struct.c | 14 +++++++++++++- source3/libads/ldap.c | 4 ++-- source3/libnet/libnet_join.c | 3 ++- source3/libsmb/namequery_dc.c | 2 +- source3/printing/nt_printing_ads.c | 6 +++--- source3/utils/net_ads.c | 13 +++++++++---- source3/winbindd/winbindd_ads.c | 5 ++++- source3/winbindd/winbindd_cm.c | 5 ++++- 11 files changed, 51 insertions(+), 17 deletions(-) diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c index b1f788d3a00..581d20e0649 100644 --- a/libgpo/pygpo.c +++ b/libgpo/pygpo.c @@ -210,7 +210,7 @@ static int py_ads_init(ADS *self, PyObject *args, PyObject *kwds) self->ads_ptr = NULL; } /* always succeeds or crashes */ - self->ads_ptr = ads_init(realm, workgroup, ldap_server); + self->ads_ptr = ads_init(realm, workgroup, ldap_server, ADS_SASL_PLAIN); return 0; } diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c index ff2154ba803..8d0752f4531 100644 --- a/source3/lib/netapi/joindomain.c +++ b/source3/lib/netapi/joindomain.c @@ -411,7 +411,10 @@ WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx, dc = strip_hostname(info->dc_unc); - ads = ads_init(info->domain_name, info->domain_name, dc); + ads = ads_init(info->domain_name, + info->domain_name, + dc, + ADS_SASL_PLAIN); if (!ads) { return WERR_GEN_FAILURE; } diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h index 154bf67f964..92bb3a22cdb 100644 --- a/source3/libads/ads_proto.h +++ b/source3/libads/ads_proto.h @@ -32,6 +32,12 @@ #ifndef _LIBADS_ADS_PROTO_H_ #define _LIBADS_ADS_PROTO_H_ +enum ads_sasl_state_e { + ADS_SASL_PLAIN = 0, + ADS_SASL_SIGN, + ADS_SASL_SEAL, +}; + /* The following definitions come from libads/ads_struct.c */ char *ads_build_path(const char *realm, const char *sep, const char *field, int reverse); @@ -39,7 +45,8 @@ char *ads_build_dn(const char *realm); char *ads_build_domain(const char *dn); ADS_STRUCT *ads_init(const char *realm, const char *workgroup, - const char *ldap_server); + const char *ldap_server, + enum ads_sasl_state_e sasl_state); bool ads_set_sasl_wrap_flags(ADS_STRUCT *ads, int flags); void ads_destroy(ADS_STRUCT **ads); diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 3ab682c0e38..043a1b21247 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -132,7 +132,8 @@ char *ads_build_domain(const char *dn) */ ADS_STRUCT *ads_init(const char *realm, const char *workgroup, - const char *ldap_server) + const char *ldap_server, + enum ads_sasl_state_e sasl_state) { ADS_STRUCT *ads; int wrap_flags; @@ -152,6 +153,17 @@ ADS_STRUCT *ads_init(const char *realm, wrap_flags = 0; } + switch (sasl_state) { + case ADS_SASL_PLAIN: + break; + case ADS_SASL_SIGN: + wrap_flags |= ADS_AUTH_SASL_SIGN; + break; + case ADS_SASL_SEAL: + wrap_flags |= ADS_AUTH_SASL_SEAL; + break; + } + ads->auth.flags = wrap_flags; /* Start with the configured page size when the connection is new, diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 66aea348e23..2dc204f1ae8 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2966,7 +2966,7 @@ ADS_STATUS ads_current_time(ADS_STRUCT *ads) if ( !ads->ldap.ld ) { if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup, - ads->server.ldap_server )) == NULL ) + ads->server.ldap_server, ADS_SASL_PLAIN )) == NULL ) { status = ADS_ERROR(LDAP_NO_MEMORY); goto done; @@ -3028,7 +3028,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32_t *val) if ( !ads->ldap.ld ) { if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup, - ads->server.ldap_server )) == NULL ) + ads->server.ldap_server, ADS_SASL_PLAIN )) == NULL ) { status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto done; diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index b876d7ea89f..a512afc238a 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -140,7 +140,8 @@ static ADS_STATUS libnet_connect_ads(const char *dns_domain_name, my_ads = ads_init(dns_domain_name, netbios_domain_name, - dc_name); + dc_name, + ADS_SASL_SEAL); if (!my_ads) { return ADS_ERROR_LDAP(LDAP_NO_MEMORY); } diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c index 4ee5b5278e4..f63dde61603 100644 --- a/source3/libsmb/namequery_dc.c +++ b/source3/libsmb/namequery_dc.c @@ -69,7 +69,7 @@ static bool ads_dc_name(const char *domain, /* Try this 3 times then give up. */ for( i =0 ; i < 3; i++) { - ads = ads_init(realm, domain, NULL); + ads = ads_init(realm, domain, NULL, ADS_SASL_PLAIN); if (!ads) { TALLOC_FREE(sitename); return False; diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c index 2588e1de7e7..a82f1361fc8 100644 --- a/source3/printing/nt_printing_ads.c +++ b/source3/printing/nt_printing_ads.c @@ -227,7 +227,7 @@ WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer, return WERR_NOT_ENOUGH_MEMORY; } - ads = ads_init(lp_realm(), lp_workgroup(), NULL); + ads = ads_init(lp_realm(), lp_workgroup(), NULL, ADS_SASL_PLAIN); if (ads == NULL) { result = WERR_RPC_S_SERVER_UNAVAILABLE; goto out; @@ -577,7 +577,7 @@ WERROR nt_printer_publish(TALLOC_CTX *mem_ctx, TALLOC_FREE(sinfo2); - ads = ads_init(lp_realm(), lp_workgroup(), NULL); + ads = ads_init(lp_realm(), lp_workgroup(), NULL, ADS_SASL_PLAIN); if (!ads) { DEBUG(3, ("ads_init() failed\n")); win_rc = WERR_RPC_S_SERVER_UNAVAILABLE; @@ -633,7 +633,7 @@ WERROR check_published_printers(struct messaging_context *msg_ctx) tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return WERR_NOT_ENOUGH_MEMORY; - ads = ads_init(lp_realm(), lp_workgroup(), NULL); + ads = ads_init(lp_realm(), lp_workgroup(), NULL, ADS_SASL_PLAIN); if (!ads) { DEBUG(3, ("ads_init() failed\n")); return WERR_RPC_S_SERVER_UNAVAILABLE; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 4a0f59a1e80..19ac9e4533f 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -620,7 +620,10 @@ retry_connect: realm = assume_own_realm(c); } - ads = ads_init(realm, c->opt_target_workgroup, c->opt_host); + ads = ads_init(realm, + c->opt_target_workgroup, + c->opt_host, + ADS_SASL_PLAIN); if (!c->opt_user_name) { c->opt_user_name = "administrator"; @@ -729,7 +732,8 @@ static int net_ads_check_int(const char *realm, const char *workgroup, const cha ADS_STRUCT *ads; ADS_STATUS status; - if ( (ads = ads_init( realm, workgroup, host )) == NULL ) { + ads = ads_init(realm, workgroup, host, ADS_SASL_PLAIN); + if (ads == NULL ) { return -1; } @@ -1764,7 +1768,7 @@ static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, st * kinit with the machine password to do dns update. */ - ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name); + ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name, ADS_SASL_PLAIN); if (ads_dns == NULL) { d_fprintf(stderr, _("DNS update failed: out of memory!\n")); @@ -2655,7 +2659,8 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv) /* use the realm so we can eventually change passwords for users in realms other than default */ - if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) { + ads = ads_init(realm, c->opt_workgroup, c->opt_host, ADS_SASL_PLAIN); + if (ads == NULL) { return -1; } diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 485ca831be9..20f47eb5954 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -110,7 +110,10 @@ static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp, /* we don't want this to affect the users ccache */ setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); - ads = ads_init(target_realm, target_dom_name, ldap_server); + ads = ads_init(target_realm, + target_dom_name, + ldap_server, + ADS_SASL_SEAL); if (!ads) { DEBUG(1,("ads_init for domain %s failed\n", target_dom_name)); return ADS_ERROR(LDAP_NO_MEMORY); diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index b9a1c1eda7b..0e671ca22be 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1414,7 +1414,10 @@ static bool dcip_check_name(TALLOC_CTX *mem_ctx, print_sockaddr(addr, sizeof(addr), pss); - ads = ads_init(domain->alt_name, domain->name, addr); + ads = ads_init(domain->alt_name, + domain->name, + addr, + ADS_SASL_PLAIN); ads->auth.flags |= ADS_AUTH_NO_BIND; ads->config.flags |= request_flags; ads->server.no_fallback = true; -- 2.17.1 From 96ee2408f5ca85d84e341d642848a2532661a1f5 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 13 Aug 2019 16:30:07 +0200 Subject: [PATCH 243/376] s3:libads: Cleanup error code paths in ads_create_machine_acct() Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 8ed993789f93624b7b60dd5314fe5472e69e903a) --- source3/libads/ldap.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 2dc204f1ae8..a0bc5fe6741 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2092,11 +2092,12 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, uint32_t etype_list) { ADS_STATUS ret; - char *samAccountName, *controlstr; - TALLOC_CTX *ctx; + char *samAccountName = NULL; + char *controlstr = NULL; + TALLOC_CTX *ctx = NULL; ADS_MODLIST mods; char *machine_escaped = NULL; - char *new_dn; + char *new_dn = NULL; const char *objectClass[] = {"top", "person", "organizationalPerson", "user", "computer", NULL}; LDAPMessage *res = NULL; @@ -2110,13 +2111,14 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, return ret; } - if (!(ctx = talloc_init("ads_add_machine_acct"))) + ctx = talloc_init("ads_add_machine_acct"); + if (ctx == NULL) { return ADS_ERROR(LDAP_NO_MEMORY); - - ret = ADS_ERROR(LDAP_NO_MEMORY); + } machine_escaped = escape_rdn_val_string_alloc(machine_name); - if (!machine_escaped) { + if (machine_escaped == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } @@ -2131,17 +2133,26 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, ads_msgfree(ads, res); new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_escaped, org_unit); - samAccountName = talloc_asprintf(ctx, "%s$", machine_name); + if (new_dn == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } - if ( !new_dn || !samAccountName ) { + samAccountName = talloc_asprintf(ctx, "%s$", machine_name); + if (samAccountName == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } - if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control))) { + controlstr = talloc_asprintf(ctx, "%u", acct_control); + if (controlstr == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } - if (!(mods = ads_init_mods(ctx))) { + mods = ads_init_mods(ctx); + if (mods == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } @@ -2155,6 +2166,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, etype_list_str = talloc_asprintf(ctx, "%d", (int)etype_list); if (etype_list_str == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } ads_mod_str(ctx, &mods, "msDS-SupportedEncryptionTypes", -- 2.17.1 From 023a59d4262c1de4b0d62de0c75a905c0ea658e8 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 21 Aug 2019 12:22:32 +0200 Subject: [PATCH 244/376] s3:libads: Use a talloc_asprintf in ads_find_machine_acct() Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 35f3e4aed1f1c2ba1c8dc50921f238937f343357) --- source3/libads/ldap.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index a0bc5fe6741..f799c8f45d8 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1367,18 +1367,22 @@ char *ads_parent_dn(const char *dn) ADS_STATUS status; char *expr; const char *attrs[] = {"*", "msDS-SupportedEncryptionTypes", "nTSecurityDescriptor", NULL}; + TALLOC_CTX *frame = talloc_stackframe(); *res = NULL; /* the easiest way to find a machine account anywhere in the tree is to look for hostname$ */ - if (asprintf(&expr, "(samAccountName=%s$)", machine) == -1) { - DEBUG(1, ("asprintf failed!\n")); - return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); + expr = talloc_asprintf(frame, "(samAccountName=%s$)", machine); + if (expr == NULL) { + status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); + goto done; } status = ads_search(ads, res, expr, attrs); - SAFE_FREE(expr); + +done: + TALLOC_FREE(frame); return status; } -- 2.17.1 From 8cc6e035b6e68267d608e1d727d6e66b92823655 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 14 Aug 2019 13:01:19 +0200 Subject: [PATCH 245/376] s3:libads: Fix detection if acount already exists in ads_find_machine_count() Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 4f389c1f78cdc2424795e3b2a1ce43818c400c2d) --- source3/libads/ldap.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index f799c8f45d8..ea0d79a3600 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1366,7 +1366,21 @@ char *ads_parent_dn(const char *dn) { ADS_STATUS status; char *expr; - const char *attrs[] = {"*", "msDS-SupportedEncryptionTypes", "nTSecurityDescriptor", NULL}; + const char *attrs[] = { + /* This is how Windows checks for machine accounts */ + "objectClass", + "SamAccountName", + "userAccountControl", + "DnsHostName", + "ServicePrincipalName", + "unicodePwd", + + /* Additional attributes Samba checks */ + "msDS-SupportedEncryptionTypes", + "nTSecurityDescriptor", + + NULL + }; TALLOC_CTX *frame = talloc_stackframe(); *res = NULL; @@ -1380,6 +1394,11 @@ char *ads_parent_dn(const char *dn) } status = ads_search(ads, res, expr, attrs); + if (ADS_ERR_OK(status)) { + if (ads_count_replies(ads, *res) != 1) { + status = ADS_ERROR_LDAP(LDAP_NO_SUCH_OBJECT); + } + } done: TALLOC_FREE(frame); @@ -1867,11 +1886,11 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin char *dn_string = NULL; ret = ads_find_machine_acct(ads, &res, machine_name); - if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) { + if (!ADS_ERR_OK(ret)) { DEBUG(5,("ads_clear_service_principal_names: WARNING: Host Account for %s not found... skipping operation.\n", machine_name)); DEBUG(5,("ads_clear_service_principal_names: WARNING: Service Principals for %s have NOT been cleared.\n", machine_name)); ads_msgfree(ads, res); - return ADS_ERROR(LDAP_NO_SUCH_OBJECT); + return ret; } DEBUG(5,("ads_clear_service_principal_names: Host account for %s found\n", machine_name)); @@ -2027,12 +2046,12 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads, const char **servicePrincipalName = spns; ret = ads_find_machine_acct(ads, &res, machine_name); - if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) { + if (!ADS_ERR_OK(ret)) { DEBUG(1,("ads_add_service_principal_name: WARNING: Host Account for %s not found... skipping operation.\n", machine_name)); DEBUG(1,("ads_add_service_principal_name: WARNING: Service Principals have NOT been added.\n")); ads_msgfree(ads, res); - return ADS_ERROR(LDAP_NO_SUCH_OBJECT); + return ret; } DEBUG(1,("ads_add_service_principal_name: Host account for %s found\n", machine_name)); @@ -2127,7 +2146,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, } ret = ads_find_machine_acct(ads, &res, machine_escaped); - if (ADS_ERR_OK(ret) && ads_count_replies(ads, res) == 1) { + if (ADS_ERR_OK(ret)) { DBG_DEBUG("Host account for %s already exists.\n", machine_escaped); ret = ADS_ERROR_LDAP(LDAP_ALREADY_EXISTS); @@ -3688,14 +3707,15 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) TALLOC_FREE(hostnameDN); status = ads_find_machine_acct(ads, &res, host); - if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { + if ((status.error_type == ENUM_ADS_ERROR_LDAP) && + (status.err.rc != LDAP_NO_SUCH_OBJECT)) { DEBUG(3, ("Failed to remove host account.\n")); SAFE_FREE(host); return status; } SAFE_FREE(host); - return status; + return ADS_SUCCESS; } /** -- 2.17.1 From e0be43a863bba4be3df81b8a7b7a95f99bfb4783 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 14 Aug 2019 12:17:20 +0200 Subject: [PATCH 246/376] s3:libads: Don't set supported encryption types during account creation This is already handled by libnet_join_post_processing_ads_modify() which calls libnet_join_set_etypes() if encrytion types should be set. Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit b755a6438022579dab1a403c81d60b1ed7efca38) --- source3/libads/ldap.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index ea0d79a3600..cdefe290c28 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2127,12 +2127,6 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, uint32_t acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\ UF_DONT_EXPIRE_PASSWD |\ UF_ACCOUNTDISABLE ); - uint32_t func_level = 0; - - ret = ads_domain_func_level(ads, &func_level); - if (!ADS_ERR_OK(ret)) { - return ret; - } ctx = talloc_init("ads_add_machine_acct"); if (ctx == NULL) { @@ -2184,18 +2178,6 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, ads_mod_strlist(ctx, &mods, "objectClass", objectClass); ads_mod_str(ctx, &mods, "userAccountControl", controlstr); - if (func_level >= DS_DOMAIN_FUNCTION_2008) { - const char *etype_list_str; - - etype_list_str = talloc_asprintf(ctx, "%d", (int)etype_list); - if (etype_list_str == NULL) { - ret = ADS_ERROR(LDAP_NO_MEMORY); - goto done; - } - ads_mod_str(ctx, &mods, "msDS-SupportedEncryptionTypes", - etype_list_str); - } - ret = ads_gen_add(ads, new_dn, mods); done: -- 2.17.1 From 86e86cddcb5b6e0319605e1c46fe1932b3e81bf1 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 13 Aug 2019 16:34:34 +0200 Subject: [PATCH 247/376] s3:libads: Fix creating machine account using LDAP This implements the same behaviour as Windows. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13884 Pair-Programmed-With: Guenther Deschner Signed-off-by: Guenther Deschner Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit ce7762935051c862ecdd3e82d93096aac61dd292) --- source3/libads/ads_proto.h | 4 +- source3/libads/ldap.c | 118 +++++++++++++++++++++++++++++++---- source3/libnet/libnet_join.c | 23 ++++--- 3 files changed, 124 insertions(+), 21 deletions(-) diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h index 92bb3a22cdb..495ef5d3325 100644 --- a/source3/libads/ads_proto.h +++ b/source3/libads/ads_proto.h @@ -114,8 +114,10 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads, const char *machine_ const char **spns); ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, + const char *machine_password, const char *org_unit, - uint32_t etype_list); + uint32_t etype_list, + const char *dns_domain_name); ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name, const char *org_unit, bool *moved); int ads_count_replies(ADS_STRUCT *ads, void *res); diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index cdefe290c28..928c0da5af9 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1516,7 +1516,6 @@ ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, name, (const void **) vals); } -#if 0 /** * Add a single ber-encoded value to a mod list * @param ctx An initialized TALLOC_CTX @@ -1537,7 +1536,6 @@ static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods, return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES, name, (const void **) values); } -#endif static void ads_print_error(int ret, LDAP *ld) { @@ -2111,8 +2109,10 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads, ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, + const char *machine_password, const char *org_unit, - uint32_t etype_list) + uint32_t etype_list, + const char *dns_domain_name) { ADS_STATUS ret; char *samAccountName = NULL; @@ -2120,13 +2120,23 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, TALLOC_CTX *ctx = NULL; ADS_MODLIST mods; char *machine_escaped = NULL; + char *dns_hostname = NULL; char *new_dn = NULL; - const char *objectClass[] = {"top", "person", "organizationalPerson", - "user", "computer", NULL}; + char *utf8_pw = NULL; + size_t utf8_pw_len = 0; + char *utf16_pw = NULL; + size_t utf16_pw_len = 0; + struct berval machine_pw_val; + bool ok; + const char **spn_array = NULL; + size_t num_spns = 0; + const char *spn_prefix[] = { + "HOST", + "RestrictedKrbHost", + }; + size_t i; LDAPMessage *res = NULL; - uint32_t acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\ - UF_DONT_EXPIRE_PASSWD |\ - UF_ACCOUNTDISABLE ); + uint32_t acct_control = UF_WORKSTATION_TRUST_ACCOUNT; ctx = talloc_init("ads_add_machine_acct"); if (ctx == NULL) { @@ -2139,10 +2149,9 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, goto done; } + /* Check if the machine account already exists. */ ret = ads_find_machine_acct(ads, &res, machine_escaped); if (ADS_ERR_OK(ret)) { - DBG_DEBUG("Host account for %s already exists.\n", - machine_escaped); ret = ADS_ERROR_LDAP(LDAP_ALREADY_EXISTS); ads_msgfree(ads, res); goto done; @@ -2155,28 +2164,111 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, goto done; } + /* Create machine account */ + samAccountName = talloc_asprintf(ctx, "%s$", machine_name); if (samAccountName == NULL) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } + dns_hostname = talloc_asprintf(ctx, + "%s.%s", + machine_name, + dns_domain_name); + if (dns_hostname == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + /* Add dns_hostname SPNs */ + for (i = 0; i < ARRAY_SIZE(spn_prefix); i++) { + char *spn = talloc_asprintf(ctx, + "%s/%s", + spn_prefix[i], + dns_hostname); + if (spn == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + ok = add_string_to_array(spn_array, + spn, + &spn_array, + &num_spns); + if (!ok) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + } + + /* Add machine_name SPNs */ + for (i = 0; i < ARRAY_SIZE(spn_prefix); i++) { + char *spn = talloc_asprintf(ctx, + "%s/%s", + spn_prefix[i], + machine_name); + if (spn == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + ok = add_string_to_array(spn_array, + spn, + &spn_array, + &num_spns); + if (!ok) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + } + + /* Make sure to NULL terminate the array */ + spn_array = talloc_realloc(ctx, spn_array, const char *, num_spns + 1); + if (spn_array == NULL) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } + spn_array[num_spns] = NULL; + controlstr = talloc_asprintf(ctx, "%u", acct_control); if (controlstr == NULL) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } + utf8_pw = talloc_asprintf(ctx, "\"%s\"", machine_password); + if (utf8_pw == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + utf8_pw_len = strlen(utf8_pw); + + ok = convert_string_talloc(ctx, + CH_UTF8, CH_UTF16MUNGED, + utf8_pw, utf8_pw_len, + (void *)&utf16_pw, &utf16_pw_len); + if (!ok) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + machine_pw_val = (struct berval) { + .bv_val = utf16_pw, + .bv_len = utf16_pw_len, + }; + mods = ads_init_mods(ctx); if (mods == NULL) { ret = ADS_ERROR(LDAP_NO_MEMORY); goto done; } - ads_mod_str(ctx, &mods, "cn", machine_name); - ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName); - ads_mod_strlist(ctx, &mods, "objectClass", objectClass); + ads_mod_str(ctx, &mods, "objectClass", "Computer"); + ads_mod_str(ctx, &mods, "SamAccountName", samAccountName); ads_mod_str(ctx, &mods, "userAccountControl", controlstr); + ads_mod_str(ctx, &mods, "DnsHostName", dns_hostname); + ads_mod_strlist(ctx, &mods, "ServicePrincipalName", spn_array); + ads_mod_ber(ctx, &mods, "unicodePwd", &machine_pw_val); ret = ads_gen_add(ads, new_dn, mods); diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index a512afc238a..d5c8599beee 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -338,10 +338,22 @@ static ADS_STATUS libnet_join_precreate_machine_acct(TALLOC_CTX *mem_ctx, /* Attempt to create the machine account and bail if this fails. Assume that the admin wants exactly what they requested */ + if (r->in.machine_password == NULL) { + r->in.machine_password = + trust_pw_new_value(mem_ctx, + r->in.secure_channel_type, + SEC_ADS); + if (r->in.machine_password == NULL) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } + } + status = ads_create_machine_acct(r->in.ads, r->in.machine_name, + r->in.machine_password, r->in.account_ou, - r->in.desired_encryption_types); + r->in.desired_encryption_types, + r->out.dns_domain_name); if (ADS_ERR_OK(status)) { DEBUG(1,("machine account creation created\n")); @@ -2668,12 +2680,11 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx, if (ADS_ERR_OK(ads_status)) { /* - * LDAP object create succeeded, now go to the rpc - * password set routines + * LDAP object creation succeeded. */ - r->in.join_flags &= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE; - goto rpc_join; + + return WERR_OK; } if (initial_account_ou != NULL) { @@ -2687,8 +2698,6 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx, DBG_INFO("Failed to pre-create account in OU %s: %s\n", r->in.account_ou, ads_errstr(ads_status)); } - rpc_join: - #endif /* HAVE_ADS */ if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) && -- 2.17.1 From 8fa84176dbcc268492f07f92d8baf3156877f78a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 14 Aug 2019 10:15:19 +0200 Subject: [PATCH 248/376] s3:libnet: Improve debug messages Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 39b8c8b30a5d5bd70f8da3a02cf77f7592788b94) --- source3/libnet/libnet_join.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index d5c8599beee..31d1d221ed3 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -356,7 +356,7 @@ static ADS_STATUS libnet_join_precreate_machine_acct(TALLOC_CTX *mem_ctx, r->out.dns_domain_name); if (ADS_ERR_OK(status)) { - DEBUG(1,("machine account creation created\n")); + DBG_WARNING("Machine account successfully created\n"); return status; } else if ((status.error_type == ENUM_ADS_ERROR_LDAP) && (status.err.rc == LDAP_ALREADY_EXISTS)) { @@ -364,7 +364,7 @@ static ADS_STATUS libnet_join_precreate_machine_acct(TALLOC_CTX *mem_ctx, } if (!ADS_ERR_OK(status)) { - DEBUG(1,("machine account creation failed\n")); + DBG_WARNING("Failed to create machine account\n"); return status; } -- 2.17.1 From 440c8890798d6ac7a75f41f0ea0d1f98d234eb6b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 8 Aug 2019 14:40:04 +0200 Subject: [PATCH 249/376] s3:libads: Just change the machine password if account already exists BUG: https://bugzilla.samba.org/show_bug.cgi?id=13884 Pair-Programmed-With: Guenther Deschner Signed-off-by: Guenther Deschner Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 14f320fa1e40ecc3a43dabb0cecd57430270a521) --- source3/libads/ldap.c | 167 ++++++++++++++++++++++++++++++----- source3/libnet/libnet_join.c | 1 + 2 files changed, 146 insertions(+), 22 deletions(-) diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 928c0da5af9..979192eb3ed 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2098,6 +2098,127 @@ ADS_STATUS ads_add_service_principal_names(ADS_STRUCT *ads, return ret; } +static uint32_t ads_get_acct_ctrl(ADS_STRUCT *ads, + LDAPMessage *msg) +{ + uint32_t acct_ctrl = 0; + bool ok; + + ok = ads_pull_uint32(ads, msg, "userAccountControl", &acct_ctrl); + if (!ok) { + return 0; + } + + return acct_ctrl; +} + +static ADS_STATUS ads_change_machine_acct(ADS_STRUCT *ads, + LDAPMessage *msg, + const struct berval *machine_pw_val) +{ + ADS_MODLIST mods; + ADS_STATUS ret; + TALLOC_CTX *frame = talloc_stackframe(); + uint32_t acct_control; + char *control_str = NULL; + const char *attrs[] = { + "objectSid", + NULL + }; + LDAPMessage *res = NULL; + char *dn = NULL; + + dn = ads_get_dn(ads, frame, msg); + if (dn == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + acct_control = ads_get_acct_ctrl(ads, msg); + if (acct_control == 0) { + ret = ADS_ERROR(LDAP_NO_RESULTS_RETURNED); + goto done; + } + + /* + * Changing the password, disables the account. So we need to change the + * userAccountControl flags to enable it again. + */ + mods = ads_init_mods(frame); + if (mods == NULL) { + ret = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; + } + + ads_mod_ber(frame, &mods, "unicodePwd", machine_pw_val); + + ret = ads_gen_mod(ads, dn, mods); + if (!ADS_ERR_OK(ret)) { + goto done; + } + TALLOC_FREE(mods); + + /* + * To activate the account, we need to disable and enable it. + */ + acct_control |= UF_ACCOUNTDISABLE; + + control_str = talloc_asprintf(frame, "%u", acct_control); + if (control_str == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + mods = ads_init_mods(frame); + if (mods == NULL) { + ret = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; + } + + ads_mod_str(frame, &mods, "userAccountControl", control_str); + + ret = ads_gen_mod(ads, dn, mods); + if (!ADS_ERR_OK(ret)) { + goto done; + } + TALLOC_FREE(mods); + TALLOC_FREE(control_str); + + /* + * Enable the account again. + */ + acct_control &= ~UF_ACCOUNTDISABLE; + + control_str = talloc_asprintf(frame, "%u", acct_control); + if (control_str == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + mods = ads_init_mods(frame); + if (mods == NULL) { + ret = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; + } + + ads_mod_str(frame, &mods, "userAccountControl", control_str); + + ret = ads_gen_mod(ads, dn, mods); + if (!ADS_ERR_OK(ret)) { + goto done; + } + TALLOC_FREE(mods); + TALLOC_FREE(control_str); + + ret = ads_search_dn(ads, &res, dn, attrs); + ads_msgfree(ads, res); + +done: + talloc_free(frame); + + return ret; +} + /** * adds a machine account to the ADS server * @param ads An intialized ADS_STRUCT @@ -2149,11 +2270,34 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, goto done; } + utf8_pw = talloc_asprintf(ctx, "\"%s\"", machine_password); + if (utf8_pw == NULL) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + utf8_pw_len = strlen(utf8_pw); + + ok = convert_string_talloc(ctx, + CH_UTF8, CH_UTF16MUNGED, + utf8_pw, utf8_pw_len, + (void *)&utf16_pw, &utf16_pw_len); + if (!ok) { + ret = ADS_ERROR(LDAP_NO_MEMORY); + goto done; + } + + machine_pw_val = (struct berval) { + .bv_val = utf16_pw, + .bv_len = utf16_pw_len, + }; + /* Check if the machine account already exists. */ ret = ads_find_machine_acct(ads, &res, machine_escaped); if (ADS_ERR_OK(ret)) { - ret = ADS_ERROR_LDAP(LDAP_ALREADY_EXISTS); + /* Change the machine account password */ + ret = ads_change_machine_acct(ads, res, &machine_pw_val); ads_msgfree(ads, res); + goto done; } ads_msgfree(ads, res); @@ -2236,27 +2380,6 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, goto done; } - utf8_pw = talloc_asprintf(ctx, "\"%s\"", machine_password); - if (utf8_pw == NULL) { - ret = ADS_ERROR(LDAP_NO_MEMORY); - goto done; - } - utf8_pw_len = strlen(utf8_pw); - - ok = convert_string_talloc(ctx, - CH_UTF8, CH_UTF16MUNGED, - utf8_pw, utf8_pw_len, - (void *)&utf16_pw, &utf16_pw_len); - if (!ok) { - ret = ADS_ERROR(LDAP_NO_MEMORY); - goto done; - } - - machine_pw_val = (struct berval) { - .bv_val = utf16_pw, - .bv_len = utf16_pw_len, - }; - mods = ads_init_mods(ctx); if (mods == NULL) { ret = ADS_ERROR(LDAP_NO_MEMORY); diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 31d1d221ed3..1052afde641 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -968,6 +968,7 @@ static ADS_STATUS libnet_join_post_processing_ads_modify(TALLOC_CTX *mem_ctx, if (r->in.ads->auth.ccache_name != NULL) { ads_kdestroy(r->in.ads->auth.ccache_name); + r->in.ads->auth.ccache_name = NULL; } ads_destroy(&r->in.ads); -- 2.17.1 From 8d426b146e7f9ba04dc07779d810bd7c8fcd4b10 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 22 Aug 2019 16:31:30 +0200 Subject: [PATCH 250/376] testprogs: Add test for 'net ads join createcomputer=' Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Wed Oct 9 08:26:17 UTC 2019 on sn-devel-184 (cherry picked from commit 459b43e5776180dc1540cd845b72ff78747ecd6f) --- testprogs/blackbox/test_net_ads.sh | 32 ++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh index 512aa9d2952..cc8345c4624 100755 --- a/testprogs/blackbox/test_net_ads.sh +++ b/testprogs/blackbox/test_net_ads.sh @@ -31,6 +31,16 @@ if [ -x "$BINDIR/ldbsearch" ]; then ldbsearch="$BINDIR/ldbsearch" fi +ldbadd="ldbadd" +if [ -x "$BINDIR/ldbadd" ]; then + ldbadd="$BINDIR/ldbadd" +fi + +ldbdel="ldbdel" +if [ -x "$BINDIR/ldbdel" ]; then + ldbdel="$BINDIR/ldbdel" +fi + # Load test functions . `dirname $0`/subunit.sh @@ -188,8 +198,9 @@ testit "testjoin user+password" $VALGRIND $net_tool ads testjoin -U$DC_USERNAME% testit "leave+keep_account" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD --keep-account || failed=`expr $failed + 1` -computers_ldb_ou="CN=Computers,DC=addom,DC=samba,DC=example,DC=com" -testit "ldb check for existence of machine account" $ldbsearch -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "cn=$HOSTNAME,$computers_ldb_ou" || failed=`expr $failed + 1` +base_dn="DC=addom,DC=samba,DC=example,DC=com" +computers_dn="CN=Computers,$base_dn" +testit "ldb check for existence of machine account" $ldbsearch -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "cn=$HOSTNAME,$computers_dn" || failed=`expr $failed + 1` testit "join" $VALGRIND $net_tool ads join -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1` @@ -198,6 +209,23 @@ testit "testjoin" $VALGRIND $net_tool ads testjoin || failed=`expr $failed + 1` ##Goodbye... testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1` +# +# Test createcomputer option of 'net ads join' +# +testit "Create OU=Servers,$base_dn" $VALGRIND $ldbadd -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER < Date: Wed, 25 Sep 2019 23:44:49 +0200 Subject: [PATCH 251/376] libcli/auth: add test for gensec_schannel code Guenther Signed-off-by: Guenther Deschner Pair-Programmed-With: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 7eae4280d23404be7d27f65a0c817bea2e0084b6) --- libcli/auth/tests/test_schannel.c | 305 ++++++++++++++++++++++++++++++ libcli/auth/wscript_build | 8 + selftest/knownfail | 1 + selftest/tests.py | 2 + 4 files changed, 316 insertions(+) create mode 100644 libcli/auth/tests/test_schannel.c diff --git a/libcli/auth/tests/test_schannel.c b/libcli/auth/tests/test_schannel.c new file mode 100644 index 00000000000..b1c88fdf667 --- /dev/null +++ b/libcli/auth/tests/test_schannel.c @@ -0,0 +1,305 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2019 Guenther Deschner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "includes.h" +#include "auth/gensec/schannel.c" + +static void torture_schannel_seal_flags(void **state, uint32_t flags, + const DATA_BLOB session_key, + const DATA_BLOB seq_num_initial, + const DATA_BLOB confounder_initial, + const DATA_BLOB confounder_expected, + const DATA_BLOB clear_initial, + const DATA_BLOB crypt_expected) +{ + NTSTATUS status; + struct schannel_state *schannel_state; + struct netlogon_creds_CredentialState *creds; + uint8_t confounder[8]; + DATA_BLOB io; + + assert_int_equal(session_key.length, 16); + assert_int_equal(seq_num_initial.length, 8); + assert_int_equal(confounder_initial.length, 8); + assert_int_equal(confounder_expected.length, 8); + assert_int_equal(clear_initial.length, crypt_expected.length); + + DEBUG(0,("checking buffer size: %d\n", (int)clear_initial.length)); + + schannel_state = talloc_zero(NULL, struct schannel_state); + assert_non_null(schannel_state); + creds = talloc_zero(schannel_state, + struct netlogon_creds_CredentialState); + assert_non_null(creds); + schannel_state->creds = creds; + + io = data_blob_dup_talloc(schannel_state, clear_initial); + assert_non_null(io.data); + assert_int_equal(io.length, clear_initial.length); + + schannel_state->creds->negotiate_flags = flags; + memcpy(schannel_state->creds->session_key, session_key.data, 16); + + memcpy(confounder, confounder_initial.data, 8); + + DEBUG(0,("confounder before crypt:\n")); + dump_data(0, confounder, 8); + dump_data(0, seq_num_initial.data, 8); + dump_data(0, io.data, io.length); + + status = netsec_do_seal(schannel_state, + seq_num_initial.data, + confounder, + io.data, + io.length, + true); + + assert_true(NT_STATUS_IS_OK(status)); + dump_data(0, io.data, io.length); + DEBUG(0,("confounder after crypt:\n")); + dump_data(0, confounder, 8); + dump_data(0, seq_num_initial.data, 8); + assert_memory_equal(io.data, crypt_expected.data, crypt_expected.length); + assert_memory_equal(confounder, confounder_expected.data, confounder_expected.length); + + status = netsec_do_seal(schannel_state, + seq_num_initial.data, + confounder, + io.data, + io.length, + false); + + assert_true(NT_STATUS_IS_OK(status)); + dump_data(0, io.data, io.length); + DEBUG(0,("confounder after decrypt:\n")); + dump_data(0, confounder, 8); + dump_data(0, seq_num_initial.data, 8); + assert_memory_equal(io.data, clear_initial.data, clear_initial.length); + assert_memory_equal(confounder, confounder_initial.data, confounder_initial.length); + + talloc_free(schannel_state); +} + +static void torture_schannel_seal_rc4(void **state) +{ + const uint8_t _session_key[16] = { + 0x14, 0xD5, 0x7F, 0x8D, 0x8E, 0xCF, 0xFB, 0x56, + 0x71, 0x29, 0x9D, 0x9C, 0x2A, 0x75, 0x00, 0xA1 + }; + const DATA_BLOB session_key = data_blob_const(_session_key, 16); + const uint8_t _seq_num_initial[8] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 + }; + const DATA_BLOB seq_num_initial = + data_blob_const(_seq_num_initial, 8); + const uint8_t _confounder_initial[8] = { + 0x1A, 0x5A, 0xE8, 0xC7, 0xBE, 0x4F, 0x1F, 0x07 + }; + const DATA_BLOB confounder_initial = + data_blob_const(_confounder_initial, 8); + const uint8_t _confounder_expected[8] = { + 0x25, 0x4A, 0x9C, 0x15, 0x82, 0x3E, 0x4A, 0x42 + }; + const DATA_BLOB confounder_expected = + data_blob_const(_confounder_expected, 8); + const uint8_t _clear_initial[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8A, 0xE3, 0x13, 0x71, 0x02, 0xF4, 0x36, 0x71, + 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x40, 0x28, 0x00, 0x78, 0x57, 0x34, 0x12, + 0x34, 0x12, 0xCD, 0xAB, 0xEF, 0x00, 0x01, 0x23, + 0x45, 0x67, 0x89, 0xAB, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, + 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const DATA_BLOB clear_initial = data_blob_const(_clear_initial, + sizeof(_clear_initial)); + const uint8_t crypt_buffer[] = { + 0x3E, 0x10, 0x74, 0xD2, 0x3C, 0x71, 0x57, 0x45, + 0xB8, 0xAA, 0xCF, 0xE3, 0x84, 0xBE, 0xC4, 0x00, + 0xF4, 0x4D, 0x88, 0x0A, 0x9B, 0xCC, 0x53, 0xFC, + 0x32, 0xAA, 0x8E, 0x4B, 0x0E, 0xDE, 0x5F, 0x7D, + 0x6D, 0x31, 0x4E, 0xAB, 0xE0, 0x7D, 0x37, 0x9D, + 0x3D, 0x16, 0xD8, 0xBA, 0x6A, 0xB0, 0xD0, 0x99, + 0x14, 0x05, 0x37, 0xCF, 0x63, 0xD3, 0xD7, 0x60, + 0x63, 0x3C, 0x03, 0x0A, 0x30, 0xA0, 0x3E, 0xC7, + 0xDA, 0x94, 0x3B, 0x40, 0x63, 0x74, 0xEF, 0xCF, + 0xE5, 0x48, 0x87, 0xE9, 0x6A, 0x5A, 0xC7, 0x61, + 0xF7, 0x09, 0xB7, 0x7C, 0xDE, 0xDB, 0xB0, 0x94, + 0x9B, 0x99, 0xC0, 0xA7, 0x7E, 0x78, 0x09, 0x35, + 0xB4, 0xF4, 0x11, 0xC3, 0xB3, 0x77, 0xB5, 0x77, + 0x25, 0xEE, 0xFD, 0x2F, 0x9A, 0x15, 0x95, 0x27, + 0x08, 0xDA, 0xD0, 0x28, 0xD6, 0x31, 0xB4, 0xB7, + 0x7A, 0x19, 0xBB, 0xF3, 0x78, 0xF8, 0xC2, 0x5B + }; + const DATA_BLOB crypt_expected = data_blob_const(crypt_buffer, + sizeof(crypt_buffer)); + int buffer_sizes[] = { + 0, 1, 3, 7, 8, 9, 15, 16, 17 + }; + int i; + + torture_schannel_seal_flags(state, 0, + session_key, + seq_num_initial, + confounder_initial, + confounder_expected, + clear_initial, + crypt_expected); + + /* repeat the test for varying buffer sizes */ + + for (i = 0; i < ARRAY_SIZE(buffer_sizes); i++) { + DATA_BLOB clear_initial_trunc = + data_blob_const(clear_initial.data, buffer_sizes[i]); + DATA_BLOB crypt_expected_trunc = + data_blob_const(crypt_expected.data, buffer_sizes[i]); + torture_schannel_seal_flags(state, 0, + session_key, + seq_num_initial, + confounder_initial, + confounder_expected, + clear_initial_trunc, + crypt_expected_trunc); + } +} + +static void torture_schannel_seal_aes(void **state) +{ + const uint8_t _session_key[16] = { + 0x8E, 0xE8, 0x27, 0x85, 0x83, 0x41, 0x3C, 0x8D, + 0xC9, 0x54, 0x70, 0x75, 0x8E, 0xC9, 0x69, 0x91 + }; + const DATA_BLOB session_key = data_blob_const(_session_key, 16); + const uint8_t _seq_num_initial[8] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 + }; + const DATA_BLOB seq_num_initial = + data_blob_const(_seq_num_initial, 8); + const uint8_t _confounder_initial[8] = { + 0x6E, 0x09, 0x25, 0x94, 0x01, 0xA0, 0x09, 0x31 + }; + const DATA_BLOB confounder_initial = + data_blob_const(_confounder_initial, 8); + const uint8_t _confounder_expected[8] = { + 0xCA, 0xFB, 0xAC, 0xFB, 0xA8, 0x26, 0x75, 0x2A + }; + const DATA_BLOB confounder_expected = + data_blob_const(_confounder_expected, 8); + const uint8_t _clear_initial[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8A, 0xE3, 0x13, 0x71, 0x02, 0xF4, 0x36, 0x71, + 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x40, 0x28, 0x00, 0x78, 0x57, 0x34, 0x12, + 0x34, 0x12, 0xCD, 0xAB, 0xEF, 0x00, 0x01, 0x23, + 0x45, 0x67, 0x89, 0xAB, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, + 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const DATA_BLOB clear_initial = data_blob_const(_clear_initial, + sizeof(_clear_initial)); + const uint8_t crypt_buffer[] = { + 0xE2, 0xE5, 0xE3, 0x26, 0x45, 0xFB, 0xFC, 0xF3, + 0x9C, 0x14, 0xDD, 0xE1, 0x39, 0x23, 0xE0, 0x55, + 0xED, 0x8F, 0xF4, 0x92, 0xA1, 0xBD, 0xDC, 0x40, + 0x58, 0x6F, 0xD2, 0x5B, 0xF9, 0xC9, 0xA3, 0x87, + 0x46, 0x4B, 0x7F, 0xB2, 0x03, 0xD2, 0x35, 0x22, + 0x3E, 0x70, 0x9F, 0x1E, 0x3F, 0x1F, 0xDB, 0x7D, + 0x79, 0x88, 0x5A, 0x3D, 0xD3, 0x40, 0x1E, 0x69, + 0xD7, 0xE2, 0x1D, 0x5A, 0xE9, 0x3B, 0xE1, 0xE2, + 0x98, 0xFD, 0xCB, 0x3A, 0xF7, 0xB5, 0x1C, 0xF8, + 0xCA, 0x02, 0x00, 0x99, 0x9F, 0x0C, 0x01, 0xE6, + 0xD2, 0x00, 0xAF, 0xE0, 0x51, 0x88, 0x62, 0x50, + 0xB7, 0xE8, 0x6D, 0x63, 0x4B, 0x97, 0x05, 0xC1, + 0xD4, 0x83, 0x96, 0x29, 0x80, 0xAE, 0xD8, 0xA2, + 0xED, 0xC9, 0x5D, 0x0D, 0x29, 0xFF, 0x2C, 0x23, + 0x02, 0xFA, 0x3B, 0xEE, 0xE8, 0xBA, 0x06, 0x01, + 0x95, 0xDF, 0x80, 0x76, 0x0B, 0x17, 0x0E, 0xD8 + }; + const DATA_BLOB crypt_expected = data_blob_const(crypt_buffer, + sizeof(crypt_buffer)); + int buffer_sizes[] = { + 0, 1, 3, 7, 8, 9, 15, 16, 17 + }; + int i; + + torture_schannel_seal_flags(state, NETLOGON_NEG_SUPPORTS_AES, + session_key, + seq_num_initial, + confounder_initial, + confounder_expected, + clear_initial, + crypt_expected); + + /* repeat the test for varying buffer sizes */ + + for (i = 0; i < ARRAY_SIZE(buffer_sizes); i++) { + DATA_BLOB clear_initial_trunc = + data_blob_const(clear_initial.data, buffer_sizes[i]); + DATA_BLOB crypt_expected_trunc = + data_blob_const(crypt_expected.data, buffer_sizes[i]); + torture_schannel_seal_flags(state, NETLOGON_NEG_SUPPORTS_AES, + session_key, + seq_num_initial, + confounder_initial, + confounder_expected, + clear_initial_trunc, + crypt_expected_trunc); + } +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(torture_schannel_seal_rc4), + cmocka_unit_test(torture_schannel_seal_aes), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, NULL, NULL); + + return rc; +} diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build index 39489c20b4e..04e2b09eadf 100644 --- a/libcli/auth/wscript_build +++ b/libcli/auth/wscript_build @@ -54,3 +54,11 @@ bld.SAMBA_BINARY( ''', install=False ) + +bld.SAMBA_BINARY('test_schannel', + source='tests/test_schannel.c', + deps=''' + gensec + cmocka + ''', + install=False) diff --git a/selftest/knownfail b/selftest/knownfail index 7b54b77a708..94b0f014749 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -374,3 +374,4 @@ ^samba.tests.ntlmdisabled.python\(ktest\).python2.ntlmdisabled.NtlmDisabledTests.test_samr_change_password\(ktest\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python3.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python2.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) +^samba.unittests.schannel.torture_schannel_seal_rc4 diff --git a/selftest/tests.py b/selftest/tests.py index e767f276353..bbb5709ee47 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -390,6 +390,8 @@ plantestsuite("samba.unittests.byteorder", "none", [os.path.join(bindir(), "default/lib/util/test_byteorder")]) plantestsuite("samba.unittests.ntlm_check", "none", [os.path.join(bindir(), "default/libcli/auth/test_ntlm_check")]) +plantestsuite("samba.unittests.schannel", "none", + [os.path.join(bindir(), "default/libcli/auth/test_schannel")]) plantestsuite("samba.unittests.test_registry_regfio", "none", [os.path.join(bindir(), "default/source3/test_registry_regfio")]) plantestsuite("samba.unittests.test_oLschema2ldif", "none", -- 2.17.1 From fc0efd56d0584d8ca950ad837bd19e7341833dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 20 Sep 2019 18:32:43 +0200 Subject: [PATCH 252/376] auth/gensec: fix non-AES schannel seal BUG: https://bugzilla.samba.org/show_bug.cgi?id=14134 Guenther Signed-off-by: Guenther Deschner Reviewed-by: Andreas Schneider (cherry picked from commit 709d54d68a9c2cb3cda91d9ab63228a7adbaceb4) --- auth/gensec/schannel.c | 9 +++++++++ selftest/knownfail | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c index 8ba1eafc76d..74a3eb5c690 100644 --- a/auth/gensec/schannel.c +++ b/auth/gensec/schannel.c @@ -296,6 +296,15 @@ static NTSTATUS netsec_do_seal(struct schannel_state *state, ZERO_ARRAY(_sealing_key); return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); } + gnutls_cipher_deinit(cipher_hnd); + rc = gnutls_cipher_init(&cipher_hnd, + GNUTLS_CIPHER_ARCFOUR_128, + &sealing_key, + NULL); + if (rc < 0) { + ZERO_ARRAY(_sealing_key); + return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); + } rc = gnutls_cipher_encrypt(cipher_hnd, data, length); diff --git a/selftest/knownfail b/selftest/knownfail index 94b0f014749..7b54b77a708 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -374,4 +374,3 @@ ^samba.tests.ntlmdisabled.python\(ktest\).python2.ntlmdisabled.NtlmDisabledTests.test_samr_change_password\(ktest\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python3.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python2.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) -^samba.unittests.schannel.torture_schannel_seal_rc4 -- 2.17.1 From f5c8dea0ae75e2d24fd3268e2b5b427cb81225c9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Sep 2019 15:15:01 -0700 Subject: [PATCH 253/376] torture:smb2: extend test for File-IDs This now hopefully covers most possible combinations of creating and opening files plus, checking the file's File-ID after every operation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 432202413f4d11d761c62f46a50747fcb9b6f0cf) --- selftest/knownfail.d/samba3.smb2.fileid | 1 + source4/torture/smb2/create.c | 299 ++++++++++++++++++++---- 2 files changed, 259 insertions(+), 41 deletions(-) create mode 100644 selftest/knownfail.d/samba3.smb2.fileid diff --git a/selftest/knownfail.d/samba3.smb2.fileid b/selftest/knownfail.d/samba3.smb2.fileid new file mode 100644 index 00000000000..89455dacdf0 --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.fileid @@ -0,0 +1 @@ +^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index beddefc4c8d..ea83b483491 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -1919,8 +1919,8 @@ static bool test_fileid(struct torture_context *tctx, struct smb2_find f; unsigned int count; union smb_search_data *d; - uint64_t fileid; - uint64_t stream_fileid; + uint64_t expected_fileid; + uint64_t returned_fileid; NTSTATUS status; bool ret = true; @@ -1930,6 +1930,9 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed\n"); + /* + * Initial create with QFID + */ create = (struct smb2_create) { .in.desired_access = SEC_FILE_ALL, .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, @@ -1943,9 +1946,47 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "test file could not be created\n"); h1 = create.out.file.handle; + expected_fileid = BVAL(&create.out.on_disk_id, 0); + + /* + * Getinfo the File-ID on the just opened handle + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Open existing with QFID + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = fname, + .in.query_on_disk_id = true, + }; - fileid = BVAL(&create.out.on_disk_id, 0); + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + /* + * Getinfo the File-ID on the just opened handle + */ finfo = (union smb_fileinfo) { .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, @@ -1954,33 +1995,111 @@ static bool test_fileid(struct torture_context *tctx, status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Overwrite with QFID + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OVERWRITE, + .in.fname = fname, + .in.query_on_disk_id = true, + }; - torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, ret, done, "bad fileid\n"); - f = (struct smb2_find) { - .in.file.handle = testdirh, - .in.pattern = "foo", - .in.max_response_size = 0x1000, - .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + /* + * Getinfo the File-ID on the open with overwrite handle + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, }; - status = smb2_find_level(tree, tree, &f, &count, &d); + status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, - "smb2_find_level failed\n"); + "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); - torture_assert_u64_equal_goto(tctx, - d->id_both_directory_info.file_id, - fileid, + /* + * Do some modifications on the basefile (IO, setinfo), verifying + * File-ID after each step. + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_write failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, ret, done, "bad fileid\n"); + sinfo = (union smb_setfileinfo) { + .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, + .basic_info.in.file.handle = h1, + }; + unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL)); + + status = smb2_setinfo_file(tree, &sinfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_setinfo_file failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + /* + * Create stream, check the stream's File-ID, should be the same as the + * base file (sic!, tested against Windows). + */ create = (struct smb2_create) { .in.desired_access = SEC_FILE_ALL, .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, .in.file_attributes = FILE_ATTRIBUTE_NORMAL, - .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF, + .in.create_disposition = NTCREATEX_DISP_CREATE, .in.fname = sname, .in.query_on_disk_id = true, }; @@ -1989,11 +2108,13 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "test file could not be created\n"); h1 = create.out.file.handle; - - stream_fileid = BVAL(&create.out.on_disk_id, 0); - torture_assert_u64_equal_goto(tctx, stream_fileid, fileid, + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, ret, done, "bad fileid\n"); + /* + * Getinfo the File-ID on the created stream + */ finfo = (union smb_fileinfo) { .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, @@ -2002,31 +2123,118 @@ static bool test_fileid(struct torture_context *tctx, status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Open stream, check the stream's File-ID, should be the same as the + * base file (sic!, tested against Windows). + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = sname, + .in.query_on_disk_id = true, + }; - torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, ret, done, "bad fileid\n"); - f = (struct smb2_find) { - .in.file.handle = testdirh, - .in.pattern = "foo", - .in.max_response_size = 0x1000, - .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, - .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + /* + * Getinfo the File-ID on the opened stream + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, }; - status = smb2_find_level(tree, tree, &f, &count, &d); + status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, - "smb2_find_level failed\n"); + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); - torture_assert_u64_equal_goto(tctx, - d->id_both_directory_info.file_id, - fileid, + /* + * Overwrite stream, check the stream's File-ID, should be the same as + * the base file (sic!, tested against Windows). + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OVERWRITE, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, ret, done, "bad fileid\n"); + /* + * Getinfo the File-ID on the overwritten stream + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Do some modifications on the stream (IO, setinfo), verifying File-ID + * after earch step. + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed\n"); + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + sinfo = (union smb_setfileinfo) { .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, .basic_info.in.file.handle = h1, @@ -2041,16 +2249,17 @@ static bool test_fileid(struct torture_context *tctx, .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, }; - status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed\n"); - - torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, - ret, done, "bad fileid\n"); - smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + /* + * Final open of the basefile with QFID + */ create = (struct smb2_create) { .in.desired_access = SEC_FILE_ALL, .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, @@ -2064,7 +2273,13 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "test file could not be created\n"); h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + /* + * Final Getinfo checking File-ID + */ finfo = (union smb_fileinfo) { .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, @@ -2073,10 +2288,15 @@ static bool test_fileid(struct torture_context *tctx, status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n"); - - torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, ret, done, "bad fileid\n"); + /* + * Final list directory, verifying the operations on basefile and stream + * didn't modify the base file metadata. + */ f = (struct smb2_find) { .in.file.handle = testdirh, .in.pattern = "foo", @@ -2088,14 +2308,11 @@ static bool test_fileid(struct torture_context *tctx, status = smb2_find_level(tree, tree, &f, &count, &d); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed\n"); - torture_assert_u64_equal_goto(tctx, d->id_both_directory_info.file_id, - fileid, + expected_fileid, ret, done, "bad fileid\n"); - smb2_util_close(tree, h1); - done: smb2_util_close(tree, testdirh); smb2_deltree(tree, DNAME); -- 2.17.1 From 2204788e596478d9635f1577ccb7dd76ed66e6a6 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 24 Sep 2019 13:09:03 -0700 Subject: [PATCH 254/376] torture:smb2: add a File-ID test on directories BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 300b47442b023532bd65417fcec04d811f40ef76) --- selftest/knownfail.d/samba3.smb2.fileid | 1 + source4/torture/smb2/create.c | 328 ++++++++++++++++++++++++ 2 files changed, 329 insertions(+) diff --git a/selftest/knownfail.d/samba3.smb2.fileid b/selftest/knownfail.d/samba3.smb2.fileid index 89455dacdf0..bdf86ac61b1 100644 --- a/selftest/knownfail.d/samba3.smb2.fileid +++ b/selftest/knownfail.d/samba3.smb2.fileid @@ -1 +1,2 @@ ^samba3.smb2.fileid.fileid\(nt4_dc\) +^samba3.smb2.fileid.fileid-dir\(nt4_dc\) diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index ea83b483491..aab74f5569a 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -2320,6 +2320,333 @@ done: return ret; } +static bool test_fileid_dir(struct torture_context *tctx, + struct smb2_tree *tree) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + const char *dname = DNAME "\\foo"; + const char *sname = DNAME "\\foo:bar"; + struct smb2_handle testdirh; + struct smb2_handle h1; + struct smb2_create create; + union smb_fileinfo finfo; + union smb_setfileinfo sinfo; + struct smb2_find f; + unsigned int count; + union smb_search_data *d; + uint64_t expected_fileid; + uint64_t returned_fileid; + NTSTATUS status; + bool ret = true; + + smb2_deltree(tree, DNAME); + + status = torture_smb2_testdir(tree, DNAME, &testdirh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir failed\n"); + + /* + * Initial directory create with QFID + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.create_disposition = NTCREATEX_DISP_OPEN_IF, + .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY, + .in.create_options = NTCREATEX_OPTIONS_DIRECTORY, + .in.fname = dname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + expected_fileid = BVAL(&create.out.on_disk_id, 0); + + /* + * Getinfo the File-ID on the just opened handle + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Open existing directory with QFID + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY, + .in.create_options = NTCREATEX_OPTIONS_DIRECTORY, + .in.fname = dname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Getinfo the File-ID on the just opened handle + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Create stream, check the stream's File-ID, should be the same as the + * base file (sic!, tested against Windows). + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_CREATE, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Getinfo the File-ID on the created stream + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Open stream, check the stream's File-ID, should be the same as the + * base file (sic!, tested against Windows). + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Getinfo the File-ID on the opened stream + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Overwrite stream, check the stream's File-ID, should be the same as + * the base file (sic!, tested against Windows). + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OVERWRITE, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Getinfo the File-ID on the overwritten stream + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Do some modifications on the stream (IO, setinfo), verifying File-ID + * after earch step. + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_write failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + sinfo = (union smb_setfileinfo) { + .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, + .basic_info.in.file.handle = h1, + }; + unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL)); + + status = smb2_setinfo_file(tree, &sinfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_setinfo_file failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Final open of the directory with QFID + */ + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY, + .in.create_options = NTCREATEX_OPTIONS_DIRECTORY, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = dname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Final Getinfo checking File-ID + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Final list directory, verifying the operations on basefile and stream + * didn't modify the base file metadata. + */ + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + +done: + smb2_util_close(tree, testdirh); + smb2_deltree(tree, DNAME); + talloc_free(mem_ctx); + return ret; +} + /* basic testing of SMB2 read */ @@ -2366,6 +2693,7 @@ struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx) struct torture_suite *suite = torture_suite_create(ctx, "fileid"); torture_suite_add_1smb2_test(suite, "fileid", test_fileid); + torture_suite_add_1smb2_test(suite, "fileid-dir", test_fileid_dir); suite->description = talloc_strdup(suite, "SMB2-CREATE tests"); -- 2.17.1 From 459acf2728aa0c3bc935227998cdc59ead5a2e7c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Sep 2019 15:15:31 -0700 Subject: [PATCH 255/376] s3:smbd: change the place where we call dos_mode() when processing SMB2_CREATE This is needed for ordinary file or directory opens so the QFID create context response gets the correct File-ID value via dos_mode() from the DOS attributes xattr. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit e1dfaa2b038d91e43d8d34bf1526b7728dba58a5) --- source3/smbd/smb2_create.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 61ed72169fb..66f4aad8c9e 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -1274,6 +1274,9 @@ static void smbd_smb2_create_after_exec(struct tevent_req *req) DEBUG(10, ("smbd_smb2_create_send: " "response construction phase\n")); + state->out_file_attributes = dos_mode(state->result->conn, + state->result->fsp_name); + if (state->mxac != NULL) { NTTIME last_write_time; @@ -1472,8 +1475,6 @@ static void smbd_smb2_create_finish(struct tevent_req *req) state->out_create_action = state->info; } result->op->create_action = state->out_create_action; - state->out_file_attributes = dos_mode(result->conn, - result->fsp_name); state->out_creation_ts = get_create_timespec(smb1req->conn, result, result->fsp_name); -- 2.17.1 From 2d62bd58db9f7c7e72b35ef1c62660107f06b8c9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Sep 2019 15:16:58 -0700 Subject: [PATCH 256/376] s3:smbd: when storing DOS attribute call dos_mode() beforehand This is required to ensure File-ID info is populated with the correct on-disk value, before calling file_set_dosmode() which will update the on-disk value. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 49a754b82d33fb523cda4151a865584ae52a2e2f) --- selftest/knownfail.d/samba3.smb2.fileid | 1 - source3/smbd/open.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/selftest/knownfail.d/samba3.smb2.fileid b/selftest/knownfail.d/samba3.smb2.fileid index bdf86ac61b1..89455dacdf0 100644 --- a/selftest/knownfail.d/samba3.smb2.fileid +++ b/selftest/knownfail.d/samba3.smb2.fileid @@ -1,2 +1 @@ ^samba3.smb2.fileid.fileid\(nt4_dc\) -^samba3.smb2.fileid.fileid-dir\(nt4_dc\) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a5650ac9c2d..7f1f8eae593 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3725,6 +3725,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, /* Overwritten files should be initially set as archive */ if ((info == FILE_WAS_OVERWRITTEN && lp_map_archive(SNUM(conn))) || lp_store_dos_attributes(SNUM(conn))) { + (void)dos_mode(conn, smb_fname); if (!posix_open) { if (file_set_dosmode(conn, smb_fname, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE, -- 2.17.1 From 2da0f65cd911e439d4c033f999a7549bc3610714 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 25 Sep 2019 08:53:29 -0700 Subject: [PATCH 257/376] s3:lib: rework a return expression into an if block Needed to add additional stuff after the if block in the next commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit d7dc85990a177954925644f9ff332b3481a03cc7) --- source3/lib/filename_util.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 8a16bacddbe..6bf29c2b0c9 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -253,7 +253,11 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) return false; } - return smb_fname->stream_name != NULL; + if (smb_fname->stream_name == NULL) { + return false; + } + + return true; } /**************************************************************************** -- 2.17.1 From 2ef4d9883f4b11098e8666143192840a3b574b30 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 25 Sep 2019 10:15:27 -0700 Subject: [PATCH 258/376] s3:lib: assert stream_name is NULL for POSIX paths BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 6c1647ca7a2f68825c34e9ccc18b86ef911e14ac) --- source3/lib/filename_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 6bf29c2b0c9..165adb116b5 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -250,7 +250,7 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) } if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) { - return false; + SMB_ASSERT(smb_fname->stream_name == NULL); } if (smb_fname->stream_name == NULL) { -- 2.17.1 From d7a2e7c33907ece55dad26c75b076aba3facc057 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 25 Sep 2019 10:18:03 -0700 Subject: [PATCH 259/376] s3:lib: factor out stream name asserts to helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit f9fdb8a2a6b9ad0fbb89a9734e81a8b1f527966f) --- source3/lib/filename_util.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 165adb116b5..7b3fab90c46 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -239,10 +239,7 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx, return out; } -/**************************************************************************** - Simple check to determine if the filename is a stream. - ***************************************************************************/ -bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) +static void assert_valid_stream_smb_fname(const struct smb_filename *smb_fname) { /* stream_name must always be NULL if there is no stream. */ if (smb_fname->stream_name) { @@ -252,6 +249,15 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) { SMB_ASSERT(smb_fname->stream_name == NULL); } +} + +/**************************************************************************** + Simple check to determine if the filename is a stream. + ***************************************************************************/ + +bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) +{ + assert_valid_stream_smb_fname(smb_fname); if (smb_fname->stream_name == NULL) { return false; -- 2.17.1 From 23b4938c18a4f51609ca588878f935ef1eb6d9a2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 26 Sep 2019 10:38:06 -0700 Subject: [PATCH 260/376] s3:lib: expand a comment with the function doc for is_ntfs_stream_smb_fname Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 2584b4cdeae3f83962cd11538cd4e441104c8274) --- source3/lib/filename_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 7b3fab90c46..750c0bb8312 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -252,7 +252,8 @@ static void assert_valid_stream_smb_fname(const struct smb_filename *smb_fname) } /**************************************************************************** - Simple check to determine if the filename is a stream. + Simple check to determine if a smb_fname is a real named stream or the + default stream. ***************************************************************************/ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) -- 2.17.1 From 42bc7f28e1a1662f73bce606dbb3b862e399a40d Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 25 Sep 2019 11:19:26 -0700 Subject: [PATCH 261/376] s3:lib: implement logic directly in is_ntfs_default_stream_smb_fname() This allows changing the semantics of is_ntfs_stream_smb_fname() in the next commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 3f8bc1ce3e094f943363921c46803fd5ec9f73bb) --- source3/lib/filename_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 750c0bb8312..ee49ae5ff8c 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -272,7 +272,9 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) ***************************************************************************/ bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname) { - if (!is_ntfs_stream_smb_fname(smb_fname)) { + assert_valid_stream_smb_fname(smb_fname); + + if (smb_fname->stream_name == NULL) { return false; } -- 2.17.1 From c48a5c6b8c995595a519e9069e3efbe24291f190 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 25 Sep 2019 11:29:04 -0700 Subject: [PATCH 262/376] s3:lib: use strequal_m() in is_ntfs_default_stream_smb_fname() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 780a8dcba998471bb154e8bae4391786b793e332) --- source3/lib/filename_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index ee49ae5ff8c..2917481c8bf 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -278,7 +278,7 @@ bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname) return false; } - return strcasecmp_m(smb_fname->stream_name, "::$DATA") == 0; + return strequal_m(smb_fname->stream_name, "::$DATA"); } /**************************************************************************** -- 2.17.1 From 8f44a25e2a630a28d908392603eae5987ec4e91e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 26 Sep 2019 10:05:40 -0700 Subject: [PATCH 263/376] s3:lib: add is_named_stream() Add a new utility functions that checks whether a struct smb_filename points to a real named stream, excluding the default stream "::$DATA". foo -> false foo::$DATA -> false foo:bar -> true foo:bar:$DATA -> true BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 091e3fdab61217251de1cf5111f070ff295d1649) --- source3/include/proto.h | 1 + source3/lib/filename_util.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/source3/include/proto.h b/source3/include/proto.h index ad6f3bbf9c3..cb8890d340b 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -985,6 +985,7 @@ struct smb_filename *cp_smb_filename_nostream(TALLOC_CTX *mem_ctx, const struct smb_filename *in); bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname); bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname); +bool is_named_stream(const struct smb_filename *smb_fname); bool is_invalid_windows_ea_name(const char *name); bool ea_list_has_invalid_name(struct ea_list *ea_list); bool split_stream_filename(TALLOC_CTX *ctx, diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 2917481c8bf..66c07001eba 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -267,6 +267,32 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) return true; } +/**************************************************************************** + Simple check to determine if a smb_fname is pointing to a normal file or + a named stream that is not the default stream "::$DATA". + + foo -> false + foo::$DATA -> false + foo:bar -> true + foo:bar:$DATA -> true + + ***************************************************************************/ + +bool is_named_stream(const struct smb_filename *smb_fname) +{ + assert_valid_stream_smb_fname(smb_fname); + + if (smb_fname->stream_name == NULL) { + return false; + } + + if (strequal_m(smb_fname->stream_name, "::$DATA")) { + return false; + } + + return true; +} + /**************************************************************************** Returns true if the filename's stream == "::$DATA" ***************************************************************************/ -- 2.17.1 From f98033600613e1c26d233063a99d2a7f7207a74f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 24 Sep 2019 12:49:38 -0700 Subject: [PATCH 264/376] s3:smbd: ensure a created stream picks up the File-ID from the basefile BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 90a14c90c4bcede1ef5414e0800aa4c84cbcf1c9) --- selftest/knownfail.d/samba3.smb2.fileid | 1 - source3/smbd/open.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 selftest/knownfail.d/samba3.smb2.fileid diff --git a/selftest/knownfail.d/samba3.smb2.fileid b/selftest/knownfail.d/samba3.smb2.fileid deleted file mode 100644 index 89455dacdf0..00000000000 --- a/selftest/knownfail.d/samba3.smb2.fileid +++ /dev/null @@ -1 +0,0 @@ -^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7f1f8eae593..8586b467d2e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3708,7 +3708,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->initial_delete_on_close = True; } - if (info == FILE_WAS_CREATED) { + if (info == FILE_WAS_CREATED && !is_named_stream(smb_fname)) { smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; if (lp_store_dos_attributes(SNUM(conn)) && -- 2.17.1 From c79e39571910d52cb9336212417f072df82a98b2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 26 Sep 2019 10:41:37 -0700 Subject: [PATCH 265/376] s3:smbd: add a comment explaining the File-ID semantics when a file is created BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit c190f3efa9eb4f633df28074b481ff884b67e65f) --- source3/smbd/open.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8586b467d2e..5524f80af20 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3708,6 +3708,15 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->initial_delete_on_close = True; } + /* + * If we created a file and it's not a stream, this is the point where + * we set the itime (aka invented time) that get's stored in the DOS + * attribute xattr. The value is going to be either what the filesystem + * provided or a copy of the creation date. + * + * Either way, we turn the itime into a File-ID, unless the filesystem + * provided one (unlikely). + */ if (info == FILE_WAS_CREATED && !is_named_stream(smb_fname)) { smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; -- 2.17.1 From 88abbea50659a00a5881ef80ae885914b446d121 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Thu, 3 Oct 2019 13:09:29 +0300 Subject: [PATCH 266/376] spnego: ignore server mech_types list We should not use the mech list sent by the server in the last 'negotiate' packet in CIFS protocol, as it is not protected and may be subject to downgrade attacks. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- auth/gensec/spnego.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index 0b3fbdce7ac..dc73e324d99 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -511,7 +511,11 @@ static NTSTATUS gensec_spnego_client_negTokenInit_start( } n->mech_idx = 0; - n->mech_types = spnego_in->negTokenInit.mechTypes; + + /* Do not use server mech list as it isn't protected. Instead, get all + * supported mechs (excluding SPNEGO). */ + n->mech_types = gensec_security_oids(gensec_security, n, + GENSEC_OID_SPNEGO); if (n->mech_types == NULL) { return NT_STATUS_INVALID_PARAMETER; } @@ -658,13 +662,30 @@ static NTSTATUS gensec_spnego_client_negTokenInit_finish( DATA_BLOB *out) { struct spnego_data spnego_out; - const char *my_mechs[] = {NULL, NULL}; + const char * const *mech_types = NULL; bool ok; - my_mechs[0] = spnego_state->neg_oid; + if (n->mech_types == NULL) { + DBG_WARNING("No mech_types list\n"); + return NT_STATUS_INVALID_PARAMETER; + } + + for (mech_types = n->mech_types; *mech_types != NULL; mech_types++) { + int cmp = strcmp(*mech_types, spnego_state->neg_oid); + + if (cmp == 0) { + break; + } + } + + if (*mech_types == NULL) { + DBG_ERR("Can't find selected sub mechanism in mech_types\n"); + return NT_STATUS_INVALID_PARAMETER; + } + /* compose reply */ spnego_out.type = SPNEGO_NEG_TOKEN_INIT; - spnego_out.negTokenInit.mechTypes = my_mechs; + spnego_out.negTokenInit.mechTypes = mech_types; spnego_out.negTokenInit.reqFlags = data_blob_null; spnego_out.negTokenInit.reqFlagsPadding = 0; spnego_out.negTokenInit.mechListMIC = data_blob_null; @@ -676,7 +697,7 @@ static NTSTATUS gensec_spnego_client_negTokenInit_finish( } ok = spnego_write_mech_types(spnego_state, - my_mechs, + mech_types, &spnego_state->mech_types); if (!ok) { DBG_ERR("failed to write mechTypes\n"); -- 2.17.1 From 5a6fed646c6e8f679bcd2fc285406933f518146e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 10 Oct 2019 16:18:21 +0200 Subject: [PATCH 267/376] s3:libsmb: Do not check the SPNEGO neg token for KRB5 The list is not protected and this could be a downgrade attack. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Pair-Programmed-With: Isaac Boukris Reviewed-by: Andreas Schneider Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Reviewed-by: Stefan Metzmacher --- source3/libsmb/cliconnect.c | 50 ------------------------------------- 1 file changed, 50 deletions(-) diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 94cec062881..3df35931bb6 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -232,8 +232,6 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, char *canon_principal = NULL; char *canon_realm = NULL; const char *target_hostname = NULL; - const DATA_BLOB *server_blob = NULL; - bool got_kerberos_mechanism = false; enum credentials_use_kerberos krb5_state; bool try_kerberos = false; bool need_kinit = false; @@ -242,48 +240,6 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, bool ok; target_hostname = smbXcli_conn_remote_name(cli->conn); - server_blob = smbXcli_conn_server_gss_blob(cli->conn); - - /* the server might not even do spnego */ - if (server_blob != NULL && server_blob->length != 0) { - char *OIDs[ASN1_MAX_OIDS] = { NULL, }; - size_t i; - - /* - * The server sent us the first part of the SPNEGO exchange in the - * negprot reply. It is WRONG to depend on the principal sent in the - * negprot reply, but right now we do it. If we don't receive one, - * we try to best guess, then fall back to NTLM. - */ - ok = spnego_parse_negTokenInit(frame, - *server_blob, - OIDs, - NULL, - NULL); - if (!ok) { - TALLOC_FREE(frame); - return NT_STATUS_INVALID_PARAMETER; - } - if (OIDs[0] == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_INVALID_PARAMETER; - } - - /* make sure the server understands kerberos */ - for (i = 0; OIDs[i] != NULL; i++) { - if (i == 0) { - DEBUG(3,("got OID=%s\n", OIDs[i])); - } else { - DEBUGADD(3,("got OID=%s\n", OIDs[i])); - } - - if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 || - strcmp(OIDs[i], OID_KERBEROS5) == 0) { - got_kerberos_mechanism = true; - break; - } - } - } auth_requested = cli_credentials_authentication_requested(creds); if (auth_requested) { @@ -333,12 +289,6 @@ NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli, need_kinit = false; } else if (krb5_state == CRED_MUST_USE_KERBEROS) { need_kinit = try_kerberos; - } else if (!got_kerberos_mechanism) { - /* - * Most likely the server doesn't support - * Kerberos, don't waste time doing a kinit - */ - need_kinit = false; } else { need_kinit = try_kerberos; } -- 2.17.1 From 7e40d859283100791602c2504005f7c99ec86996 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 7 Oct 2019 23:51:19 +0300 Subject: [PATCH 268/376] selftest: s3: add a test for spnego downgrade from krb5 to ntlm BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- selftest/knownfail.d/spnego_downgrade | 1 + selftest/target/Samba3.pm | 9 +++++ source3/script/tests/test_smbd_no_krb5.sh | 46 +++++++++++++++++++++++ source3/selftest/tests.py | 4 ++ 4 files changed, 60 insertions(+) create mode 100644 selftest/knownfail.d/spnego_downgrade create mode 100755 source3/script/tests/test_smbd_no_krb5.sh diff --git a/selftest/knownfail.d/spnego_downgrade b/selftest/knownfail.d/spnego_downgrade new file mode 100644 index 00000000000..494a55fd43d --- /dev/null +++ b/selftest/knownfail.d/spnego_downgrade @@ -0,0 +1 @@ +^samba3.blackbox.smbd_no_krb5.test_spnego_downgrade diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 32bd8698df2..b6bfcef824d 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1608,6 +1608,7 @@ sub provision($$$$$$$$$) my $dfqconffile="$libdir/dfq.conf"; my $errorinjectconf="$libdir/error_inject.conf"; my $delayinjectconf="$libdir/delay_inject.conf"; + my $globalinjectconf="$libdir/global_inject.conf"; my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/third_party/nss_wrapper/nss_wrapper.pl"; my $nss_wrapper_passwd = "$privatedir/passwd"; @@ -1796,6 +1797,8 @@ sub provision($$$$$$$$$) #it just means we ALLOW one to be configured. allow insecure wide links = yes + include = $globalinjectconf + # Begin extra options $extra_options # End extra options @@ -2331,6 +2334,12 @@ sub provision($$$$$$$$$) } close(DFQCONF); + unless (open(DELAYCONF, ">$globalinjectconf")) { + warn("Unable to open $globalinjectconf"); + return undef; + } + close(DELAYCONF); + ## ## create a test account ## diff --git a/source3/script/tests/test_smbd_no_krb5.sh b/source3/script/tests/test_smbd_no_krb5.sh new file mode 100755 index 00000000000..e9dbb4ae80e --- /dev/null +++ b/source3/script/tests/test_smbd_no_krb5.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then +cat < $global_inject_conf + +# verify that kerberos fails +test_smbclient_expect_failure "smbd_no_krb5" "ls" "//$SERVER/tmp" -k $opt || failed=`expr $failed + 1` + +# verify downgrade to ntlmssp +test_smbclient "test_spnego_downgrade" "ls" "//$SERVER/tmp" $opt || failed=`expr $failed + 1` + +echo '' > $global_inject_conf + +testok $0 $failed diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 5b5a1978988..93c41ef956d 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -751,6 +751,10 @@ plantestsuite("samba3.blackbox.net_tdb", "simpleserver:local", plantestsuite("samba3.blackbox.smbd_error", "simpleserver:local", [os.path.join(samba3srcdir, "script/tests/test_smbd_error.sh")]) +plantestsuite("samba3.blackbox.smbd_no_krb5", "ad_member:local", + [os.path.join(samba3srcdir, "script/tests/test_smbd_no_krb5.sh"), + smbclient3, '$SERVER', "$DC_USERNAME", "$DC_PASSWORD", "$PREFIX"]) + plantestsuite("samba3.blackbox.durable_v2_delay", "simpleserver:local", [os.path.join(samba3srcdir, "script/tests/test_durable_handle_reconnect.sh")]) -- 2.17.1 From 27982255d6454841d3d17c8de3b3d4eac9d84adb Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 4 Sep 2019 16:31:21 +0300 Subject: [PATCH 269/376] spnego: add client option to omit sending an optimistic token BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- auth/gensec/spnego.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index dc73e324d99..97472c26837 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -136,6 +136,7 @@ struct spnego_state { bool done_mic_check; bool simulate_w2k; + bool no_optimistic; /* * The following is used to implement @@ -187,6 +188,10 @@ static NTSTATUS gensec_spnego_client_start(struct gensec_security *gensec_securi spnego_state->simulate_w2k = gensec_setting_bool(gensec_security->settings, "spnego", "simulate_w2k", false); + spnego_state->no_optimistic = gensec_setting_bool(gensec_security->settings, + "spnego", + "client_no_optimistic", + false); gensec_security->private_data = spnego_state; return NT_STATUS_OK; @@ -1944,6 +1949,12 @@ static void gensec_spnego_update_pre(struct tevent_req *req) * blob and NT_STATUS_OK. */ state->sub.status = NT_STATUS_OK; + } else if (spnego_state->state_position == SPNEGO_CLIENT_START && + spnego_state->no_optimistic) { + /* + * Skip optimistic token per conf. + */ + state->sub.status = NT_STATUS_MORE_PROCESSING_REQUIRED; } else { /* * MORE_PROCESSING_REQUIRED => -- 2.17.1 From 425ac58f58c999007f740ca0362269977d1380e4 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 4 Sep 2019 16:39:43 +0300 Subject: [PATCH 270/376] selftest: add tests for no optimistic spnego exchange BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- selftest/knownfail.d/spnego_no_optimistic | 1 + source4/selftest/tests.py | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 selftest/knownfail.d/spnego_no_optimistic diff --git a/selftest/knownfail.d/spnego_no_optimistic b/selftest/knownfail.d/spnego_no_optimistic new file mode 100644 index 00000000000..54f51446be0 --- /dev/null +++ b/selftest/knownfail.d/spnego_no_optimistic @@ -0,0 +1 @@ +^samba4.smb.spnego.*.no_optimistic diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 3f55649f217..1772611eb53 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -547,6 +547,10 @@ plansmbtorture4testsuite('base.xcopy', "ad_dc_ntvfs", ['//$NETBIOSNAME/xcopy_sha plansmbtorture4testsuite('base.xcopy', "ad_dc_ntvfs", ['//$NETBIOSNAME/xcopy_share', '-k', 'no', '--signing=required', '-U%'], modname="samba4.smb.signing --signing=required anon") plansmbtorture4testsuite('base.xcopy', "s4member", ['//$NETBIOSNAME/xcopy_share', '-k', 'no', '--signing=no', '-U%'], modname="samba4.smb.signing --signing=no anon") +# Test SPNEGO without issuing an optimistic token +opt='--option=spnego:client_no_optimistic=yes' +plansmbtorture4testsuite('base.xcopy', "ad_dc", ['//$NETBIOSNAME/xcopy_share', '-U$USERNAME%$PASSWORD', opt, '-k', 'no'], modname="samba4.smb.spnego.ntlmssp.no_optimistic") +plansmbtorture4testsuite('base.xcopy', "ad_dc", ['//$NETBIOSNAME/xcopy_share', '-U$USERNAME%$PASSWORD', opt, '-k', 'yes'], modname="samba4.smb.spnego.krb5.no_optimistic") wb_opts_default = ["--option=\"torture:strict mode=no\"", "--option=\"torture:timelimit=1\"", "--option=\"torture:winbindd_separator=/\"", "--option=\"torture:winbindd_netbios_name=$SERVER\"", "--option=\"torture:winbindd_netbios_domain=$DOMAIN\""] -- 2.17.1 From 9c4cb9ba9568e9ba0589f041959e71bb496313dd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Oct 2019 13:23:17 +0200 Subject: [PATCH 271/376] python/tests/gensec: make it possible to add knownfail tests for gensec.update() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- python/samba/tests/gensec.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/gensec.py b/python/samba/tests/gensec.py index b5ce51de756..c9056ef9681 100644 --- a/python/samba/tests/gensec.py +++ b/python/samba/tests/gensec.py @@ -79,10 +79,16 @@ class GensecTests(samba.tests.TestCase): while True: if not client_finished: print("running client gensec_update") - (client_finished, client_to_server) = self.gensec_client.update(server_to_client) + try: + (client_finished, client_to_server) = self.gensec_client.update(server_to_client) + except samba.NTSTATUSError as nt: + raise AssertionError(nt) if not server_finished: print("running server gensec_update") - (server_finished, server_to_client) = self.gensec_server.update(client_to_server) + try: + (server_finished, server_to_client) = self.gensec_server.update(client_to_server) + except samba.NTSTATUSError as nt: + raise AssertionError(nt) if client_finished and server_finished: break -- 2.17.1 From f3a02fdf780578194d4ad722ebd822a04a2dd886 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Fri, 11 Oct 2019 00:20:16 +0300 Subject: [PATCH 272/376] python/tests/gensec: add spnego downgrade python tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Pair-Programmed-With: Andreas Schneider Signed-off-by: Isaac Boukris Signed-off-by: Andreas Schneider Reviewed-by: Stefan Metzmacher --- python/samba/tests/gensec.py | 24 +++++++++++++++++++++++- selftest/knownfail.d/samba.tests.gensec | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 selftest/knownfail.d/samba.tests.gensec diff --git a/python/samba/tests/gensec.py b/python/samba/tests/gensec.py index c9056ef9681..47bb6c82a01 100644 --- a/python/samba/tests/gensec.py +++ b/python/samba/tests/gensec.py @@ -47,11 +47,17 @@ class GensecTests(samba.tests.TestCase): def test_info_uninitialized(self): self.assertRaises(RuntimeError, self.gensec.session_info) - def _test_update(self, mech, client_mech=None): + def _test_update(self, mech, client_mech=None, client_only_opt=None): """Test GENSEC by doing an exchange with ourselves using GSSAPI against a KDC""" """Start up a client and server GENSEC instance to test things with""" + if client_only_opt: + orig_client_opt = self.lp_ctx.get(client_only_opt) + if not orig_client_opt: + orig_client_opt = '' + self.lp_ctx.set(client_only_opt, "yes") + self.gensec_client = gensec.Security.start_client(self.settings) self.gensec_client.set_credentials(self.get_credentials()) self.gensec_client.want_feature(gensec.FEATURE_SEAL) @@ -60,6 +66,9 @@ class GensecTests(samba.tests.TestCase): else: self.gensec_client.start_mech_by_sasl_name(mech) + if client_only_opt: + self.lp_ctx.set(client_only_opt, "no") + self.gensec_server = gensec.Security.start_server(settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx)) creds = Credentials() @@ -78,11 +87,15 @@ class GensecTests(samba.tests.TestCase): """Run the actual call loop""" while True: if not client_finished: + if client_only_opt: + self.lp_ctx.set(client_only_opt, "yes") print("running client gensec_update") try: (client_finished, client_to_server) = self.gensec_client.update(server_to_client) except samba.NTSTATUSError as nt: raise AssertionError(nt) + if client_only_opt: + self.lp_ctx.set(client_only_opt, "no") if not server_finished: print("running server gensec_update") try: @@ -93,6 +106,9 @@ class GensecTests(samba.tests.TestCase): if client_finished and server_finished: break + if client_only_opt: + self.lp_ctx.set(client_only_opt, orig_client_opt) + self.assertTrue(server_finished) self.assertTrue(client_finished) @@ -121,6 +137,12 @@ class GensecTests(samba.tests.TestCase): def test_update_spnego(self): self._test_update("GSS-SPNEGO") + def test_update_spnego_downgrade(self): + self._test_update("GSS-SPNEGO", "spnego", "gensec:gssapi_krb5") + + def test_update_no_optimistic_spnego(self): + self._test_update("GSS-SPNEGO", "spnego", "spnego:client_no_optimistic") + def test_update_w2k_spnego_client(self): self.lp_ctx.set("spnego:simulate_w2k", "yes") diff --git a/selftest/knownfail.d/samba.tests.gensec b/selftest/knownfail.d/samba.tests.gensec new file mode 100644 index 00000000000..afc9eba9af5 --- /dev/null +++ b/selftest/knownfail.d/samba.tests.gensec @@ -0,0 +1,2 @@ +^samba.tests.gensec.samba.tests.gensec.GensecTests.test_update_no_optimistic_spnego +^samba.tests.gensec.samba.tests.gensec.GensecTests.test_update_spnego_downgrade -- 2.17.1 From 0d292ca72a389010306e79e7f782783b452cc603 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 4 Sep 2019 17:04:12 +0300 Subject: [PATCH 273/376] spnego: fix server handling of no optimistic exchange BUG: https://bugzilla.samba.org/show_bug.cgi?id=14106 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Sat Oct 12 15:51:42 UTC 2019 on sn-devel-184 --- auth/gensec/spnego.c | 13 +++++++++++++ selftest/knownfail.d/samba.tests.gensec | 2 -- selftest/knownfail.d/spnego_downgrade | 1 - selftest/knownfail.d/spnego_no_optimistic | 1 - 4 files changed, 13 insertions(+), 4 deletions(-) delete mode 100644 selftest/knownfail.d/samba.tests.gensec delete mode 100644 selftest/knownfail.d/spnego_downgrade delete mode 100644 selftest/knownfail.d/spnego_no_optimistic diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index 97472c26837..ddbe03c5d6b 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -1321,6 +1321,10 @@ static NTSTATUS gensec_spnego_server_negTokenInit_step( spnego_state->mic_requested = true; } + if (sub_in.length == 0) { + spnego_state->no_optimistic = true; + } + /* * Note that 'cur_sec' is temporary memory, but * cur_sec->oid points to a const string in the @@ -1955,6 +1959,15 @@ static void gensec_spnego_update_pre(struct tevent_req *req) * Skip optimistic token per conf. */ state->sub.status = NT_STATUS_MORE_PROCESSING_REQUIRED; + } else if (spnego_state->state_position == SPNEGO_SERVER_START && + state->sub.in.length == 0 && spnego_state->no_optimistic) { + /* + * If we didn't like the mechanism for which the client sent us + * an optimistic token, or if he didn't send any, don't call + * the sub mechanism just yet. + */ + state->sub.status = NT_STATUS_MORE_PROCESSING_REQUIRED; + spnego_state->no_optimistic = false; } else { /* * MORE_PROCESSING_REQUIRED => diff --git a/selftest/knownfail.d/samba.tests.gensec b/selftest/knownfail.d/samba.tests.gensec deleted file mode 100644 index afc9eba9af5..00000000000 --- a/selftest/knownfail.d/samba.tests.gensec +++ /dev/null @@ -1,2 +0,0 @@ -^samba.tests.gensec.samba.tests.gensec.GensecTests.test_update_no_optimistic_spnego -^samba.tests.gensec.samba.tests.gensec.GensecTests.test_update_spnego_downgrade diff --git a/selftest/knownfail.d/spnego_downgrade b/selftest/knownfail.d/spnego_downgrade deleted file mode 100644 index 494a55fd43d..00000000000 --- a/selftest/knownfail.d/spnego_downgrade +++ /dev/null @@ -1 +0,0 @@ -^samba3.blackbox.smbd_no_krb5.test_spnego_downgrade diff --git a/selftest/knownfail.d/spnego_no_optimistic b/selftest/knownfail.d/spnego_no_optimistic deleted file mode 100644 index 54f51446be0..00000000000 --- a/selftest/knownfail.d/spnego_no_optimistic +++ /dev/null @@ -1 +0,0 @@ -^samba4.smb.spnego.*.no_optimistic -- 2.17.1 From c191a37848ba01f503ee5fc5000d4ea1a1474500 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 9 Oct 2019 20:11:03 +0200 Subject: [PATCH 274/376] lib:krb5_wrap: Do not create a temporary file for MEMORY keytabs The autobuild cleanup script fails with: The tree has 3 new uncommitted files!!! git clean -n Would remove MEMORY:tmp_smb_creds_SK98Lv Would remove MEMORY:tmp_smb_creds_kornU6 Would remove MEMORY:tmp_smb_creds_ljR828 Signed-off-by: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit d888655244b4d8ec7a69a042e0ff3c074585b0de) --- lib/krb5_wrap/krb5_samba.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index a4e73c64f00..5aceae44eec 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -2002,26 +2002,23 @@ krb5_error_code smb_krb5_kinit_keyblock_ccache(krb5_context ctx, krb_options); #elif defined(HAVE_KRB5_GET_INIT_CREDS_KEYTAB) { -#define SMB_CREDS_KEYTAB "MEMORY:tmp_smb_creds_XXXXXX" - char tmp_name[sizeof(SMB_CREDS_KEYTAB)]; +#define SMB_CREDS_KEYTAB "MEMORY:tmp_kinit_keyblock_ccache" + char tmp_name[64] = {0}; krb5_keytab_entry entry; krb5_keytab keytab; - int tmpfd; - mode_t mask; + int rc; memset(&entry, 0, sizeof(entry)); entry.principal = principal; *(KRB5_KT_KEY(&entry)) = *keyblock; - memcpy(tmp_name, SMB_CREDS_KEYTAB, sizeof(SMB_CREDS_KEYTAB)); - mask = umask(S_IRWXO | S_IRWXG); - tmpfd = mkstemp(tmp_name); - umask(mask); - if (tmpfd == -1) { - DBG_ERR("Failed to mkstemp %s\n", tmp_name); + rc = snprintf(tmp_name, sizeof(tmp_name), + "%s-%p", + SMB_CREDS_KEYTAB, + &my_creds); + if (rc < 0) { return KRB5_KT_BADNAME; } - close(tmpfd); code = krb5_kt_resolve(ctx, tmp_name, &keytab); if (code) { return code; -- 2.17.1 From 41e658f446adaf4a373ece4fbb1d009a69a293dc Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 9 Oct 2019 16:32:47 +0200 Subject: [PATCH 275/376] s3:libads: Do not turn on canonicalization flag for MIT Kerberos This partially reverts 303b7e59a286896888ee2473995fc50bb2b5ce5e. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14155 Pair-Programmed-With: Isaac Boukris Signed-off-by: Andreas Schneider Signed-off-by: Isaac Boukris Reviewed-by: Stefan Metzmacher (cherry picked from commit 123584294cfd153acc2d9a5be9d71c395c847a25) --- source3/libads/krb5_setpw.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 67bc2f4640d..028b0dcfa65 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -207,7 +207,22 @@ static ADS_STATUS ads_krb5_chg_password(const char *kdc_host, krb5_get_init_creds_opt_set_win2k(context, opts, true); krb5_get_init_creds_opt_set_canonicalize(context, opts, true); #else /* MIT */ +#if 0 + /* + * FIXME + * + * Due to an upstream MIT Kerberos bug, this feature is not + * not working. Affection versions (2019-10-09): <= 1.17 + * + * Reproducer: + * kinit -C aDmInIsTrAtOr@ACME.COM -S kadmin/changepw@ACME.COM + * + * This is NOT a problem if the service is a krbtgt. + * + * https://bugzilla.samba.org/show_bug.cgi?id=14155 + */ krb5_get_init_creds_opt_set_canonicalize(opts, true); +#endif #endif /* MIT */ /* note that heimdal will fill in the local addresses if the addresses -- 2.17.1 From 6902275b6f3c337a4ba5d1fea3f1e0f81fa34a4a Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Tue, 15 Oct 2019 13:52:42 +0300 Subject: [PATCH 276/376] nsswitch: Link stress-nss-libwbclient against pthread BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit d473f1e38c2822746030516269b4d70032cf9b2e) --- nsswitch/wscript_build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 6acc4a19b9b..861ed2f23bf 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -20,7 +20,7 @@ bld.SAMBA_BINARY('nsstest', if bld.CONFIG_SET('HAVE_PTHREAD'): bld.SAMBA_BINARY('stress-nss-libwbclient', source='stress-nss-libwbclient.c', - deps='wbclient', + deps='wbclient pthread', install=False ) -- 2.17.1 From 7f5334a92c4a378f88c0ee8c5fde46dd087a9dc0 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Tue, 15 Oct 2019 17:01:48 +0300 Subject: [PATCH 277/376] s3:libsmb: Link libsmb against pthread BUG: https://bugzilla.samba.org/show_bug.cgi?id=14140 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Alexander Bokovoy (cherry picked from commit 7259197bf716f8b81dea74beefe6ee3b1239f172) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Oct 16 20:39:04 UTC 2019 on sn-devel-184 --- source3/libsmb/wscript | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/libsmb/wscript b/source3/libsmb/wscript index d9e933e9e9f..febff9df7fc 100644 --- a/source3/libsmb/wscript +++ b/source3/libsmb/wscript @@ -16,6 +16,7 @@ def build(bld): libsmb_xattr.c libsmb_setget.c''', public_deps=''' + pthread talloc smbconf libsmb -- 2.17.1 From ad617f2f2944b25528e947c09fc86dcd2b62cf70 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 18 Oct 2019 11:02:06 +0200 Subject: [PATCH 278/376] WHATSNEW: Add release notes for Samba 4.11.1. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index d573bb65819..2e61702b71b 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,89 @@ + ============================== + Release Notes for Samba 4.11.1 + October 18, 2019 + ============================== + + +This is the latest stable release of the Samba 4.11 release series. + + +Changes since 4.11.0: +--------------------- + +o Michael Adam + * BUG 14141: getpwnam and getpwuid need to return data for ID_TYPE_BOTH + group. + +o Jeremy Allison + * BUG 14094: smbc_readdirplus() is incompatible with smbc_telldir() and + smbc_lseekdir(). + * BUG 14152: s3: smbclient: Stop an SMB2-connection from blundering into + SMB1-specific calls. + +o Ralph Boehme + * BUG 14137: Fix stale file handle error when using mkstemp on a share. + +o Isaac Boukris + * BUG 14106: Fix spnego fallback from kerberos to ntlmssp in smbd server. + * BUG 14140: Overlinking libreplace against librt and pthread against every + binary or library causes issues. + +o Günther Deschner + * BUG 14130: s3-winbindd: Fix forest trusts with additional trust attributes. + * BUG 14134: auth/gensec: Fix non-AES schannel seal. + +o Amitay Isaacs + * BUG 14147: Deleted records can be resurrected during recovery. + +o Björn Jacke + * BUG 14136: Fix uncaught exception in classicupgrade. + * BUG 14139: fault.c: Improve fault_report message text pointing to our wiki. + +o Bryan Mason + * BUG 14128: s3:client: Use DEVICE_URI, instead of argv[0], for Device URI. + +o Stefan Metzmacher + * BUG 14124: pam_winbind with krb5_auth or wbinfo -K doesn't work for users + of trusted domains/forests. + +o Mathieu Parent + * BUG 14131: Remove 'pod2man' as it is no longer needed. + +o Andreas Schneider + * BUG 13884: Joining Active Directory should not use SAMR to set the + password. + * BUG 14140: Overlinking libreplace against librt and pthread against every + binary or library causes issues. + * BUG 14155: 'kpasswd' fails when built with MIT Kerberos. + +o Martin Schwenke + * BUG 14129: Exit code of ctdb nodestatus should not be influenced by deleted + nodes. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the "Samba 4.1 and newer" product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + ============================== Release Notes for Samba 4.11.0 September 17, 2019 -- 2.17.1 From be4cb417135af09fcf076a92bc8b7e02310a2383 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 18 Oct 2019 11:02:36 +0200 Subject: [PATCH 279/376] VERSION: Disable GIT_SNAPSHOT for Samba 4.11.1. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 137edf08bba..61c76acaef7 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 7b8309398beab679cd4068da497661ce33616edc Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 18 Oct 2019 11:03:16 +0200 Subject: [PATCH 280/376] VERSION: Bump version up to 4.11.2... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 61c76acaef7..fbc941686eb 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=1 +SAMBA_VERSION_RELEASE=2 ######################################################## # If a official release has a serious bug # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 193d6f5e8cc074370bafa282218e1991506a9edc Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 18 Oct 2019 11:03:16 +0200 Subject: [PATCH 281/376] VERSION: Bump version up to 4.11.2... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger (cherry picked from commit 7b8309398beab679cd4068da497661ce33616edc) --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 61c76acaef7..fbc941686eb 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=1 +SAMBA_VERSION_RELEASE=2 ######################################################## # If a official release has a serious bug # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 07df3dfa6bf081c3f2ad7777995325d834ad3129 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Aug 2019 13:39:53 -0700 Subject: [PATCH 282/376] CVE-2019-10218 - s3: libsmb: Protect SMB1 client code from evil server returned names. Disconnect with NT_STATUS_INVALID_NETWORK_RESPONSE if so. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14071 Signed-off-by: Jeremy Allison --- source3/libsmb/clilist.c | 75 ++++++++++++++++++++++++++++++++++++++++ source3/libsmb/proto.h | 3 ++ 2 files changed, 78 insertions(+) diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index 5cb1fce4338..4f518339e2b 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -24,6 +24,66 @@ #include "trans2.h" #include "../libcli/smb/smbXcli_base.h" +/**************************************************************************** + Check if a returned directory name is safe. +****************************************************************************/ + +static NTSTATUS is_bad_name(bool windows_names, const char *name) +{ + const char *bad_name_p = NULL; + + bad_name_p = strchr(name, '/'); + if (bad_name_p != NULL) { + /* + * Windows and POSIX names can't have '/'. + * Server is attacking us. + */ + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + if (windows_names) { + bad_name_p = strchr(name, '\\'); + if (bad_name_p != NULL) { + /* + * Windows names can't have '\\'. + * Server is attacking us. + */ + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + } + return NT_STATUS_OK; +} + +/**************************************************************************** + Check if a returned directory name is safe. Disconnect if server is + sending bad names. +****************************************************************************/ + +NTSTATUS is_bad_finfo_name(const struct cli_state *cli, + const struct file_info *finfo) +{ + NTSTATUS status = NT_STATUS_OK; + bool windows_names = true; + + if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) { + windows_names = false; + } + if (finfo->name != NULL) { + status = is_bad_name(windows_names, finfo->name); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("bad finfo->name\n"); + return status; + } + } + if (finfo->short_name != NULL) { + status = is_bad_name(windows_names, finfo->short_name); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("bad finfo->short_name\n"); + return status; + } + } + return NT_STATUS_OK; +} + /**************************************************************************** Calculate a safe next_entry_offset. ****************************************************************************/ @@ -492,6 +552,13 @@ static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, TALLOC_FREE(finfo); return NT_STATUS_NO_MEMORY; } + + status = is_bad_finfo_name(state->cli, finfo); + if (!NT_STATUS_IS_OK(status)) { + smbXcli_conn_disconnect(state->cli->conn, status); + TALLOC_FREE(finfo); + return status; + } } *pfinfo = finfo; return NT_STATUS_OK; @@ -727,6 +794,14 @@ static void cli_list_trans_done(struct tevent_req *subreq) ff_eos = true; break; } + + status = is_bad_finfo_name(state->cli, finfo); + if (!NT_STATUS_IS_OK(status)) { + smbXcli_conn_disconnect(state->cli->conn, status); + tevent_req_nterror(req, status); + return; + } + if (!state->first && (state->mask[0] != '\0') && strcsequal(finfo->name, state->mask)) { DEBUG(1, ("Error: Looping in FIND_NEXT as name %s has " diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h index 6a647da58c8..48855d7112c 100644 --- a/source3/libsmb/proto.h +++ b/source3/libsmb/proto.h @@ -760,6 +760,9 @@ NTSTATUS cli_posix_whoami(struct cli_state *cli, /* The following definitions come from libsmb/clilist.c */ +NTSTATUS is_bad_finfo_name(const struct cli_state *cli, + const struct file_info *finfo); + NTSTATUS cli_list_old(struct cli_state *cli,const char *Mask,uint16_t attribute, NTSTATUS (*fn)(const char *, struct file_info *, const char *, void *), void *state); -- 2.17.1 From 914c985e66adc63d54b3e17dab324f376f84e349 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Aug 2019 12:08:09 -0700 Subject: [PATCH 283/376] CVE-2019-10218 - s3: libsmb: Protect SMB2 client code from evil server returned names. Disconnect with NT_STATUS_INVALID_NETWORK_RESPONSE if so. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14071 Signed-off-by: Jeremy Allison --- source3/libsmb/cli_smb2_fnum.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index 535beaab841..3fa322c243b 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -1442,6 +1442,13 @@ NTSTATUS cli_smb2_list(struct cli_state *cli, goto fail; } + /* Protect against server attack. */ + status = is_bad_finfo_name(cli, finfo); + if (!NT_STATUS_IS_OK(status)) { + smbXcli_conn_disconnect(cli->conn, status); + goto fail; + } + if (dir_check_ftype((uint32_t)finfo->mode, (uint32_t)attribute)) { /* -- 2.17.1 From e0e8830b88e45e3e954b1e5074cef8c8bf5406a8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 19 Sep 2019 11:50:01 +1200 Subject: [PATCH 284/376] CVE-2019-14833: Use utf8 characters in the unacceptable password This shows that the "check password script" handling has a bug. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12438 Signed-off-by: Andrew Bartlett --- selftest/knownfail.d/unacceptable-passwords | 1 + selftest/target/Samba4.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 selftest/knownfail.d/unacceptable-passwords diff --git a/selftest/knownfail.d/unacceptable-passwords b/selftest/knownfail.d/unacceptable-passwords new file mode 100644 index 00000000000..75fa2fc32b8 --- /dev/null +++ b/selftest/knownfail.d/unacceptable-passwords @@ -0,0 +1 @@ +^samba.tests.samba_tool.user_check_password_script.samba.tests.samba_tool.user_check_password_script.UserCheckPwdTestCase.test_checkpassword_unacceptable\(chgdcpass:local\) \ No newline at end of file diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 02cdfc18bad..195e9b88044 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1993,7 +1993,7 @@ sub provision_chgdcpass($$) print "PROVISIONING CHGDCPASS...\n"; # This environment disallows the use of this password # (and also removes the default AD complexity checks) - my $unacceptable_password = "widk3Dsle32jxdBdskldsk55klASKQ"; + my $unacceptable_password = "Paßßword-widk3Dsle32jxdBdskldsk55klASKQ"; my $extra_smb_conf = " check password script = $self->{srcdir}/selftest/checkpassword_arg1.sh ${unacceptable_password} allow dcerpc auth level connect:lsarpc = yes -- 2.17.1 From b3a71bf847e3797582a2c657720726694fe424ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Baumbach?= Date: Tue, 6 Aug 2019 16:32:32 +0200 Subject: [PATCH 285/376] CVE-2019-14833 dsdb: send full password to check password script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit utf8_len represents the number of characters (not bytes) of the password. If the password includes multi-byte characters it is required to write the total number of bytes to the check password script. Otherwise the last bytes of the password string would be ignored. Therefore we rename utf8_len to be clear what it does and does not represent. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12438 Signed-off-by: Björn Baumbach Signed-off-by: Andrew Bartlett --- selftest/knownfail.d/unacceptable-passwords | 1 - source4/dsdb/common/util.c | 30 ++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) delete mode 100644 selftest/knownfail.d/unacceptable-passwords diff --git a/selftest/knownfail.d/unacceptable-passwords b/selftest/knownfail.d/unacceptable-passwords deleted file mode 100644 index 75fa2fc32b8..00000000000 --- a/selftest/knownfail.d/unacceptable-passwords +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.samba_tool.user_check_password_script.samba.tests.samba_tool.user_check_password_script.UserCheckPwdTestCase.test_checkpassword_unacceptable\(chgdcpass:local\) \ No newline at end of file diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index e521ed09999..3ebec827404 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -2036,21 +2036,36 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx, const uint32_t pwdProperties, const uint32_t minPwdLength) { - const char *utf8_pw = (const char *)utf8_blob->data; - size_t utf8_len = strlen_m(utf8_pw); char *password_script = NULL; + const char *utf8_pw = (const char *)utf8_blob->data; + + /* + * This looks strange because it is. + * + * The check for the number of characters in the password + * should clearly not be against the byte length, or else a + * single UTF8 character would count for more than one. + * + * We have chosen to use the number of 16-bit units that the + * password encodes to as the measure of length. This is not + * the same as the number of codepoints, if a password + * contains a character beyond the Basic Multilingual Plane + * (above 65535) it will count for more than one "character". + */ + + size_t password_characters_roughly = strlen_m(utf8_pw); /* checks if the "minPwdLength" property is satisfied */ - if (minPwdLength > utf8_len) { + if (minPwdLength > password_characters_roughly) { return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT; } - /* checks the password complexity */ + /* We might not be asked to check the password complexity */ if (!(pwdProperties & DOMAIN_PASSWORD_COMPLEX)) { return SAMR_VALIDATION_STATUS_SUCCESS; } - if (utf8_len == 0) { + if (password_characters_roughly == 0) { return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH; } @@ -2058,6 +2073,7 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx, if (password_script != NULL && *password_script != '\0') { int check_ret = 0; int error = 0; + ssize_t nwritten = 0; struct tevent_context *event_ctx = NULL; struct tevent_req *req = NULL; int cps_stdin = -1; @@ -2120,7 +2136,9 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx, cps_stdin = samba_runcmd_export_stdin(req); - if (write(cps_stdin, utf8_pw, utf8_len) != utf8_len) { + nwritten = write(cps_stdin, utf8_blob->data, + utf8_blob->length); + if (nwritten != utf8_blob->length) { close(cps_stdin); cps_stdin = -1; TALLOC_FREE(password_script); -- 2.17.1 From 4087d16945f97479b46a2d5fbfc883f813959fd9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 15 Oct 2019 16:28:46 +1300 Subject: [PATCH 286/376] CVE-2019-14847 dsdb: Demonstrate the correct interaction of ranged_results style attributes and dirsync Incremental results are provided by a flag on the dirsync control, not by changing the attribute name. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14040 Signed-off-by: Andrew Bartlett --- selftest/knownfail.d/dirsync | 1 + source4/dsdb/tests/python/dirsync.py | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 selftest/knownfail.d/dirsync diff --git a/selftest/knownfail.d/dirsync b/selftest/knownfail.d/dirsync new file mode 100644 index 00000000000..bc49fe0d9bb --- /dev/null +++ b/selftest/knownfail.d/dirsync @@ -0,0 +1 @@ +^samba4.ldap.dirsync.python\(ad_dc_ntvfs\).__main__.ExtendedDirsyncTests.test_dirsync_linkedattributes_range\( \ No newline at end of file diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index 8b46357c670..78117bc364b 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -28,6 +28,7 @@ from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options import base64 +import ldb from ldb import LdbError, SCOPE_BASE from ldb import Message, MessageElement, Dn from ldb import FLAG_MOD_ADD, FLAG_MOD_DELETE @@ -588,6 +589,31 @@ class SimpleDirsyncTests(DirsyncBaseTests): class ExtendedDirsyncTests(SimpleDirsyncTests): + def test_dirsync_linkedattributes_range(self): + self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) + res = self.ldb_admin.search(self.base_dn, + attrs=["member;range=1-1"], + expression="(name=Administrators)", + controls=["dirsync:1:0:0"]) + + self.assertTrue(len(res) > 0) + self.assertTrue(res[0].get("member;range=1-1") is None) + self.assertTrue(res[0].get("member") is not None) + self.assertTrue(len(res[0].get("member")) > 0) + + def test_dirsync_linkedattributes_range_user(self): + self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) + try: + res = self.ldb_simple.search(self.base_dn, + attrs=["member;range=1-1"], + expression="(name=Administrators)", + controls=["dirsync:1:0:0"]) + except LdbError as e: + (num, _) = e.args + self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + self.fail() + def test_dirsync_linkedattributes(self): flag_incr_linked = 2147483648 self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) -- 2.17.1 From e33b8c5651032b82ffa3631b37ddb93f2bfe3b8d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 15 Oct 2019 15:44:34 +1300 Subject: [PATCH 287/376] CVE-2019-14847 dsdb: Correct behaviour of ranged_results when combined with dirsync BUG: https://bugzilla.samba.org/show_bug.cgi?id=14040 Signed-off-by: Andrew Bartlett --- selftest/knownfail.d/dirsync | 1 - source4/dsdb/samdb/ldb_modules/dirsync.c | 11 ++++---- .../dsdb/samdb/ldb_modules/ranged_results.c | 25 ++++++++++++++++--- 3 files changed, 28 insertions(+), 9 deletions(-) delete mode 100644 selftest/knownfail.d/dirsync diff --git a/selftest/knownfail.d/dirsync b/selftest/knownfail.d/dirsync deleted file mode 100644 index bc49fe0d9bb..00000000000 --- a/selftest/knownfail.d/dirsync +++ /dev/null @@ -1 +0,0 @@ -^samba4.ldap.dirsync.python\(ad_dc_ntvfs\).__main__.ExtendedDirsyncTests.test_dirsync_linkedattributes_range\( \ No newline at end of file diff --git a/source4/dsdb/samdb/ldb_modules/dirsync.c b/source4/dsdb/samdb/ldb_modules/dirsync.c index 00f24bd6d59..96cec7774cf 100644 --- a/source4/dsdb/samdb/ldb_modules/dirsync.c +++ b/source4/dsdb/samdb/ldb_modules/dirsync.c @@ -1014,7 +1014,7 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req } /* - * check if there's an extended dn control + * check if there's a dirsync control */ control = ldb_request_get_control(req, LDB_CONTROL_DIRSYNC_OID); if (control == NULL) { @@ -1343,11 +1343,12 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req } /* - * Remove our control from the list of controls + * Mark dirsync control as uncritical (done) + * + * We need this so ranged_results knows how to behave with + * dirsync */ - if (!ldb_save_controls(control, req, NULL)) { - return ldb_operr(ldb); - } + control->critical = false; dsc->schema = dsdb_get_schema(ldb, dsc); /* * At the begining we make the hypothesis that we will return a complete diff --git a/source4/dsdb/samdb/ldb_modules/ranged_results.c b/source4/dsdb/samdb/ldb_modules/ranged_results.c index 13bf3a2d0a9..98438799997 100644 --- a/source4/dsdb/samdb/ldb_modules/ranged_results.c +++ b/source4/dsdb/samdb/ldb_modules/ranged_results.c @@ -35,14 +35,14 @@ struct rr_context { struct ldb_module *module; struct ldb_request *req; + bool dirsync_in_use; }; static struct rr_context *rr_init_context(struct ldb_module *module, struct ldb_request *req) { - struct rr_context *ac; - - ac = talloc_zero(req, struct rr_context); + struct ldb_control *dirsync_control = NULL; + struct rr_context *ac = talloc_zero(req, struct rr_context); if (ac == NULL) { ldb_set_errstring(ldb_module_get_ctx(module), "Out of Memory"); return NULL; @@ -51,6 +51,16 @@ static struct rr_context *rr_init_context(struct ldb_module *module, ac->module = module; ac->req = req; + /* + * check if there's a dirsync control (as there is an + * interaction between these modules) + */ + dirsync_control = ldb_request_get_control(req, + LDB_CONTROL_DIRSYNC_OID); + if (dirsync_control != NULL) { + ac->dirsync_in_use = true; + } + return ac; } @@ -82,6 +92,15 @@ static int rr_search_callback(struct ldb_request *req, struct ldb_reply *ares) ares->response, ares->error); } + if (ac->dirsync_in_use) { + /* + * We return full attribute values when mixed with + * dirsync + */ + return ldb_module_send_entry(ac->req, + ares->message, + ares->controls); + } /* LDB_REPLY_ENTRY */ temp_ctx = talloc_new(ac->req); -- 2.17.1 From 3815f9bfda8137f33b5f24e81cc61d1027a01748 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Thu, 24 Oct 2019 10:42:16 +0200 Subject: [PATCH 288/376] WHATSNEW: Add release notes for Samba 4.11.2. * Bug 14071: CVE-2019-10218: Client code can return filenames containing path separators. * Bug 12438: CVE-2019-14833: Samba AD DC check password script does not receive the full password. * Bug 14040: CVE-2019-14847: User with "get changes" permission can crash AD DC LDAP server via dirsync. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 2e61702b71b..8c6db3b3034 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,77 @@ + ============================== + Release Notes for Samba 4.11.2 + October 29, 2019 + ============================== + + +This is a security release in order to address the following defects: + +o CVE-2019-10218: Client code can return filenames containing path separators. +o CVE-2019-14833: Samba AD DC check password script does not receive the full + password. +o CVE-2019-14847: User with "get changes" permission can crash AD DC LDAP server + via dirsync. + +======= +Details +======= + +o CVE-2019-10218: + Malicious servers can cause Samba client code to return filenames containing + path separators to calling code. + +o CVE-2019-14833: + When the password contains multi-byte (non-ASCII) characters, the check + password script does not receive the full password string. + +o CVE-2019-14847: + Users with the "get changes" extended access right can crash the AD DC LDAP + server by requesting an attribute using the range= syntax. + +For more details and workarounds, please refer to the security advisories. + + +Changes since 4.11.1: +--------------------- + +o Jeremy Allison + * BUG 14071: CVE-2019-10218 - s3: libsmb: Protect SMB1 and SMB2 client code + from evil server returned names. + +o Andrew Bartlett + * BUG 12438: CVE-2019-14833: Use utf8 characters in the unacceptable + password. + * BUG 14040: CVE-2019-14847 dsdb: Correct behaviour of ranged_results when + combined with dirsync. + +o Björn Baumbach + * BUG 12438: CVE-2019-14833 dsdb: Send full password to check password + script. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the "Samba 4.1 and newer" product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + ============================== Release Notes for Samba 4.11.1 October 18, 2019 @@ -81,8 +155,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================== Release Notes for Samba 4.11.0 -- 2.17.1 From df2b97d12e6d5d36dc152896a21ba44bc7531654 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Thu, 24 Oct 2019 10:52:52 +0200 Subject: [PATCH 289/376] VERSION: Disable GIT_SNAPSHOT for the 4.11.2 release. * Bug 14071: CVE-2019-10218: Client code can return filenames containing path separators. * Bug 12438: CVE-2019-14833: Samba AD DC check password script does not receive the full password. * Bug 14040: CVE-2019-14847: User with "get changes" permission can crash AD DC LDAP server via dirsync. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fbc941686eb..e4636c3dc96 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From e704eee3083658f7dcdd4238295f8e0b229a1688 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 29 Oct 2019 11:10:52 +0100 Subject: [PATCH 290/376] VERSION: Bump version up to 4.11.3. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fbc941686eb..e9cc49c7f77 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=2 +SAMBA_VERSION_RELEASE=3 ######################################################## # If a official release has a serious bug # -- 2.17.1 From 509f11547f3eee151e16f14a17c58d193cf81993 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Oct 2019 11:39:02 -0700 Subject: [PATCH 291/376] s3: libsmb: Ensure SMB1 cli_qpathinfo2() doesn't return an inode number. The info level it uses doesn't return that, previously we were using the field that is returned as the EA size as the inode number (which is usually zero, so the code in libsmbclient would then synthesize an inode number from a hash of the pathname, which is all it can do for SMB1). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14161 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit d495074ee27a5f528d5156a69800ee58d799b1eb) --- source3/libsmb/clirap.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index e80dfc92a77..b4b40ebdab4 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -855,7 +855,15 @@ NTSTATUS cli_qpathinfo2_recv(struct tevent_req *req, *size = IVAL2_TO_SMB_BIG_UINT(state->data,48); } if (ino) { - *ino = IVAL(state->data, 64); + /* + * SMB1 qpathinfo2 uses SMB_QUERY_FILE_ALL_INFO + * which doesn't return an inode number (fileid). + * We can't change this to one of the FILE_ID + * info levels as only Win2003 and above support + * these [MS-SMB: 2.2.2.3.1] and the SMB1 code + * needs to support older servers. + */ + *ino = 0; } return NT_STATUS_OK; } -- 2.17.1 From 4aa37b8e722d0ee7c7417b33ea62e7a66151a867 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Oct 2019 12:41:08 -0700 Subject: [PATCH 292/376] s3: torture: Ensure SMB1 cli_qpathinfo2() doesn't return an inode number. Piggyback on existing tests, ensure we don't regress on: BUG: https://bugzilla.samba.org/show_bug.cgi?id=14161 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit 8e55a8562951924e4b1aad5a6d67fc8b309590c1) --- source3/torture/torture.c | 49 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 66dc0cf4d1c..a795e61125f 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -4211,6 +4211,7 @@ static bool run_trans2test(int dummy) bool correct = True; NTSTATUS status; uint32_t fs_attr; + uint64_t ino; printf("starting trans2 test\n"); @@ -4218,6 +4219,14 @@ static bool run_trans2test(int dummy) return False; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* Ensure ino is zero, SMB2 gets a real one. */ + ino = 0; + } else { + /* Ensure ino is -1, SMB1 never gets a real one. */ + ino = (uint64_t)-1; + } + status = cli_get_fs_attr_info(cli, &fs_attr); if (!NT_STATUS_IS_OK(status)) { printf("ERROR: cli_get_fs_attr_info returned %s\n", @@ -4289,7 +4298,7 @@ static bool run_trans2test(int dummy) O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum); cli_close(cli, fnum); status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts, - &m_time_ts, &size, NULL, NULL); + &m_time_ts, &size, NULL, &ino); if (!NT_STATUS_IS_OK(status)) { printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status)); correct = False; @@ -4299,6 +4308,19 @@ static bool run_trans2test(int dummy) printf("This system appears to set a initial 0 write time\n"); correct = False; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* SMB2 should always return an inode. */ + if (ino == 0) { + printf("SMB2 bad inode (0)\n"); + correct = false; + } + } else { + /* SMB1 must always return zero here. */ + if (ino != 0) { + printf("SMB1 bad inode (!0)\n"); + correct = false; + } + } } cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); @@ -11593,11 +11615,20 @@ static bool run_dir_createtime(int dummy) struct timespec create_time1; uint16_t fnum; bool ret = false; + uint64_t ino; if (!torture_open_connection(&cli, 0)) { return false; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* Ensure ino is zero, SMB2 gets a real one. */ + ino = 0; + } else { + /* Ensure ino is -1, SMB1 never gets a real one. */ + ino = (uint64_t)-1; + } + cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); cli_rmdir(cli, dname); @@ -11608,13 +11639,27 @@ static bool run_dir_createtime(int dummy) } status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL, - NULL, NULL, NULL); + NULL, NULL, &ino); if (!NT_STATUS_IS_OK(status)) { printf("cli_qpathinfo2 returned %s\n", nt_errstr(status)); goto out; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* SMB2 should always return an inode. */ + if (ino == 0) { + printf("SMB2 bad inode (0)\n"); + goto out; + } + } else { + /* SMB1 must always return zero here. */ + if (ino != 0) { + printf("SMB1 bad inode (!0)\n"); + goto out; + } + } + /* Sleep 3 seconds, then create a file. */ sleep(3); -- 2.17.1 From 2958016c30a8d9f80a45b64e91a20d8ebf995d85 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 21 Oct 2019 17:08:08 +0200 Subject: [PATCH 293/376] replace: Only link libnsl and libsocket if requrired BUG: https://bugzilla.samba.org/show_bug.cgi?id=14168 Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Wed Oct 23 08:23:13 UTC 2019 on sn-devel-184 (cherry picked from commit 263bec1b8d0744da73dd92e4a361fb7430289ab3) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Mon Nov 4 09:31:23 UTC 2019 on sn-devel-184 --- lib/replace/wscript | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/replace/wscript b/lib/replace/wscript index 240d730cbee..56e2a22de49 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -190,10 +190,35 @@ def configure(conf): conf.CHECK_TYPE_IN('sig_atomic_t', 'signal.h', define='HAVE_SIG_ATOMIC_T_TYPE') conf.CHECK_FUNCS('sigsetmask siggetmask sigprocmask sigblock sigaction sigset') - conf.CHECK_FUNCS_IN('''inet_ntoa inet_aton inet_ntop inet_pton connect gethostbyname - getaddrinfo getnameinfo freeaddrinfo gai_strerror socketpair''', - 'socket nsl', checklibc=True, - headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h') + # Those functions are normally available in libc + if not conf.CHECK_FUNCS(''' + inet_ntoa + inet_aton + inet_ntop + inet_pton + connect + gethostbyname + getaddrinfo + getnameinfo + freeaddrinfo + gai_strerror + socketpair''', + headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h'): + conf.CHECK_FUNCS_IN(''' + inet_ntoa + inet_aton + inet_ntop + inet_pton + connect + gethostbyname + getaddrinfo + getnameinfo + freeaddrinfo + gai_strerror + socketpair''', + 'socket nsl', + headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h') + conf.DEFINE('REPLACE_REQUIRES_LIBSOCKET_LIBNSL', 1) conf.CHECK_FUNCS('memset_s memset_explicit') @@ -836,6 +861,7 @@ def build(bld): extra_libs = '' if bld.CONFIG_SET('HAVE_LIBBSD'): extra_libs += ' bsd' if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' + if bld.CONFIG_SET('REPLACE_REQUIRES_LIBSOCKET_LIBNSL'): extra_libs += ' socket nsl' bld.SAMBA_SUBSYSTEM('LIBREPLACE_HOSTCC', REPLACE_HOSTCC_SOURCE, @@ -876,7 +902,7 @@ def build(bld): # at the moment: # hide_symbols=bld.BUILTIN_LIBRARY('replace'), private_library=True, - deps='crypt dl nsl socket attr' + extra_libs) + deps='crypt dl attr' + extra_libs) replace_test_cflags = '' if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): -- 2.17.1 From b62705398d13bdad54e5abb65a23fa0d94c3571d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Oct 2019 12:12:32 +0200 Subject: [PATCH 294/376] s4:tests/dirsync: add tests for dirsync with extended_dn This demonstrates a problems that the extended_dn returned by the dirsync module always uses the SDDL format for GUID/SID components. Azure AD connect reports discovery errors: reference-value-not-ldap-conformant for attributes member and manager. The key is that it sends the LDAP_SERVER_EXTENDED_DN_OID without an ExtendedDNRequestValue blob, which means the flag value should be treated as 0 and the HEX string format should be used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14153 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 6d43d82b49c8cd47da2f1489fe8b52d5a873a19c) --- selftest/knownfail.d/dirsync_extended_dn | 1 + source4/dsdb/tests/python/dirsync.py | 31 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 selftest/knownfail.d/dirsync_extended_dn diff --git a/selftest/knownfail.d/dirsync_extended_dn b/selftest/knownfail.d/dirsync_extended_dn new file mode 100644 index 00000000000..0ef6ea56391 --- /dev/null +++ b/selftest/knownfail.d/dirsync_extended_dn @@ -0,0 +1 @@ +^samba4.ldap.dirsync.python.*.__main__.ExtendedDirsyncTests.test_dirsync_extended_dn diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index 78117bc364b..0a22ac4239a 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -681,6 +681,37 @@ class ExtendedDirsyncTests(SimpleDirsyncTests): self.assertEqual(res[0].get("member;range=1-1"), None) self.assertEqual(len(res[0].get("member;range=0-0")), 2) + def test_dirsync_extended_dn(self): + """Check that dirsync works together with the extended_dn control""" + # Let's search for members + self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) + res = self.ldb_simple.search(self.base_dn, + expression="(name=Administrators)", + controls=["dirsync:1:1:1"]) + + self.assertTrue(len(res[0].get("member")) > 0) + size = len(res[0].get("member")) + + resEX1 = self.ldb_simple.search(self.base_dn, + expression="(name=Administrators)", + controls=["dirsync:1:1:1","extended_dn:1:1"]) + self.assertTrue(len(resEX1[0].get("member")) > 0) + sizeEX1 = len(resEX1[0].get("member")) + self.assertEqual(sizeEX1, size) + self.assertIn(res[0]["member"][0], resEX1[0]["member"][0]) + self.assertIn(b"; 0) + sizeEX0 = len(resEX0[0].get("member")) + self.assertEqual(sizeEX0, size) + self.assertIn(res[0]["member"][0], resEX0[0]["member"][0]) + self.assertIn(b"; Date: Fri, 4 Oct 2019 14:57:40 +0200 Subject: [PATCH 295/376] s4:dirsync: fix interaction of dirsync and extended_dn controls Azure AD connect reports discovery errors: reference-value-not-ldap-conformant for attributes member and manager. The key is that it sends the LDAP_SERVER_EXTENDED_DN_OID without an ExtendedDNRequestValue blob, which means the flag value should be treated as 0 and the HEX string format should be used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14153 RN: Prevent azure ad connect from reporting discovery errors: reference-value-not-ldap-conformant Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Thu Oct 24 11:06:58 UTC 2019 on sn-devel-184 (cherry picked from commit d0f566c4ad32d69a1cf896e2dde56fc2489bb7fc) --- selftest/knownfail.d/dirsync_extended_dn | 1 - source4/dsdb/samdb/ldb_modules/dirsync.c | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) delete mode 100644 selftest/knownfail.d/dirsync_extended_dn diff --git a/selftest/knownfail.d/dirsync_extended_dn b/selftest/knownfail.d/dirsync_extended_dn deleted file mode 100644 index 0ef6ea56391..00000000000 --- a/selftest/knownfail.d/dirsync_extended_dn +++ /dev/null @@ -1 +0,0 @@ -^samba4.ldap.dirsync.python.*.__main__.ExtendedDirsyncTests.test_dirsync_extended_dn diff --git a/source4/dsdb/samdb/ldb_modules/dirsync.c b/source4/dsdb/samdb/ldb_modules/dirsync.c index 96cec7774cf..dfa72a1d203 100644 --- a/source4/dsdb/samdb/ldb_modules/dirsync.c +++ b/source4/dsdb/samdb/ldb_modules/dirsync.c @@ -51,6 +51,7 @@ struct dirsync_context { uint64_t fromreqUSN; uint32_t cursor_size; bool noextended; + int extended_type; bool linkIncrVal; bool localonly; bool partial; @@ -481,7 +482,8 @@ skip: } ldb_dn_extended_filter(dn->dn, myaccept); - dn_ln = ldb_dn_get_extended_linearized(dn, dn->dn, 1); + dn_ln = dsdb_dn_get_extended_linearized(dn, dn, + dsc->extended_type); if (dn_ln == NULL) { talloc_free(dn); @@ -998,6 +1000,7 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req struct ldb_control *control; struct ldb_result *acl_res; struct ldb_dirsync_control *dirsync_ctl; + struct ldb_control *extended = NULL; struct ldb_request *down_req; struct dirsync_context *dsc; struct ldb_context *ldb; @@ -1229,7 +1232,19 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req dsc->nbDefaultAttrs = 3; } - if (!ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID)) { + /* check if there's an extended dn control */ + extended = ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID); + if (extended != NULL) { + struct ldb_extended_dn_control *extended_ctrl = NULL; + + if (extended->data != NULL) { + extended_ctrl = talloc_get_type(extended->data, + struct ldb_extended_dn_control); + } + if (extended_ctrl != NULL) { + dsc->extended_type = extended_ctrl->type; + } + } else { ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, false, NULL); if (ret != LDB_SUCCESS) { return ret; -- 2.17.1 From 0b3503a436a37a3e67eed7ce66351a172005c57a Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Fri, 30 Aug 2019 00:22:15 +0300 Subject: [PATCH 296/376] libnet_join: build dnsHostName from netbios name and lp_dnsdomain() This make the join process much more reliable, and avoids "Constraint violation" error when the fqdn returned from getaddrinfo has already got assigned an SPN. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14116 Signed-off-by: Isaac Boukris Reviewed-by: Ralph Boehme Reviewed-by: Alexander Bokovoy --- source3/libnet/libnet_join.c | 31 +++++++++++------------------- testprogs/blackbox/test_net_ads.sh | 7 +++++-- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 1052afde641..ff464ad6e62 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -533,29 +533,23 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, } } - if (!name_to_fqdn(my_fqdn, r->in.machine_name) - || (strchr(my_fqdn, '.') == NULL)) { - fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name, - r->out.dns_domain_name); - } + fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name, lp_dnsdomain()); if (!strlower_m(my_fqdn)) { return ADS_ERROR_LDAP(LDAP_NO_MEMORY); } - if (!strequal(my_fqdn, r->in.machine_name)) { - spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); - if (!spn) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } + spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); + if (spn == NULL) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } - ok = ads_element_in_array(spn_array, num_spns, spn); + ok = ads_element_in_array(spn_array, num_spns, spn); + if (!ok) { + ok = add_string_to_array(spn_array, spn, + &spn_array, &num_spns); if (!ok) { - ok = add_string_to_array(spn_array, spn, - &spn_array, &num_spns); - if (!ok) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); } } @@ -591,12 +585,9 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, /* * Add HOST/netbiosname.domainname */ - if (r->out.dns_domain_name == NULL) { - continue; - } fstr_sprintf(my_fqdn, "%s.%s", *netbios_aliases, - r->out.dns_domain_name); + lp_dnsdomain()); spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); if (spn == NULL) { diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh index cc8345c4624..ef6f99ddea4 100755 --- a/testprogs/blackbox/test_net_ads.sh +++ b/testprogs/blackbox/test_net_ads.sh @@ -81,7 +81,7 @@ testit "testjoin (dedicated keytab)" $VALGRIND $net_tool ads testjoin -kP || fai netbios=$(grep "netbios name" $BASEDIR/$WORKDIR/client.conf | cut -f2 -d= | awk '{$1=$1};1') uc_netbios=$(echo $netbios | tr '[:lower:]' '[:upper:]') lc_realm=$(echo $REALM | tr '[:upper:]' '[:lower:]') -fqdns="$netbios.$lc_realm" +fqdn="$netbios.$lc_realm" krb_princ="primary/instance@$REALM" testit "test (dedicated keytab) add a fully qualified krb5 principal" $VALGRIND $net_tool ads keytab add $krb_princ -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1` @@ -99,7 +99,7 @@ testit "test (dedicated keytab) at least one krb5 principal created from $machin service="nfs" testit "test (dedicated keytab) add a $service service to keytab" $VALGRIND $net_tool ads keytab add $service -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1` -search_str="$service/$fqdns@$REALM" +search_str="$service/$fqdn@$REALM" found=`$net_tool ads keytab list -U$DC_USERNAME%$DC_PASSWORD --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" | grep $search_str | wc -l` testit "test (dedicated keytab) at least one (long form) krb5 principal created from service added is present in keytab" test $found -gt 1 || failed=`expr $failed + 1` @@ -206,6 +206,9 @@ testit "join" $VALGRIND $net_tool ads join -U$DC_USERNAME%$DC_PASSWORD || failed testit "testjoin" $VALGRIND $net_tool ads testjoin || failed=`expr $failed + 1` +testit_grep "check dNSHostName" $fqdn $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ dNSHostName || failed=`expr $failed + 1` +testit_grep "check SPN" ${uc_netbios}.${lc_realm} $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1` + ##Goodbye... testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1` -- 2.17.1 From 2e7683c937e05085770e88cf48288f0404c28092 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 18 Sep 2019 20:00:34 +0300 Subject: [PATCH 297/376] libnet_join_set_machine_spn: improve style and make a bit room for indentation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14116 Signed-off-by: Isaac Boukris Reviewed-by: Ralph Boehme Reviewed-by: Alexander Bokovoy --- source3/libnet/libnet_join.c | 95 ++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index ff464ad6e62..54bff06c614 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -517,7 +517,7 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, /* Windows only creates HOST/shortname & HOST/fqdn. */ spn = talloc_asprintf(mem_ctx, "HOST/%s", r->in.machine_name); - if (!spn) { + if (spn == NULL) { return ADS_ERROR_LDAP(LDAP_NO_MEMORY); } if (!strupper_m(spn)) { @@ -553,60 +553,59 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, } } - netbios_aliases = lp_netbios_aliases(); - if (netbios_aliases != NULL) { - for (; *netbios_aliases != NULL; netbios_aliases++) { - /* - * Add HOST/NETBIOSNAME - */ - spn = talloc_asprintf(mem_ctx, "HOST/%s", *netbios_aliases); - if (spn == NULL) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } - if (!strupper_m(spn)) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } + for (netbios_aliases = lp_netbios_aliases(); + netbios_aliases != NULL && *netbios_aliases != NULL; + netbios_aliases++) { + /* + * Add HOST/NETBIOSNAME + */ + spn = talloc_asprintf(mem_ctx, "HOST/%s", *netbios_aliases); + if (spn == NULL) { + TALLOC_FREE(spn); + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } + if (!strupper_m(spn)) { + TALLOC_FREE(spn); + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } - ok = ads_element_in_array(spn_array, num_spns, spn); - if (ok) { - TALLOC_FREE(spn); - continue; - } - ok = add_string_to_array(spn_array, spn, - &spn_array, &num_spns); - if (!ok) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } + ok = ads_element_in_array(spn_array, num_spns, spn); + if (ok) { + TALLOC_FREE(spn); + continue; + } + ok = add_string_to_array(spn_array, spn, + &spn_array, &num_spns); + if (!ok) { TALLOC_FREE(spn); + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } + TALLOC_FREE(spn); - /* - * Add HOST/netbiosname.domainname - */ - fstr_sprintf(my_fqdn, "%s.%s", - *netbios_aliases, - lp_dnsdomain()); + /* + * Add HOST/netbiosname.domainname + */ + fstr_sprintf(my_fqdn, "%s.%s", + *netbios_aliases, + lp_dnsdomain()); - spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); - if (spn == NULL) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } + spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); + if (spn == NULL) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } - ok = ads_element_in_array(spn_array, num_spns, spn); - if (ok) { - TALLOC_FREE(spn); - continue; - } - ok = add_string_to_array(spn_array, spn, - &spn_array, &num_spns); - if (!ok) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); - } + ok = ads_element_in_array(spn_array, num_spns, spn); + if (ok) { + TALLOC_FREE(spn); + continue; + } + ok = add_string_to_array(spn_array, spn, + &spn_array, &num_spns); + if (!ok) { TALLOC_FREE(spn); + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); } + TALLOC_FREE(spn); } /* make sure to NULL terminate the array */ -- 2.17.1 From 3f9a9b95dd1f128817a979e8687b480d6dc9cab1 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 18 Sep 2019 21:29:47 +0300 Subject: [PATCH 298/376] libnet_join_set_machine_spn: simplify memory handling and avoid a possible memory leak when passing null to add_string_to_array() as mem_ctx. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14116 Signed-off-by: Isaac Boukris Reviewed-by: Ralph Boehme Reviewed-by: Alexander Bokovoy --- source3/libnet/libnet_join.c | 74 ++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 54bff06c614..15659b5ab43 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -490,6 +490,7 @@ static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx, static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r) { + TALLOC_CTX *frame = talloc_stackframe(); ADS_STATUS status; ADS_MODLIST mods; fstring my_fqdn; @@ -506,7 +507,7 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, return status; } - status = libnet_join_get_machine_spns(mem_ctx, + status = libnet_join_get_machine_spns(frame, r, discard_const_p(char **, &spn_array), &num_spns); @@ -516,40 +517,46 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, /* Windows only creates HOST/shortname & HOST/fqdn. */ - spn = talloc_asprintf(mem_ctx, "HOST/%s", r->in.machine_name); + spn = talloc_asprintf(frame, "HOST/%s", r->in.machine_name); if (spn == NULL) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } if (!strupper_m(spn)) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } ok = ads_element_in_array(spn_array, num_spns, spn); if (!ok) { - ok = add_string_to_array(spn_array, spn, + ok = add_string_to_array(frame, spn, &spn_array, &num_spns); if (!ok) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } } fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name, lp_dnsdomain()); if (!strlower_m(my_fqdn)) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } - spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); + spn = talloc_asprintf(frame, "HOST/%s", my_fqdn); if (spn == NULL) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } ok = ads_element_in_array(spn_array, num_spns, spn); if (!ok) { - ok = add_string_to_array(spn_array, spn, + ok = add_string_to_array(frame, spn, &spn_array, &num_spns); if (!ok) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } } @@ -559,28 +566,26 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, /* * Add HOST/NETBIOSNAME */ - spn = talloc_asprintf(mem_ctx, "HOST/%s", *netbios_aliases); + spn = talloc_asprintf(frame, "HOST/%s", *netbios_aliases); if (spn == NULL) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } if (!strupper_m(spn)) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } ok = ads_element_in_array(spn_array, num_spns, spn); if (ok) { - TALLOC_FREE(spn); continue; } ok = add_string_to_array(spn_array, spn, &spn_array, &num_spns); if (!ok) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } - TALLOC_FREE(spn); /* * Add HOST/netbiosname.domainname @@ -589,51 +594,56 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, *netbios_aliases, lp_dnsdomain()); - spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn); + spn = talloc_asprintf(frame, "HOST/%s", my_fqdn); if (spn == NULL) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } ok = ads_element_in_array(spn_array, num_spns, spn); if (ok) { - TALLOC_FREE(spn); continue; } ok = add_string_to_array(spn_array, spn, &spn_array, &num_spns); if (!ok) { - TALLOC_FREE(spn); - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } - TALLOC_FREE(spn); } /* make sure to NULL terminate the array */ - spn_array = talloc_realloc(mem_ctx, spn_array, const char *, num_spns + 1); + spn_array = talloc_realloc(frame, spn_array, const char *, num_spns + 1); if (spn_array == NULL) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } spn_array[num_spns] = NULL; mods = ads_init_mods(mem_ctx); if (!mods) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } /* fields of primary importance */ status = ads_mod_str(mem_ctx, &mods, "dNSHostName", my_fqdn); if (!ADS_ERR_OK(status)) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } status = ads_mod_strlist(mem_ctx, &mods, "servicePrincipalName", spn_array); if (!ADS_ERR_OK(status)) { - return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; } - return ads_gen_mod(r->in.ads, r->out.dn, mods); + status = ads_gen_mod(r->in.ads, r->out.dn, mods); + +done: + TALLOC_FREE(frame); + return status; } /**************************************************************** -- 2.17.1 From 526ad3a904ad9d18219cc5d06313cfa2318fc2ef Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 18 Sep 2019 23:15:57 +0300 Subject: [PATCH 299/376] libnet_join_set_machine_spn: simplify adding uniq spn to array and do not skip adding a fully qualified spn to netbios-aliases in case a short spn already existed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14116 Signed-off-by: Isaac Boukris Reviewed-by: Ralph Boehme Reviewed-by: Alexander Bokovoy --- source3/libnet/libnet_join.c | 56 +++++++++++++++--------------------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 15659b5ab43..71d45276392 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -483,6 +483,19 @@ static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx, return status; } +static ADS_STATUS add_uniq_spn(TALLOC_CTX *mem_ctx, const char *spn, + const char ***array, size_t *num) +{ + bool ok = ads_element_in_array(*array, *num, spn); + if (!ok) { + ok = add_string_to_array(mem_ctx, spn, array, num); + if (!ok) { + return ADS_ERROR_LDAP(LDAP_NO_MEMORY); + } + } + return ADS_SUCCESS; +} + /**************************************************************** Set a machines dNSHostName and servicePrincipalName attributes ****************************************************************/ @@ -497,7 +510,6 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, const char **spn_array = NULL; size_t num_spns = 0; char *spn = NULL; - bool ok; const char **netbios_aliases = NULL; /* Find our DN */ @@ -527,14 +539,9 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, goto done; } - ok = ads_element_in_array(spn_array, num_spns, spn); - if (!ok) { - ok = add_string_to_array(frame, spn, - &spn_array, &num_spns); - if (!ok) { - status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); - goto done; - } + status = add_uniq_spn(frame, spn, &spn_array, &num_spns); + if (!ADS_ERR_OK(status)) { + goto done; } fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name, lp_dnsdomain()); @@ -550,14 +557,9 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, goto done; } - ok = ads_element_in_array(spn_array, num_spns, spn); - if (!ok) { - ok = add_string_to_array(frame, spn, - &spn_array, &num_spns); - if (!ok) { - status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); - goto done; - } + status = add_uniq_spn(frame, spn, &spn_array, &num_spns); + if (!ADS_ERR_OK(status)) { + goto done; } for (netbios_aliases = lp_netbios_aliases(); @@ -576,14 +578,8 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, goto done; } - ok = ads_element_in_array(spn_array, num_spns, spn); - if (ok) { - continue; - } - ok = add_string_to_array(spn_array, spn, - &spn_array, &num_spns); - if (!ok) { - status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = add_uniq_spn(frame, spn, &spn_array, &num_spns); + if (!ADS_ERR_OK(status)) { goto done; } @@ -600,14 +596,8 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, goto done; } - ok = ads_element_in_array(spn_array, num_spns, spn); - if (ok) { - continue; - } - ok = add_string_to_array(spn_array, spn, - &spn_array, &num_spns); - if (!ok) { - status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + status = add_uniq_spn(frame, spn, &spn_array, &num_spns); + if (!ADS_ERR_OK(status)) { goto done; } } -- 2.17.1 From 35da7673e882dfc16e95bbfa1bea49ee837d33a5 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Tue, 17 Sep 2019 21:38:07 +0300 Subject: [PATCH 300/376] docs-xml: add "additional dns hostnames" smb.conf option BUG: https://bugzilla.samba.org/show_bug.cgi?id=14116 Signed-off-by: Isaac Boukris Reviewed-by: Ralph Boehme Reviewed-by: Alexander Bokovoy --- docs-xml/smbdotconf/base/additionaldnshostnames.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs-xml/smbdotconf/base/additionaldnshostnames.xml diff --git a/docs-xml/smbdotconf/base/additionaldnshostnames.xml b/docs-xml/smbdotconf/base/additionaldnshostnames.xml new file mode 100644 index 00000000000..ddc04ee9f81 --- /dev/null +++ b/docs-xml/smbdotconf/base/additionaldnshostnames.xml @@ -0,0 +1,11 @@ + + + A list of additional DNS names by which this host can be identified + + +empty string (no additional dns names) + host2.example.com host3.other.com + -- 2.17.1 From b30b3073f9c0aa052b354385b2878f9a17756bee Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Fri, 13 Sep 2019 10:56:10 +0300 Subject: [PATCH 301/376] libnet_join: add SPNs for additional-dns-hostnames entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and set msDS-AdditionalDnsHostName to the specified list. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14116 Signed-off-by: Isaac Boukris Reviewed-by: Ralph Boehme Reviewed-by: Alexander Bokovoy Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Fri Oct 25 10:43:08 UTC 2019 on sn-devel-184 Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Tue Nov 5 13:57:30 UTC 2019 on sn-devel-184 --- source3/libnet/libnet_join.c | 27 +++++++++++++++++++++++++++ testprogs/blackbox/test_net_ads.sh | 10 +++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 71d45276392..9d4f656ffec 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -511,6 +511,7 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, size_t num_spns = 0; char *spn = NULL; const char **netbios_aliases = NULL; + const char **addl_hostnames = NULL; /* Find our DN */ @@ -602,6 +603,22 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, } } + for (addl_hostnames = lp_additional_dns_hostnames(); + addl_hostnames != NULL && *addl_hostnames != NULL; + addl_hostnames++) { + + spn = talloc_asprintf(frame, "HOST/%s", *addl_hostnames); + if (spn == NULL) { + status = ADS_ERROR_LDAP(LDAP_NO_MEMORY); + goto done; + } + + status = add_uniq_spn(frame, spn, &spn_array, &num_spns); + if (!ADS_ERR_OK(status)) { + goto done; + } + } + /* make sure to NULL terminate the array */ spn_array = talloc_realloc(frame, spn_array, const char *, num_spns + 1); if (spn_array == NULL) { @@ -629,6 +646,16 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx, goto done; } + addl_hostnames = lp_additional_dns_hostnames(); + if (addl_hostnames != NULL && *addl_hostnames != NULL) { + status = ads_mod_strlist(mem_ctx, &mods, + "msDS-AdditionalDnsHostName", + addl_hostnames); + if (!ADS_ERR_OK(status)) { + goto done; + } + } + status = ads_gen_mod(r->in.ads, r->out.dn, mods); done: diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh index ef6f99ddea4..8bcff006b8e 100755 --- a/testprogs/blackbox/test_net_ads.sh +++ b/testprogs/blackbox/test_net_ads.sh @@ -202,13 +202,21 @@ base_dn="DC=addom,DC=samba,DC=example,DC=com" computers_dn="CN=Computers,$base_dn" testit "ldb check for existence of machine account" $ldbsearch -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "cn=$HOSTNAME,$computers_dn" || failed=`expr $failed + 1` -testit "join" $VALGRIND $net_tool ads join -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1` +dns_alias1="${netbios}_alias1.other.${lc_realm}" +dns_alias2="${netbios}_alias2.other2.${lc_realm}" +testit "join" $VALGRIND $net_tool --option=additionaldnshostnames=$dns_alias1,$dns_alias2 ads join -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1` testit "testjoin" $VALGRIND $net_tool ads testjoin || failed=`expr $failed + 1` testit_grep "check dNSHostName" $fqdn $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ dNSHostName || failed=`expr $failed + 1` testit_grep "check SPN" ${uc_netbios}.${lc_realm} $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1` +testit_grep "dns alias SPN" $dns_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1` +testit_grep "dns alias SPN" $dns_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1` + +testit_grep "dns alias addl" $dns_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1` +testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1` + ##Goodbye... testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1` -- 2.17.1 From ac3cb59fd4f3736547979a780508c51106b84d8e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 4 May 2019 12:12:04 +0200 Subject: [PATCH 302/376] s3:dbwrap: initialize messaging before getting the ctdb connection This is a better fix for bug #13465. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13925 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit ca95d7f41b683b4d7ac59ed6ee709d44abfe2019) --- source3/lib/dbwrap/dbwrap_open.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c index c8dfd9103a8..20084bca471 100644 --- a/source3/lib/dbwrap/dbwrap_open.c +++ b/source3/lib/dbwrap/dbwrap_open.c @@ -141,13 +141,19 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx; struct ctdbd_connection *conn; + /* + * Initialize messaging before getting the ctdb + * connection, as the ctdb connection requires messaging + * to be initialized. + */ + msg_ctx = global_messaging_context(); + conn = messaging_ctdb_connection(); if (conn == NULL) { DBG_WARNING("No ctdb connection\n"); errno = EIO; return NULL; } - msg_ctx = global_messaging_context(); result = db_open_ctdb(mem_ctx, msg_ctx, base, hash_size, -- 2.17.1 From 098ddd6fe4e7d95cba6fa50749479f5243f671e9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 4 May 2019 12:12:48 +0200 Subject: [PATCH 303/376] s3: remove now unneeded call to cmdline_messaging_context() This was only needed as dbwrap_open() had a bug where it asked for the ctdb connection before initializing messaging. The previous commit fixed that so we can now safely remove the calls to cmdline_messaging_context() from all tools that don't use messaging. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13925 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Thu Oct 24 09:33:47 UTC 2019 on sn-devel-184 (cherry picked from commit 9471508391fd3bcf199b1e94f8d9ee2b956e8f8e) --- source3/lib/popt_common_cmdline.c | 7 ------- source3/utils/dbwrap_tool.c | 2 -- source3/utils/eventlogadm.c | 3 --- source3/utils/ntlm_auth.c | 2 -- source3/utils/pdbedit.c | 2 -- source3/utils/sharesec.c | 1 - source3/utils/smbget.c | 2 -- source3/utils/smbpasswd.c | 2 -- source3/utils/testparm.c | 2 -- 9 files changed, 23 deletions(-) diff --git a/source3/lib/popt_common_cmdline.c b/source3/lib/popt_common_cmdline.c index 79e34847f48..39a787510a3 100644 --- a/source3/lib/popt_common_cmdline.c +++ b/source3/lib/popt_common_cmdline.c @@ -102,15 +102,8 @@ static void popt_common_credentials_callback(poptContext con, } if (reason == POPT_CALLBACK_REASON_POST) { - struct messaging_context *msg_ctx = NULL; bool ok; - msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE()); - if (msg_ctx == NULL) { - fprintf(stderr, "Unable to initialize " - "messaging context\n"); - } - ok = lp_load_client(get_dyn_CONFIGFILE()); if (!ok) { const char *pname = poptGetInvocationName(con); diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c index 2808a5d68bf..153a4459ee0 100644 --- a/source3/utils/dbwrap_tool.c +++ b/source3/utils/dbwrap_tool.c @@ -422,8 +422,6 @@ int main(int argc, const char **argv) while (extra_argv[extra_argc]) extra_argc++; } - cmdline_messaging_context(get_dyn_CONFIGFILE()); - lp_load_global(get_dyn_CONFIGFILE()); if ((extra_argc < 2) || (extra_argc > 5)) { diff --git a/source3/utils/eventlogadm.c b/source3/utils/eventlogadm.c index db874dfae8a..2770fffa48c 100644 --- a/source3/utils/eventlogadm.c +++ b/source3/utils/eventlogadm.c @@ -473,9 +473,6 @@ int main( int argc, char *argv[] ) exit( 1 ); } - cmdline_messaging_context(configfile == NULL ? - get_dyn_CONFIGFILE() : configfile); - if ( configfile == NULL ) { lp_load_global(get_dyn_CONFIGFILE()); } else if (!lp_load_global(configfile)) { diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 2be641c891c..87f6554ae4f 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -2504,8 +2504,6 @@ enum { poptFreeContext(pc); - cmdline_messaging_context(get_dyn_CONFIGFILE()); - if (!lp_load_global(get_dyn_CONFIGFILE())) { d_fprintf(stderr, "ntlm_auth: error opening config file %s. Error was %s\n", get_dyn_CONFIGFILE(), strerror(errno)); diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 74f8c3b0b2f..14edbaeceea 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -1128,8 +1128,6 @@ int main(int argc, const char **argv) if (user_name == NULL) user_name = poptGetArg(pc); - cmdline_messaging_context(get_dyn_CONFIGFILE()); - if (!lp_load_global(get_dyn_CONFIGFILE())) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", get_dyn_CONFIGFILE()); exit(1); diff --git a/source3/utils/sharesec.c b/source3/utils/sharesec.c index 2ea81b9adfa..10c347eaac3 100644 --- a/source3/utils/sharesec.c +++ b/source3/utils/sharesec.c @@ -501,7 +501,6 @@ int main(int argc, const char *argv[]) setlinebuf(stdout); - cmdline_messaging_context(get_dyn_CONFIGFILE()); lp_load_with_registry_shares(get_dyn_CONFIGFILE()); /* check for initializing secrets.tdb first */ diff --git a/source3/utils/smbget.c b/source3/utils/smbget.c index 58690be56e3..a948a336445 100644 --- a/source3/utils/smbget.c +++ b/source3/utils/smbget.c @@ -1003,8 +1003,6 @@ int main(int argc, char **argv) popt_burn_cmdline_password(argc, argv); - cmdline_messaging_context(get_dyn_CONFIGFILE()); - if (smbc_init(get_auth_data, opt.debuglevel) < 0) { fprintf(stderr, "Unable to initialize libsmbclient\n"); return 1; diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 8e2b9d7f80f..a6509abe5cb 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -197,8 +197,6 @@ static int process_options(int argc, char **argv, int local_flags) usage(); } - cmdline_messaging_context(configfile); - if (!lp_load_global(configfile)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", configfile); diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index efa58a6a417..9ba625da4bf 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -742,8 +742,6 @@ static void do_per_share_checks(int s) goto done; } - cmdline_messaging_context(config_file); - fprintf(stderr,"Load smb config files from %s\n",config_file); if (!lp_load_with_registry_shares(config_file)) { -- 2.17.1 From eacdde195ac595bce9b35febb13b9723851fbb41 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 5 Aug 2019 10:59:22 +0200 Subject: [PATCH 304/376] s3:smbd: Incomplete conversion of former parametric options BUG: https://bugzilla.samba.org/show_bug.cgi?id=14069 RN: Incomplete conversion of former parametric options Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (backported from commit ea17bd5539eb0be7a446b99c8b6baa4aa1ab273f) --- source3/modules/vfs_ceph.c | 2 +- source3/modules/vfs_glusterfs.c | 2 +- source3/modules/vfs_gpfs.c | 2 +- source3/smbd/reply.c | 4 ++-- source3/smbd/trans2.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 1b293ddb1b0..28363f003c2 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -146,7 +146,7 @@ static int cephwrap_connect(struct vfs_handle_struct *handle, const char *servi /* * Unless we have an async implementation of getxattrat turn this off. */ - lp_do_parameter(SNUM(handle->conn), "smbd:async dosmode", "false"); + lp_do_parameter(SNUM(handle->conn), "smbd async dosmode", "false"); return 0; diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index afb34b4b47c..8827bf018ab 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -367,7 +367,7 @@ static int vfs_gluster_connect(struct vfs_handle_struct *handle, /* * Unless we have an async implementation of getxattrat turn this off. */ - lp_do_parameter(SNUM(handle->conn), "smbd:async dosmode", "false"); + lp_do_parameter(SNUM(handle->conn), "smbd async dosmode", "false"); done: if (ret < 0) { diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index f0d5074d36b..22848496178 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -2195,7 +2195,7 @@ static int vfs_gpfs_connect(struct vfs_handle_struct *handle, * Unless we have an async implementation of get_dos_attributes turn * this off. */ - lp_do_parameter(SNUM(handle->conn), "smbd:async dosmode", "false"); + lp_do_parameter(SNUM(handle->conn), "smbd async dosmode", "false"); return 0; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 35d1ae772d5..65ac729c732 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1386,7 +1386,7 @@ void reply_getatr(struct smb_request *req) const char *p; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); - bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); + bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn)); START_PROFILE(SMBgetatr); @@ -1769,7 +1769,7 @@ void reply_search(struct smb_request *req) bool mask_contains_wcard = False; bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; TALLOC_CTX *ctx = talloc_tos(); - bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); + bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn)); struct dptr_struct *dirptr = NULL; struct smbXsrv_connection *xconn = req->xconn; struct smbd_server_connection *sconn = req->sconn; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0539b35bb73..b0616f15ade 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2710,7 +2710,7 @@ static void call_trans2findfirst(connection_struct *conn, bool mask_contains_wcard = False; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; - bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); + bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn)); struct dptr_struct *dirptr = NULL; struct smbd_server_connection *sconn = req->sconn; uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP | @@ -3126,7 +3126,7 @@ static void call_trans2findnext(connection_struct *conn, int space_remaining; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; - bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); + bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn)); TALLOC_CTX *ctx = talloc_tos(); struct dptr_struct *dirptr; struct smbd_server_connection *sconn = req->sconn; -- 2.17.1 From 8c5e4161fa4e6cf0cfc8e1c45dc09e82de27685d Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 5 Aug 2019 11:11:14 +0200 Subject: [PATCH 305/376] s3:smbd: Fix sync dosmode fallback in async dosmode codepath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=14070 RN: Fix sync dosmode fallback in async dosmode codepath Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Tue Aug 6 15:40:18 UTC 2019 on sn-devel-184 (cherry picked from commit 5d4aa6e867044e6b58b45acde32ac35e1d0a7765) --- source3/smbd/dosmode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index d722c022fe9..bdcdda69ac8 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -917,7 +917,11 @@ static void dos_mode_at_vfs_get_dosmode_done(struct tevent_req *subreq) return; } - smb_path = synthetic_smb_fname(state, path, NULL, NULL, 0); + smb_path = synthetic_smb_fname(state, + path, + NULL, + &state->smb_fname->st, + 0); if (tevent_req_nomem(path, req)) { return; } -- 2.17.1 From fb118393f39a2111b75180d035d3082334ccf8f3 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 25 Oct 2019 15:41:40 +0200 Subject: [PATCH 306/376] torture: expand test "vfs.fruit.resource fork IO" to check size Reveals a bug where the resource fork size is capped at 65454 bytes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14171 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit b63069db9fb6efb33b7b917cd5b0ee06b0da9cdc) --- selftest/knownfail.d/samba3.vfs.fruit | 3 +++ source4/torture/vfs/fruit.c | 29 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit index 6307e2b3404..6982e100861 100644 --- a/selftest/knownfail.d/samba3.vfs.fruit +++ b/selftest/knownfail.d/samba3.vfs.fruit @@ -1,2 +1,5 @@ ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) +^samba3.vfs.fruit fruit_delete_empty_adfiles.resource fork IO\(nt4_dc\) +^samba3.vfs.fruit metadata_stream.resource fork IO\(nt4_dc\) +^samba3.vfs.fruit metadata_netatalk.resource fork IO\(nt4_dc\) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index e3d8539595d..0dedb92579f 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -2397,6 +2397,35 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx, fname, AFPRESOURCE_STREAM_NAME, (off_t)64*1024*1024, 10, rfork_content); + /* Check size after write */ + + ZERO_STRUCT(io); + io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; + io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE | + SEC_FILE_WRITE_ATTRIBUTE; + io.smb2.in.fname = rfork; + status = smb2_create(tree, mem_ctx, &(io.smb2)); + CHECK_STATUS(status, NT_STATUS_OK); + filehandle = io.smb2.out.file.handle; + + torture_comment(tctx, "(%s) check resource fork size after write\n", + __location__); + + ZERO_STRUCT(finfo); + finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION; + finfo.generic.in.file.handle = filehandle; + status = smb2_getinfo_file(tree, mem_ctx, &finfo); + CHECK_STATUS(status, NT_STATUS_OK); + if (finfo.all_info.out.size != 64*1024*1024 + 10) { + torture_result(tctx, TORTURE_FAIL, + "(%s) Incorrect resource fork size\n", + __location__); + ret = false; + smb2_util_close(tree, filehandle); + goto done; + } + smb2_util_close(tree, filehandle); + ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME, (off_t)64*1024*1024, 10, 0, 10, rfork_content); -- 2.17.1 From d47b2cb8a224a7133d47ff0df78abe172480b144 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 24 Oct 2019 17:17:28 +0200 Subject: [PATCH 307/376] vfs_fruit: fix a long line BUG: https://bugzilla.samba.org/show_bug.cgi?id=14171 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (backported from commit f0c8ac47a4608eabeae334d39885aab98198b753) --- source3/modules/vfs_fruit.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 85c7af21d58..049a6d72668 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1697,7 +1697,11 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, ad->ad_data = p_ad; } - len = SMB_VFS_NEXT_PREAD(handle, ad->ad_fsp, ad->ad_data, talloc_array_length(ad->ad_data), 0); + len = SMB_VFS_NEXT_PREAD(handle, + ad->ad_fsp, + ad->ad_data, + talloc_array_length(ad->ad_data), + 0); if (len != talloc_array_length(ad->ad_data)) { DBG_NOTICE("%s %s: bad size: %zd\n", smb_fname->base_name, strerror(errno), len); -- 2.17.1 From 1fa47717494f63413c1fe6a1e348605bdc2a17f3 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 24 Oct 2019 17:26:08 +0200 Subject: [PATCH 308/376] vfs_fruit: README.Coding fix: multi-line if expression Also remove a TAB. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14171 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (backported from commit baaaf59e948df625b01fa8b6317ab5c3babb4e8f) --- source3/modules/vfs_fruit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 049a6d72668..4e5d61d9baa 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1719,7 +1719,8 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, if ((ad_getentryoff(ad, ADEID_FINDERI) != ADEDOFF_FINDERI_DOT_UND) || (ad_getentrylen(ad, ADEID_FINDERI) < ADEDLEN_FINDERI) - || (ad_getentryoff(ad, ADEID_RFORK) < ADEDOFF_RFORK_DOT_UND)) { + || (ad_getentryoff(ad, ADEID_RFORK) < ADEDOFF_RFORK_DOT_UND)) + { DBG_ERR("invalid AppleDouble resource %s\n", smb_fname->base_name); errno = EINVAL; -- 2.17.1 From c00a8959b6ff474478a40469cd5ea367c7037be4 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 25 Oct 2019 15:21:32 +0200 Subject: [PATCH 309/376] lib/adouble: drop ad_data reallocate logic Simply set the buffer size to AD_XATTR_MAX_HDR_SIZE. When reading the AppleDouble file, read up to AD_XATTR_MAX_HDR_SIZE from the file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14171 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (backported from commit 9a3da6bebcdb924ca2027337544d79ac2088677e) --- source3/modules/vfs_fruit.c | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 4e5d61d9baa..131513423bd 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1664,8 +1664,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, struct adouble *ad, const struct smb_filename *smb_fname) { - char *p_ad = NULL; - size_t size; + size_t to_read; ssize_t len; int ret; bool ok; @@ -1677,32 +1676,17 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, return -1; } - /* - * AppleDouble file header content and size, two cases: - * - * - without xattrs it is exactly AD_DATASZ_DOT_UND (82) bytes large - * - with embedded xattrs it can be larger, up to AD_XATTR_MAX_HDR_SIZE - * - * Read as much as we can up to AD_XATTR_MAX_HDR_SIZE. - */ - size = ad->ad_fsp->fsp_name->st.st_ex_size; - if (size > talloc_array_length(ad->ad_data)) { - if (size > AD_XATTR_MAX_HDR_SIZE) { - size = AD_XATTR_MAX_HDR_SIZE; - } - p_ad = talloc_realloc(ad, ad->ad_data, char, size); - if (p_ad == NULL) { - return -1; - } - ad->ad_data = p_ad; + to_read = ad->ad_fsp->fsp_name->st.st_ex_size; + if (to_read > AD_XATTR_MAX_HDR_SIZE) { + to_read = AD_XATTR_MAX_HDR_SIZE; } len = SMB_VFS_NEXT_PREAD(handle, ad->ad_fsp, ad->ad_data, - talloc_array_length(ad->ad_data), + to_read, 0); - if (len != talloc_array_length(ad->ad_data)) { + if (len != to_read) { DBG_NOTICE("%s %s: bad size: %zd\n", smb_fname->base_name, strerror(errno), len); return -1; @@ -1800,7 +1784,23 @@ static struct adouble *ad_alloc(TALLOC_CTX *ctx, adsize = AD_DATASZ_XATTR; break; case ADOUBLE_RSRC: - adsize = AD_DATASZ_DOT_UND; + /* + * AppleDouble ._ file case, optimize for fewer (but larger) + * IOs. Two cases: + * + * - without xattrs size of the header is exactly + * AD_DATASZ_DOT_UND (82) bytes + * + * - with embedded xattrs it can be larger, up to + * AD_XATTR_MAX_HDR_SIZE + * + * Larger headers are not supported, but this is a reasonable + * limit that is also employed by the macOS client. + * + * We used the largest possible size to be able to read the full + * header with one IO. + */ + adsize = AD_XATTR_MAX_HDR_SIZE; break; default: return NULL; -- 2.17.1 From ce18ef9e54530a96d33a4ec842bd599a4a51a7b8 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 24 Oct 2019 17:15:18 +0200 Subject: [PATCH 310/376] lib/adouble: pass filesize to ad_unpack() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ad_unpack() needs the filesize, not the capped IO size we're using in the caller to read up to "size" bystem from the ._ AppleDouble file. This fixes a regression introduced by bdc257a1cbac7e8c73a084b618ba642476807483 for bug 13968. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14171 RN: vfs_fruit returns capped resource fork length Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Wed Oct 30 14:52:34 UTC 2019 on sn-devel-184 (backported from commit f3df83a2c346d945487a27a9d258ee6331ea7dbb) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Fri Nov 8 13:52:49 UTC 2019 on sn-devel-184 --- selftest/knownfail.d/samba3.vfs.fruit | 3 --- source3/modules/vfs_fruit.c | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit index 6982e100861..6307e2b3404 100644 --- a/selftest/knownfail.d/samba3.vfs.fruit +++ b/selftest/knownfail.d/samba3.vfs.fruit @@ -1,5 +1,2 @@ ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) -^samba3.vfs.fruit fruit_delete_empty_adfiles.resource fork IO\(nt4_dc\) -^samba3.vfs.fruit metadata_stream.resource fork IO\(nt4_dc\) -^samba3.vfs.fruit metadata_netatalk.resource fork IO\(nt4_dc\) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 131513423bd..b8ede0cdfdb 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1693,7 +1693,9 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, } /* Now parse entries */ - ok = ad_unpack(ad, ADEID_NUM_DOT_UND, size); + ok = ad_unpack(ad, + ADEID_NUM_DOT_UND, + ad->ad_fsp->fsp_name->st.st_ex_size); if (!ok) { DBG_ERR("invalid AppleDouble resource %s\n", smb_fname->base_name); -- 2.17.1 From b4e5ae5bcba5027541ecc5a4c92000bb4766c47a Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 12:43:25 +0100 Subject: [PATCH 311/376] s3:printing: fix a long line BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (cherry picked from commit dcb555c06a6341871b691dab3758e7de04110282) --- source3/printing/printing.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/printing/printing.c b/source3/printing/printing.c index e6caaa1222f..42036a56bb5 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -2867,7 +2867,8 @@ WERROR print_job_start(const struct auth_session_info *server_info, fstrcpy(pjob.clientmachine, clientmachine); fstrcpy(pjob.user, lp_printjob_username(snum)); - standard_sub_advanced(sharename, server_info->unix_info->sanitized_username, + standard_sub_advanced(sharename, + server_info->unix_info->sanitized_username, path, server_info->unix_token->gid, server_info->unix_info->sanitized_username, server_info->info->domain_name, -- 2.17.1 From 69faa68148bf93e7416160984dc81a3a50728641 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 12:44:45 +0100 Subject: [PATCH 312/376] s3: replace standard_sub_advanced with talloc_sub_advanced in one place BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (cherry picked from commit 81ae199bb72886f2f1ed87b22b4c75b6b99c72f6) --- source3/printing/printing.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 42036a56bb5..0ad07046850 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -2819,7 +2819,7 @@ WERROR print_job_start(const struct auth_session_info *server_info, struct spoolss_DeviceMode *devmode, uint32_t *_jobid) { uint32_t jobid; - char *path; + char *path = NULL, *userstr = NULL; struct printjob pjob; const char *sharename = lp_const_servicename(snum); struct tdb_print_db *pdb = get_print_db_byname(sharename); @@ -2866,13 +2866,19 @@ WERROR print_job_start(const struct auth_session_info *server_info, fstrcpy(pjob.clientmachine, clientmachine); - fstrcpy(pjob.user, lp_printjob_username(snum)); - standard_sub_advanced(sharename, + userstr = talloc_sub_advanced(talloc_tos(), + sharename, server_info->unix_info->sanitized_username, path, server_info->unix_token->gid, server_info->unix_info->sanitized_username, server_info->info->domain_name, - pjob.user, sizeof(pjob.user)); + lp_printjob_username(snum)); + if (userstr == NULL) { + werr = WERR_NOT_ENOUGH_MEMORY; + goto fail; + } + strlcpy(pjob.user, userstr, sizeof(pjob.user)); + TALLOC_FREE(userstr); fstrcpy(pjob.queuename, lp_const_servicename(snum)); -- 2.17.1 From 58ea968c752d6d7e750b4ffce267be1eb0cd543f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 10:19:13 +0100 Subject: [PATCH 313/376] s3: remove unused function standard_sub_advanced() BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (cherry picked from commit a591de28659919d2afd7ed55106cded6a0d9ab35) --- source3/include/proto.h | 4 ---- source3/lib/substitute.c | 16 ---------------- 2 files changed, 20 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index cb8890d340b..60db3aaa4a1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -185,10 +185,6 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, const char *connectpath, gid_t gid, const char *smb_name, const char *domain_name, const char *str); -void standard_sub_advanced(const char *servicename, const char *user, - const char *connectpath, gid_t gid, - const char *smb_name, const char *domain_name, - char *str, size_t len); /* The following definitions come from lib/sysquotas.c */ diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index ea227c5ab68..a6af5deb381 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -863,22 +863,6 @@ char *talloc_sub_advanced(TALLOC_CTX *ctx, return ret_string; } -void standard_sub_advanced(const char *servicename, const char *user, - const char *connectpath, gid_t gid, - const char *smb_name, const char *domain_name, - char *str, size_t len) -{ - char *s = talloc_sub_advanced(talloc_tos(), - servicename, user, connectpath, - gid, smb_name, domain_name, str); - - if (!s) { - return; - } - strlcpy( str, s, len ); - TALLOC_FREE( s ); -} - /****************************************************************************** version of standard_sub_basic() for string lists; uses talloc_sub_basic() for the work -- 2.17.1 From 90c90fc8a25b041e5213b9695dfc68ed9df37a08 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 12:45:44 +0100 Subject: [PATCH 314/376] s3: rename talloc_sub_advanced() to talloc_sub_full() We currently have the following substitution functions: talloc_sub_basic() talloc_sub_advanced() talloc_sub_basic() currently substitutes a subset of talloc_sub_advanced(). We'll need a function X that only substitutes what talloc_sub_advanced() substitutes *without* what talloc_sub_basic() does. To get there rename talloc_sub_advanced() to talloc_sub_full(). A subsequent commit will then bring back talloc_sub_advanced() as described above. Examples with fictional replacement letters A and B. Currently: talloc_sub_basic: A talloc_sub_advanced: AB New: talloc_sub_basic: A talloc_sub_advanced: B talloc_sub_full: AB BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (backported from commit 4736623c24503b3ca09c76c9dbb134ef833b2f80) --- source3/include/proto.h | 2 +- source3/lib/substitute.c | 4 ++-- source3/modules/vfs_expand_msdfs.c | 2 +- source3/modules/vfs_full_audit.c | 2 +- source3/modules/vfs_recycle.c | 2 +- source3/modules/vfs_virusfilter_utils.c | 2 +- source3/printing/print_generic.c | 2 +- source3/printing/printing.c | 8 ++++---- source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 10 +++++----- source3/smbd/lanman.c | 4 ++-- source3/smbd/service.c | 10 +++++----- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 60db3aaa4a1..b508022925e 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -180,7 +180,7 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, const char *domain, uid_t uid, gid_t gid); -char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, +char *talloc_sub_full(TALLOC_CTX *mem_ctx, const char *servicename, const char *user, const char *connectpath, gid_t gid, const char *smb_name, const char *domain_name, diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index a6af5deb381..80fc43e35c9 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -790,7 +790,7 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -char *talloc_sub_advanced(TALLOC_CTX *ctx, +char *talloc_sub_full(TALLOC_CTX *ctx, const char *servicename, const char *user, const char *connectpath, @@ -804,7 +804,7 @@ char *talloc_sub_advanced(TALLOC_CTX *ctx, a_string = talloc_strdup(talloc_tos(), str); if (a_string == NULL) { - DEBUG(0, ("talloc_sub_advanced: Out of memory!\n")); + DBG_ERR("Out of memory!\n"); return NULL; } diff --git a/source3/modules/vfs_expand_msdfs.c b/source3/modules/vfs_expand_msdfs.c index 598da08c0c8..ccd124ac617 100644 --- a/source3/modules/vfs_expand_msdfs.c +++ b/source3/modules/vfs_expand_msdfs.c @@ -154,7 +154,7 @@ static char *expand_msdfs_target(TALLOC_CTX *ctx, return NULL; } - targethost = talloc_sub_advanced(ctx, + targethost = talloc_sub_full(ctx, lp_servicename(talloc_tos(), SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index f6e11516970..a442563115c 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -485,7 +485,7 @@ static char *audit_prefix(TALLOC_CTX *ctx, connection_struct *conn) if (!prefix) { return NULL; } - result = talloc_sub_advanced(ctx, + result = talloc_sub_full(ctx, lp_servicename(talloc_tos(), SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index e84f0351c87..0b7b820f18b 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -460,7 +460,7 @@ static int recycle_unlink(vfs_handle_struct *handle, bool exist; int rc = -1; - repository = talloc_sub_advanced(NULL, lp_servicename(talloc_tos(), SNUM(conn)), + repository = talloc_sub_full(NULL, lp_servicename(talloc_tos(), SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, conn->session_info->unix_token->gid, diff --git a/source3/modules/vfs_virusfilter_utils.c b/source3/modules/vfs_virusfilter_utils.c index f56fc6ed5d8..8ec61a0c8f2 100644 --- a/source3/modules/vfs_virusfilter_utils.c +++ b/source3/modules/vfs_virusfilter_utils.c @@ -35,7 +35,7 @@ char *virusfilter_string_sub( connection_struct *conn, const char *str) { - return talloc_sub_advanced(mem_ctx, + return talloc_sub_full(mem_ctx, lp_servicename(mem_ctx, SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c index b6b50062caf..9c47d3ff7a5 100644 --- a/source3/printing/print_generic.c +++ b/source3/printing/print_generic.c @@ -72,7 +72,7 @@ static int print_run_command(int snum, const char* printername, bool do_sub, } if (do_sub && snum != -1) { - syscmd = talloc_sub_advanced(ctx, + syscmd = talloc_sub_full(ctx, lp_servicename(talloc_tos(), snum), current_user_info.unix_name, "", diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 0ad07046850..c6bf6ec69dd 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -1724,7 +1724,7 @@ static void print_queue_update(struct messaging_context *msg_ctx, if (!lpqcommand) { return; } - lpqcommand = talloc_sub_advanced(ctx, + lpqcommand = talloc_sub_full(ctx, lp_servicename(talloc_tos(), snum), current_user_info.unix_name, "", @@ -1744,7 +1744,7 @@ static void print_queue_update(struct messaging_context *msg_ctx, if (!lprmcommand) { return; } - lprmcommand = talloc_sub_advanced(ctx, + lprmcommand = talloc_sub_full(ctx, lp_servicename(talloc_tos(), snum), current_user_info.unix_name, "", @@ -2866,7 +2866,7 @@ WERROR print_job_start(const struct auth_session_info *server_info, fstrcpy(pjob.clientmachine, clientmachine); - userstr = talloc_sub_advanced(talloc_tos(), + userstr = talloc_sub_full(talloc_tos(), sharename, server_info->unix_info->sanitized_username, path, server_info->unix_token->gid, @@ -3035,7 +3035,7 @@ NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum, status = NT_STATUS_PRINT_CANCELLED; goto fail; } - lpq_cmd = talloc_sub_advanced(tmp_ctx, + lpq_cmd = talloc_sub_full(tmp_ctx, lp_servicename(talloc_tos(), snum), current_user_info.unix_name, "", diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c index 6246a61672e..3af4cef4bc0 100644 --- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c +++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c @@ -225,7 +225,7 @@ static void init_srv_share_info_1(struct pipes_struct *p, char *remark = lp_comment(p->mem_ctx, snum); if (remark) { - remark = talloc_sub_advanced( + remark = talloc_sub_full( p->mem_ctx, lp_servicename(talloc_tos(), snum), get_current_username(), lp_path(talloc_tos(), snum), p->session_info->unix_token->uid, get_current_username(), @@ -253,7 +253,7 @@ static void init_srv_share_info_2(struct pipes_struct *p, remark = lp_comment(p->mem_ctx, snum); if (remark) { - remark = talloc_sub_advanced( + remark = talloc_sub_full( p->mem_ctx, lp_servicename(talloc_tos(), snum), get_current_username(), lp_path(talloc_tos(), snum), p->session_info->unix_token->uid, get_current_username(), @@ -318,7 +318,7 @@ static void init_srv_share_info_501(struct pipes_struct *p, char *remark = lp_comment(p->mem_ctx, snum); if (remark) { - remark = talloc_sub_advanced( + remark = talloc_sub_full( p->mem_ctx, lp_servicename(talloc_tos(), snum), get_current_username(), lp_path(talloc_tos(), snum), p->session_info->unix_token->uid, get_current_username(), @@ -352,7 +352,7 @@ static void init_srv_share_info_502(struct pipes_struct *p, char *remark = lp_comment(ctx, snum); if (remark) { - remark = talloc_sub_advanced( + remark = talloc_sub_full( p->mem_ctx, lp_servicename(talloc_tos(), snum), get_current_username(), lp_path(talloc_tos(), snum), p->session_info->unix_token->uid, get_current_username(), @@ -393,7 +393,7 @@ static void init_srv_share_info_1004(struct pipes_struct *p, char *remark = lp_comment(p->mem_ctx, snum); if (remark) { - remark = talloc_sub_advanced( + remark = talloc_sub_full( p->mem_ctx, lp_servicename(talloc_tos(), snum), get_current_username(), lp_path(talloc_tos(), snum), p->session_info->unix_token->uid, get_current_username(), diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 50451b2778d..ee6e9a481e2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -115,7 +115,7 @@ static int CopyExpanded(connection_struct *conn, *p_space_remaining = 0; return 0; } - buf = talloc_sub_advanced(ctx, + buf = talloc_sub_full(ctx, lp_servicename(ctx, SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, @@ -166,7 +166,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) if (!buf) { return 0; } - buf = talloc_sub_advanced(ctx, + buf = talloc_sub_full(ctx, lp_servicename(ctx, SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d7c85d8b6ca..fd23d1a2d60 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -583,7 +583,7 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, conn->vuid = vuser->vuid; { - char *s = talloc_sub_advanced(talloc_tos(), + char *s = talloc_sub_full(talloc_tos(), lp_const_servicename(SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, @@ -699,7 +699,7 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, * to below */ /* execute any "root preexec = " line */ if (*lp_root_preexec(talloc_tos(), snum)) { - char *cmd = talloc_sub_advanced(talloc_tos(), + char *cmd = talloc_sub_full(talloc_tos(), lp_const_servicename(SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, @@ -737,7 +737,7 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, /* execute any "preexec = " line */ if (*lp_preexec(talloc_tos(), snum)) { - char *cmd = talloc_sub_advanced(talloc_tos(), + char *cmd = talloc_sub_full(talloc_tos(), lp_const_servicename(SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, @@ -1139,7 +1139,7 @@ void close_cnum(connection_struct *conn, uint64_t vuid) /* execute any "postexec = " line */ if (*lp_postexec(talloc_tos(), SNUM(conn)) && change_to_user(conn, vuid)) { - char *cmd = talloc_sub_advanced(talloc_tos(), + char *cmd = talloc_sub_full(talloc_tos(), lp_const_servicename(SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, @@ -1155,7 +1155,7 @@ void close_cnum(connection_struct *conn, uint64_t vuid) change_to_root_user(); /* execute any "root postexec = " line */ if (*lp_root_postexec(talloc_tos(), SNUM(conn))) { - char *cmd = talloc_sub_advanced(talloc_tos(), + char *cmd = talloc_sub_full(talloc_tos(), lp_const_servicename(SNUM(conn)), conn->session_info->unix_info->unix_name, conn->connectpath, -- 2.17.1 From cbd6426ad519de1d487752ab6fea504e3c671612 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 11:57:39 +0100 Subject: [PATCH 315/376] s3:lib: factor out talloc_sub_advanced() from talloc_sub_full() BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (cherry picked from commit 41ab92b62fbf029374b89f9d0ddf7578981f37cf) --- source3/include/proto.h | 4 ++++ source3/lib/substitute.c | 28 +++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index b508022925e..43a4b8f8b4d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -180,6 +180,10 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, const char *domain, uid_t uid, gid_t gid); +char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, + const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *str); char *talloc_sub_full(TALLOC_CTX *mem_ctx, const char *servicename, const char *user, const char *connectpath, gid_t gid, diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index 80fc43e35c9..95369b838ea 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -790,21 +790,19 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -char *talloc_sub_full(TALLOC_CTX *ctx, +char *talloc_sub_advanced(TALLOC_CTX *ctx, const char *servicename, const char *user, const char *connectpath, gid_t gid, - const char *smb_name, - const char *domain_name, const char *str) { - char *a_string, *ret_string; + char *a_string; char *b, *p, *s; a_string = talloc_strdup(talloc_tos(), str); if (a_string == NULL) { - DBG_ERR("Out of memory!\n"); + DEBUG(0, ("talloc_sub_advanced_only: Out of memory!\n")); return NULL; } @@ -858,6 +856,26 @@ char *talloc_sub_full(TALLOC_CTX *ctx, } } + return a_string; +} + +char *talloc_sub_full(TALLOC_CTX *ctx, + const char *servicename, + const char *user, + const char *connectpath, + gid_t gid, + const char *smb_name, + const char *domain_name, + const char *str) +{ + char *a_string, *ret_string; + + a_string = talloc_sub_advanced(ctx, servicename, user, connectpath, + gid, str); + if (a_string == NULL) { + return NULL; + } + ret_string = talloc_sub_basic(ctx, smb_name, domain_name, a_string); TALLOC_FREE(a_string); return ret_string; -- 2.17.1 From 1f504300bf35d793019eb86d9206eacef7d58d6e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 12:03:31 +0100 Subject: [PATCH 316/376] s3:printing: add a DEBUG statement BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (cherry picked from commit ede00779ab2d881e061adb9d861879e8c68e272b) --- source3/printing/print_generic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c index 9c47d3ff7a5..d3c72dd6a9a 100644 --- a/source3/printing/print_generic.c +++ b/source3/printing/print_generic.c @@ -56,6 +56,8 @@ static int print_run_command(int snum, const char* printername, bool do_sub, return -1; } + DBG_DEBUG("Incoming command '%s'\n", syscmd); + while ((arg = va_arg(ap, char *))) { char *value = va_arg(ap,char *); syscmd = talloc_string_sub(ctx, syscmd, arg, value); -- 2.17.1 From 5d8e92a572796ddaf43b6847c324c77617a9e39d Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 31 Oct 2019 12:46:38 +0100 Subject: [PATCH 317/376] s3:printing: Fix %J substition print_run_command() uses lp_print_command() which internally performs basic substition by calling talloc_sub_basic(). As a result. any of the variables in the "basic set", including "%J" are already substituted. To prevent the unwanted subtitution, we declare all affected configuration options as const, which disabled the basic substition. As a result print_run_command() can run manual substitution on all characters, including %J, in the variadic argument list *before* calling lp_string() to run basic substition which we had disabled before with the const. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13745 Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Thu Nov 7 16:01:21 UTC 2019 on sn-devel-184 (cherry picked from commit 8846887a55b0c97a1639fc6ecb228941cf16b8f2) --- .../smbdotconf/printing/lppausecommand.xml | 1 + docs-xml/smbdotconf/printing/lpqcommand.xml | 1 + .../smbdotconf/printing/lpresumecommand.xml | 1 + docs-xml/smbdotconf/printing/lprmcommand.xml | 1 + docs-xml/smbdotconf/printing/printcommand.xml | 1 + .../smbdotconf/printing/queuepausecommand.xml | 1 + .../printing/queueresumecommand.xml | 1 + source3/printing/print_generic.c | 19 +++++++++++-------- source3/printing/printing.c | 8 ++++---- source3/utils/testparm.c | 2 +- 10 files changed, 23 insertions(+), 13 deletions(-) diff --git a/docs-xml/smbdotconf/printing/lppausecommand.xml b/docs-xml/smbdotconf/printing/lppausecommand.xml index 3aa134c4377..f2518d3def0 100644 --- a/docs-xml/smbdotconf/printing/lppausecommand.xml +++ b/docs-xml/smbdotconf/printing/lppausecommand.xml @@ -1,6 +1,7 @@ This parameter specifies the command to be diff --git a/docs-xml/smbdotconf/printing/lpqcommand.xml b/docs-xml/smbdotconf/printing/lpqcommand.xml index f3c17f286d1..f0161f3448d 100644 --- a/docs-xml/smbdotconf/printing/lpqcommand.xml +++ b/docs-xml/smbdotconf/printing/lpqcommand.xml @@ -1,6 +1,7 @@ This parameter specifies the command to be diff --git a/docs-xml/smbdotconf/printing/lpresumecommand.xml b/docs-xml/smbdotconf/printing/lpresumecommand.xml index 153ba76a693..2cee574bd73 100644 --- a/docs-xml/smbdotconf/printing/lpresumecommand.xml +++ b/docs-xml/smbdotconf/printing/lpresumecommand.xml @@ -1,6 +1,7 @@ This parameter specifies the command to be diff --git a/docs-xml/smbdotconf/printing/lprmcommand.xml b/docs-xml/smbdotconf/printing/lprmcommand.xml index 4b7f3dd75c3..a595c1225c0 100644 --- a/docs-xml/smbdotconf/printing/lprmcommand.xml +++ b/docs-xml/smbdotconf/printing/lprmcommand.xml @@ -1,6 +1,7 @@ This parameter specifies the command to be diff --git a/docs-xml/smbdotconf/printing/printcommand.xml b/docs-xml/smbdotconf/printing/printcommand.xml index c84e45f404d..42a7188cb9a 100644 --- a/docs-xml/smbdotconf/printing/printcommand.xml +++ b/docs-xml/smbdotconf/printing/printcommand.xml @@ -1,6 +1,7 @@ After a print job has finished spooling to diff --git a/docs-xml/smbdotconf/printing/queuepausecommand.xml b/docs-xml/smbdotconf/printing/queuepausecommand.xml index 5dca45657cc..600a2baa621 100644 --- a/docs-xml/smbdotconf/printing/queuepausecommand.xml +++ b/docs-xml/smbdotconf/printing/queuepausecommand.xml @@ -1,6 +1,7 @@ This parameter specifies the command to be diff --git a/docs-xml/smbdotconf/printing/queueresumecommand.xml b/docs-xml/smbdotconf/printing/queueresumecommand.xml index 4a573330048..431295a804e 100644 --- a/docs-xml/smbdotconf/printing/queueresumecommand.xml +++ b/docs-xml/smbdotconf/printing/queueresumecommand.xml @@ -1,6 +1,7 @@ This parameter specifies the command to be diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c index d3c72dd6a9a..574f357c76c 100644 --- a/source3/printing/print_generic.c +++ b/source3/printing/print_generic.c @@ -73,14 +73,17 @@ static int print_run_command(int snum, const char* printername, bool do_sub, return -1; } + syscmd = lp_string(ctx, syscmd); + if (syscmd == NULL) { + return -1; + } + if (do_sub && snum != -1) { - syscmd = talloc_sub_full(ctx, + syscmd = talloc_sub_advanced(ctx, lp_servicename(talloc_tos(), snum), current_user_info.unix_name, "", get_current_gid(NULL), - get_current_username(), - current_user_info.domain, syscmd); if (!syscmd) { return -1; @@ -120,7 +123,7 @@ static int generic_job_pause(int snum, struct printjob *pjob) /* need to pause the spooled entry */ slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); return print_run_command(snum, lp_printername(talloc_tos(), snum), True, - lp_lppause_command(talloc_tos(), snum), NULL, + lp_lppause_command(snum), NULL, "%j", jobstr, NULL); } @@ -135,7 +138,7 @@ static int generic_job_resume(int snum, struct printjob *pjob) /* need to pause the spooled entry */ slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); return print_run_command(snum, lp_printername(talloc_tos(), snum), True, - lp_lpresume_command(talloc_tos(), snum), NULL, + lp_lpresume_command(snum), NULL, "%j", jobstr, NULL); } @@ -257,7 +260,7 @@ static int generic_job_submit(int snum, struct printjob *pjob, /* send it to the system spooler */ ret = print_run_command(snum, lp_printername(talloc_tos(), snum), True, - lp_print_command(talloc_tos(), snum), NULL, + lp_print_command(snum), NULL, "%s", p, "%J", jobname, "%f", p, @@ -310,7 +313,7 @@ static int generic_job_submit(int snum, struct printjob *pjob, static int generic_queue_pause(int snum) { return print_run_command(snum, lp_printername(talloc_tos(), snum), True, - lp_queuepause_command(talloc_tos(), snum), NULL, NULL); + lp_queuepause_command(snum), NULL, NULL); } /**************************************************************************** @@ -319,7 +322,7 @@ static int generic_queue_pause(int snum) static int generic_queue_resume(int snum) { return print_run_command(snum, lp_printername(talloc_tos(), snum), True, - lp_queueresume_command(talloc_tos(), snum), NULL, NULL); + lp_queueresume_command(snum), NULL, NULL); } /**************************************************************************** diff --git a/source3/printing/printing.c b/source3/printing/printing.c index c6bf6ec69dd..0f4db52e011 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -1717,7 +1717,7 @@ static void print_queue_update(struct messaging_context *msg_ctx, /* don't strip out characters like '$' from the printername */ lpqcommand = talloc_string_sub2(ctx, - lp_lpq_command(talloc_tos(), snum), + lp_lpq_command(snum), "%p", lp_printername(talloc_tos(), snum), false, false, false); @@ -1737,7 +1737,7 @@ static void print_queue_update(struct messaging_context *msg_ctx, } lprmcommand = talloc_string_sub2(ctx, - lp_lprm_command(talloc_tos(), snum), + lp_lprm_command(snum), "%p", lp_printername(talloc_tos(), snum), false, false, false); @@ -2199,7 +2199,7 @@ static bool print_job_delete1(struct tevent_context *ev, { result = (*(current_printif->job_delete))( lp_printername(talloc_tos(), snum), - lp_lprm_command(talloc_tos(), snum), + lp_lprm_command(snum), pjob); /* Delete the tdb entry if the delete succeeded or the job hasn't @@ -3027,7 +3027,7 @@ NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum, /* don't strip out characters like '$' from the printername */ lpq_cmd = talloc_string_sub2(tmp_ctx, - lp_lpq_command(talloc_tos(), snum), + lp_lpq_command(snum), "%p", lp_printername(talloc_tos(), snum), false, false, false); diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index 9ba625da4bf..f4e94b6ef74 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -611,7 +611,7 @@ static void do_per_share_checks(int s) "excludes octal 010 (S_IXGRP).\n\n", lp_servicename(talloc_tos(), s)); } - if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') { + if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(s)) != '\0') { fprintf(stderr, "Warning: Service %s defines a print command, but " "parameter is ignored when using CUPS libraries.\n\n", -- 2.17.1 From 4b249abae3b48761ab0bc362c98ae52728a664ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Oct 2019 12:11:01 -0700 Subject: [PATCH 318/376] s3: libsmb: Ensure we don't call cli_RNetShareEnum() on an SMB1 connection. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14174 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit 1cfcad6283da855d3e97237a7a6fd6f4d2436ee2) --- source3/libsmb/libsmb_dir.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index df606c4adfe..ab20a127c49 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -856,7 +856,12 @@ SMBC_opendir_ctx(SMBCCTX *context, list_fn, (void *)dir); if (rc != 0 && - lp_client_min_protocol() <= PROTOCOL_NT1) { + smbXcli_conn_protocol(srv->cli->conn) <= + PROTOCOL_NT1) { + /* + * Only call cli_RNetShareEnum() + * on SMB1 connections, not SMB2+. + */ rc = cli_RNetShareEnum(srv->cli, list_fn, (void *)dir); -- 2.17.1 From 78ead63dbff6667a933cfc0b7d00ff1ec77c564c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Oct 2019 12:11:49 -0700 Subject: [PATCH 319/376] s3: utils: smbtree. Ensure we don't call cli_RNetShareEnum() on an SMB1 connection. Last unprotected call of cli_RNetShareEnum(). Not a libsmbclient bug here but might as well fix the last caller as part of the fix for the bug. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14174 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme (cherry picked from commit f30b8b3aa1309e9daeb9a3601b537dead81e5dbb) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Nov 13 14:45:53 UTC 2019 on sn-devel-184 --- source3/utils/smbtree.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c index 9f589b4060f..de32924489f 100644 --- a/source3/utils/smbtree.c +++ b/source3/utils/smbtree.c @@ -26,6 +26,7 @@ #include "libsmb/libsmb.h" #include "libsmb/namequery.h" #include "libsmb/clirap.h" +#include "../libcli/smb/smbXcli_base.h" static int use_bcast; @@ -231,6 +232,10 @@ static bool get_shares(char *server_name, const struct user_auth_info *user_info if (get_rpc_shares(cli, add_name, &shares)) return True; + if (smbXcli_conn_protocol(cli->conn) > PROTOCOL_NT1) { + return false; + } + if (!cli_RNetShareEnum(cli, add_name, &shares)) return False; -- 2.17.1 From 9010e9f373e648811f04bd7d2d9a6fc799bb903c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Oct 2019 14:38:35 -0700 Subject: [PATCH 320/376] s3: libsmb: Ensure return from net_share_enum_rpc() sets cli->raw_status on error. Convert net_share_enum_rpc() to return an NTSTATUS and ensure the status is set correctly on error so SMBC_errno() can return it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14176 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Tue Nov 5 12:36:48 UTC 2019 on sn-devel-184 (cherry picked from commit ff47cc661d432a9337ade9a232a4f49164652812) --- source3/libsmb/libsmb_dir.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index ab20a127c49..14bfcdec6a7 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -350,7 +350,7 @@ dir_list_fn(const char *mnt, return NT_STATUS_OK; } -static int +static NTSTATUS net_share_enum_rpc(struct cli_state *cli, void (*fn)(const char *name, uint32_t type, @@ -377,7 +377,7 @@ net_share_enum_rpc(struct cli_state *cli, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); - return -1; + goto done; } ZERO_STRUCT(info_ctr); @@ -400,18 +400,18 @@ net_share_enum_rpc(struct cli_state *cli, /* Was it successful? */ if (!NT_STATUS_IS_OK(nt_status)) { /* Nope. Go clean up. */ - result = ntstatus_to_werror(nt_status); goto done; } if (!W_ERROR_IS_OK(result)) { /* Nope. Go clean up. */ + nt_status = werror_to_ntstatus(result); goto done; } if (total_entries == 0) { /* Nope. Go clean up. */ - result = WERR_GEN_FAILURE; + nt_status = NT_STATUS_NOT_FOUND; goto done; } @@ -436,7 +436,7 @@ done: TALLOC_FREE(pipe_hnd); /* Tell 'em if it worked */ - return W_ERROR_IS_OK(result) ? 0 : -1; + return nt_status; } @@ -825,7 +825,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } } else if (srv || (resolve_name(server, &rem_ss, 0x20, false))) { - int rc; + NTSTATUS status; /* * If we hadn't found the server, get one now @@ -852,27 +852,38 @@ SMBC_opendir_ctx(SMBCCTX *context, /* List the shares ... */ - rc = net_share_enum_rpc(srv->cli, + status = net_share_enum_rpc(srv->cli, list_fn, (void *)dir); - if (rc != 0 && + if (!NT_STATUS_IS_OK(status) && smbXcli_conn_protocol(srv->cli->conn) <= PROTOCOL_NT1) { /* * Only call cli_RNetShareEnum() * on SMB1 connections, not SMB2+. */ - rc = cli_RNetShareEnum(srv->cli, + int rc = cli_RNetShareEnum(srv->cli, list_fn, (void *)dir); + if (rc != 0) { + status = cli_nt_error(srv->cli); + } else { + status = NT_STATUS_OK; + } } - if (rc != 0) { - errno = cli_errno(srv->cli); + if (!NT_STATUS_IS_OK(status)) { + /* + * Set cli->raw_status so SMBC_errno() + * will correctly return the error. + */ + srv->cli->raw_status = status; if (dir != NULL) { SAFE_FREE(dir->fname); SAFE_FREE(dir); } TALLOC_FREE(frame); + errno = map_errno_from_nt_status( + status); return NULL; } } else { -- 2.17.1 From 83299928bbfb7bbd2b28b07cf6fe582b2a4e616e Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 30 Oct 2019 13:15:48 -0700 Subject: [PATCH 321/376] wscript: Fix build with system heimdal Ubuntu has heimdal include files in /usr/include/heimdal. As the kerberos include files are pulled into many files through indirect includes, add the discovered include paths to EXTRA_INCLUDES to always have them available. Also set USING_SYSTEM_KRB5 when enabling the system heimdal build, to correctly handle the inclusion of the krb5-types.h file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Christof Schmitt Reviewed-by: Andrew Bartlett (cherry picked from commit be2d90b60d19eca408b60fe4e1b49f9b418f1b97) --- wscript_configure_system_heimdal | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wscript_configure_system_heimdal b/wscript_configure_system_heimdal index 0ff6dad2f55..235fa1912b7 100644 --- a/wscript_configure_system_heimdal +++ b/wscript_configure_system_heimdal @@ -18,6 +18,7 @@ if krb5_config: elif l.startswith("includedir="): include_path = l.strip()[len("includedir="):] heimdal_includedirs.append(include_path) + conf.ADD_EXTRA_INCLUDES(include_path) conf.define('HEIMDAL_KRB5_TYPES_PATH', include_path + "/krb5-types.h") finally: @@ -97,3 +98,5 @@ finally: check_system_heimdal_binary("compile_et") check_system_heimdal_binary("asn1_compile") + +conf.define('USING_SYSTEM_KRB5', 1) -- 2.17.1 From 95f267704e70171a5dbf5784c745de07c2c1b001 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sat, 9 Nov 2019 15:36:32 +0000 Subject: [PATCH 322/376] selftest: system-heimdal: workaround upstream "host" canon bug BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Isaac Boukris Reviewed-by: Christof Schmitt Reviewed-by: Andrew Bartlett (cherry picked from commit 15ddd95d94688ed742a2965c4b269d7c84e2d858) --- selftest/target/Samba.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index c30f6fe33ce..2d0378d1b92 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -252,6 +252,7 @@ sub mk_krb5_conf($$) $ctx->{dnsname}, $ctx->{domain}, $ctx->{kdc_ipv4}); + my $lc_domain = lc($ctx->{domain}); print KRB5CONF " #Generated krb5.conf for $ctx->{realm} @@ -263,6 +264,11 @@ sub mk_krb5_conf($$) forwardable = yes allow_weak_crypto = yes + name_canon_rules=as-is:realm=$ctx->{realm} + name_canon_rules=as-is:realm=$ctx->{dnsname} + name_canon_rules=as-is:realm=$ctx->{domain} + name_canon_rules=as-is:realm=$lc_domain + # We are running on the same machine, do not correct # system clock differences kdc_timesync = 0 -- 2.17.1 From 060ff2dd504e1e4b2e4f6daf456cdd38b8879337 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 11 Nov 2019 13:08:28 -0700 Subject: [PATCH 323/376] krb5_plugin: Use C99 initializer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Christof Schmitt Reviewed-by: Andrew Bartlett (cherry picked from commit 1aef796e302058ad3327613964fa89abaf940c1c) --- nsswitch/krb5_plugin/winbind_krb5_locator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nsswitch/krb5_plugin/winbind_krb5_locator.c b/nsswitch/krb5_plugin/winbind_krb5_locator.c index 518c871b248..a31c0822370 100644 --- a/nsswitch/krb5_plugin/winbind_krb5_locator.c +++ b/nsswitch/krb5_plugin/winbind_krb5_locator.c @@ -409,10 +409,10 @@ static krb5_error_code smb_krb5_locator_lookup(void *private_data, #endif const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = { - 0, /* version */ - smb_krb5_locator_init, - smb_krb5_locator_close, - smb_krb5_locator_lookup, + .minor_version = 0, + .init = smb_krb5_locator_init, + .fini = smb_krb5_locator_close, + .lookup = smb_krb5_locator_lookup, }; #endif -- 2.17.1 From ce4ab72c01f08e217f489a89fddb8b9428ecbc6e Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 11 Nov 2019 13:37:25 -0700 Subject: [PATCH 324/376] krb5_plugin: Fix developer build with newer heimdal system library Newer heimdal versions provide a different locator plugin interface. The function pointer for the old method has been renamed. Use an ifdef to initialize the correct pointer. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Christof Schmitt Reviewed-by: Andrew Bartlett (cherry picked from commit 85d23236200dbe013c09a4f23d982ef1baac240d) --- nsswitch/krb5_plugin/winbind_krb5_locator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nsswitch/krb5_plugin/winbind_krb5_locator.c b/nsswitch/krb5_plugin/winbind_krb5_locator.c index a31c0822370..d08cdf72a59 100644 --- a/nsswitch/krb5_plugin/winbind_krb5_locator.c +++ b/nsswitch/krb5_plugin/winbind_krb5_locator.c @@ -412,7 +412,11 @@ const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = { .minor_version = 0, .init = smb_krb5_locator_init, .fini = smb_krb5_locator_close, +#ifdef KRB5_PLUGIN_LOCATE_VERSION_2 + .old_lookup = smb_krb5_locator_lookup, +#else .lookup = smb_krb5_locator_lookup, +#endif }; #endif -- 2.17.1 From af83d6adf94ae78a55f84a8743b2191b591d43a5 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 30 Oct 2019 13:45:55 -0700 Subject: [PATCH 325/376] autobuild: Add test for build with system heimdal library The configure option --with-system-heimdalkrb5 requires --without-ad-dc. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Christof Schmitt Reviewed-by: Andrew Bartlett (cherry picked from commit 7965a204d68196acddf553959bb3407125baf31d) --- script/autobuild.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/script/autobuild.py b/script/autobuild.py index ef75f507add..cf665bd6a7c 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -124,6 +124,7 @@ builddirs = { "samba": ".", "samba-nt4": ".", "samba-fileserver": ".", + "samba-ktest-heimdal": ".", "samba-ad-member": ".", "samba-xc": ".", "samba-o3": ".", @@ -293,6 +294,17 @@ tasks = { ("check-clean-tree", "script/clean-source-tree.sh"), ], + "samba-ktest-heimdal": [ + ("random-sleep", random_sleep(300, 900)), + ("configure", "./configure.developer --without-ad-dc --with-system-heimdalkrb5 --with-selftest-prefix=./bin/ab" + samba_configure_params), + ("make", "make -j"), + ("test", make_test(include_envs=[ + "ktest", + ])), + ("lcov", LCOV_CMD), + ("check-clean-tree", "script/clean-source-tree.sh"), + ], + "samba-ad-member": [ ("random-sleep", random_sleep(300, 900)), ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params), -- 2.17.1 From 7d7e63264932d8312135017a505e5d4315952afb Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 30 Oct 2019 13:49:55 -0700 Subject: [PATCH 326/376] bootstrap: Add heimdal-multidev for Debian and Ubuntu This is required for testing the build with the configure option --with-system-heimdalkrb5. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Christof Schmitt Reviewed-by: Andrew Bartlett (cherry picked from commit 2efc243f1ad09eae46f6f99fb0646ecd4356c3f9) --- .gitlab-ci.yml | 2 +- bootstrap/config.py | 1 + bootstrap/generated-dists/debian7/bootstrap.sh | 1 + bootstrap/generated-dists/debian7/packages.yml | 1 + bootstrap/generated-dists/debian8/bootstrap.sh | 1 + bootstrap/generated-dists/debian8/packages.yml | 1 + bootstrap/generated-dists/debian9/bootstrap.sh | 1 + bootstrap/generated-dists/debian9/packages.yml | 1 + bootstrap/generated-dists/ubuntu1404/bootstrap.sh | 1 + bootstrap/generated-dists/ubuntu1404/packages.yml | 1 + bootstrap/generated-dists/ubuntu1604/bootstrap.sh | 1 + bootstrap/generated-dists/ubuntu1604/packages.yml | 1 + bootstrap/generated-dists/ubuntu1804/bootstrap.sh | 1 + bootstrap/generated-dists/ubuntu1804/packages.yml | 1 + bootstrap/sha1sum.txt | 2 +- 15 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 313ae01fa69..263a13738e2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 339a70ba1881feec94109c5c4eafacf4ff6c43bc + SAMBA_CI_CONTAINER_TAG: 970e3a86b8a9dc10a0a3ec716ab355eb9664dc38 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. diff --git a/bootstrap/config.py b/bootstrap/config.py index 9126961fc93..a83a3efb983 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -102,6 +102,7 @@ PKGS = [ ('libunwind-dev', 'libunwind-devel'), # for back trace ('libglib2.0-dev', 'glib2-devel'), ('libicu-dev', 'libicu-devel'), + ('heimdal-multidev', ''), # NAME1, NAME2 # for debian, locales provide locale support with language packs diff --git a/bootstrap/generated-dists/debian7/bootstrap.sh b/bootstrap/generated-dists/debian7/bootstrap.sh index 4e126cf5e8e..fcba67cb16f 100755 --- a/bootstrap/generated-dists/debian7/bootstrap.sh +++ b/bootstrap/generated-dists/debian7/bootstrap.sh @@ -30,6 +30,7 @@ apt-get -y install \ git \ glusterfs-common \ gzip \ + heimdal-multidev \ hostname \ htop \ krb5-config \ diff --git a/bootstrap/generated-dists/debian7/packages.yml b/bootstrap/generated-dists/debian7/packages.yml index 667825c283e..62fd54b1197 100644 --- a/bootstrap/generated-dists/debian7/packages.yml +++ b/bootstrap/generated-dists/debian7/packages.yml @@ -19,6 +19,7 @@ packages: - git - glusterfs-common - gzip + - heimdal-multidev - hostname - htop - krb5-config diff --git a/bootstrap/generated-dists/debian8/bootstrap.sh b/bootstrap/generated-dists/debian8/bootstrap.sh index 4c8c65223f9..54e3f78db93 100755 --- a/bootstrap/generated-dists/debian8/bootstrap.sh +++ b/bootstrap/generated-dists/debian8/bootstrap.sh @@ -30,6 +30,7 @@ apt-get -y install \ git \ glusterfs-common \ gzip \ + heimdal-multidev \ hostname \ htop \ krb5-config \ diff --git a/bootstrap/generated-dists/debian8/packages.yml b/bootstrap/generated-dists/debian8/packages.yml index a2d4bdb0638..a65ca2f5d05 100644 --- a/bootstrap/generated-dists/debian8/packages.yml +++ b/bootstrap/generated-dists/debian8/packages.yml @@ -19,6 +19,7 @@ packages: - git - glusterfs-common - gzip + - heimdal-multidev - hostname - htop - krb5-config diff --git a/bootstrap/generated-dists/debian9/bootstrap.sh b/bootstrap/generated-dists/debian9/bootstrap.sh index fa7051a67e1..4bc421437e6 100755 --- a/bootstrap/generated-dists/debian9/bootstrap.sh +++ b/bootstrap/generated-dists/debian9/bootstrap.sh @@ -30,6 +30,7 @@ apt-get -y install \ git \ glusterfs-common \ gzip \ + heimdal-multidev \ hostname \ htop \ krb5-config \ diff --git a/bootstrap/generated-dists/debian9/packages.yml b/bootstrap/generated-dists/debian9/packages.yml index 1e3bd0c380c..0021d64db62 100644 --- a/bootstrap/generated-dists/debian9/packages.yml +++ b/bootstrap/generated-dists/debian9/packages.yml @@ -19,6 +19,7 @@ packages: - git - glusterfs-common - gzip + - heimdal-multidev - hostname - htop - krb5-config diff --git a/bootstrap/generated-dists/ubuntu1404/bootstrap.sh b/bootstrap/generated-dists/ubuntu1404/bootstrap.sh index 65625604f4b..34c7726e50c 100755 --- a/bootstrap/generated-dists/ubuntu1404/bootstrap.sh +++ b/bootstrap/generated-dists/ubuntu1404/bootstrap.sh @@ -29,6 +29,7 @@ apt-get -y install \ gdb \ git \ gzip \ + heimdal-multidev \ hostname \ htop \ krb5-config \ diff --git a/bootstrap/generated-dists/ubuntu1404/packages.yml b/bootstrap/generated-dists/ubuntu1404/packages.yml index 8838828d7b8..5dd5d008c6e 100644 --- a/bootstrap/generated-dists/ubuntu1404/packages.yml +++ b/bootstrap/generated-dists/ubuntu1404/packages.yml @@ -18,6 +18,7 @@ packages: - gdb - git - gzip + - heimdal-multidev - hostname - htop - krb5-config diff --git a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh index a47ef984cb5..8923e06d257 100755 --- a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh +++ b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh @@ -29,6 +29,7 @@ apt-get -y install \ gdb \ git \ gzip \ + heimdal-multidev \ hostname \ htop \ krb5-config \ diff --git a/bootstrap/generated-dists/ubuntu1604/packages.yml b/bootstrap/generated-dists/ubuntu1604/packages.yml index 23939c38e80..d42971db3b5 100644 --- a/bootstrap/generated-dists/ubuntu1604/packages.yml +++ b/bootstrap/generated-dists/ubuntu1604/packages.yml @@ -18,6 +18,7 @@ packages: - gdb - git - gzip + - heimdal-multidev - hostname - htop - krb5-config diff --git a/bootstrap/generated-dists/ubuntu1804/bootstrap.sh b/bootstrap/generated-dists/ubuntu1804/bootstrap.sh index 45212ccfb81..3ec8f714aa0 100755 --- a/bootstrap/generated-dists/ubuntu1804/bootstrap.sh +++ b/bootstrap/generated-dists/ubuntu1804/bootstrap.sh @@ -30,6 +30,7 @@ apt-get -y install \ git \ glusterfs-common \ gzip \ + heimdal-multidev \ hostname \ htop \ krb5-config \ diff --git a/bootstrap/generated-dists/ubuntu1804/packages.yml b/bootstrap/generated-dists/ubuntu1804/packages.yml index f2c981fba83..8778af2bafb 100644 --- a/bootstrap/generated-dists/ubuntu1804/packages.yml +++ b/bootstrap/generated-dists/ubuntu1804/packages.yml @@ -19,6 +19,7 @@ packages: - git - glusterfs-common - gzip + - heimdal-multidev - hostname - htop - krb5-config diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 52cf7350bc0..0a3dbf1adf0 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -339a70ba1881feec94109c5c4eafacf4ff6c43bc +970e3a86b8a9dc10a0a3ec716ab355eb9664dc38 -- 2.17.1 From 3e5b173ef44a1f54d489e915f609570db37f1d18 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 30 Oct 2019 14:24:58 -0700 Subject: [PATCH 327/376] gitlab-ci: Run samba-fileserver-heimdalkrb5 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14179 Signed-off-by: Christof Schmitt Reviewed-by: Andrew Bartlett Autobuild-User(master): Christof Schmitt Autobuild-Date(master): Wed Nov 13 19:14:25 UTC 2019 on sn-devel-184 (cherry picked from commit 5343cec5f0a5531af85d72021dba30c31a4a3f1b) --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 263a13738e2..67a86d2b0c8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -176,6 +176,9 @@ samba-ad-dc-backup: samba-fileserver: extends: .private_template +samba-ktest-heimdal: + extends: .private_template + samba-ad-dc-1: extends: .private_template -- 2.17.1 From bc152b8473a8041b014b000d64fffd397af2f9fe Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 29 Oct 2019 15:25:26 +1100 Subject: [PATCH 328/376] ctdb-tcp: Check incoming queue to see if incoming connection is up This makes it consistent with the reverse case. Also, in_fd will soon be removed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14175 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit e62b3a05a874db13a848573d2e2fb1c157393b9c) --- ctdb/tcp/tcp_connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 6123380ca9f..5bcb5216bd2 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -153,7 +153,7 @@ static void ctdb_node_connect_write(struct tevent_context *ev, * as connected, but only if the corresponding listening * socket is also connected */ - if (tnode->in_fd != -1) { + if (tnode->in_queue != NULL) { node->ctdb->upcalls->node_connected(node); } } -- 2.17.1 From 77deaadca8e8dbc3c92ea16893099c72f6dc874e Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 29 Oct 2019 15:29:11 +1100 Subject: [PATCH 329/376] ctdb-tcp: Avoid orphaning the TCP incoming queue CTDB's incoming queue handling does not check whether an existing queue exists, so can overwrite the pointer to the queue. This used to be harmless until commit c68b6f96f26664459187ab2fbd56767fb31767e0 changed the read callback to use a parent structure as the callback data. Instead of cleaning up an orphaned queue on disconnect, as before, this will now free the new queue. At first glance it doesn't seem possible that 2 incoming connections from the same node could be processed before the intervening disconnect. However, the incoming connections and disconnect occur on different file descriptors. The queue can become orphaned on node A when the following sequence occurs: 1. Node A comes up 2. Node A accepts an incoming connection from node B 3. Node B processes a timeout before noticing that outgoing the queue is writable 4. Node B tears down the outgoing connection to node A 5. Node B initiates a new connection to node A 6. Node A accepts an incoming connection from node B Node A processes then the disconnect of the old incoming connection from (2) but tears down the new incoming connection from (6). This then occurs until the originally affected node is restarted. However, due to the number of outgoing connection attempts and associated teardowns, this induces the same behaviour on the corresponding incoming queue on all nodes that node A attempts to connect to. Therefore, other nodes become affected and need to be restarted too. As a result, the whole cluster probably needs to be restarted to recover from this situation. The problem can occur any time CTDB is started on a node. The fix is to avoid accepting new incoming connections when a queue for incoming connections is already present. The connecting node will simply retry establishing its outgoing connection. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14175 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit d0baad257e511280ff3e5c7372c38c43df841070) --- ctdb/tcp/tcp_connect.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 5bcb5216bd2..df115b783e0 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -312,6 +312,13 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, return; } + if (tnode->in_queue != NULL) { + DBG_ERR("Incoming queue active, rejecting connection from %s\n", + ctdb_addr_to_str(&addr)); + close(fd); + return; + } + ret = set_blocking(fd, false); if (ret != 0) { DBG_ERR("Failed to set socket non-blocking (%s)\n", -- 2.17.1 From 0b78c29a0fa091d54871cac084e9673605ae6a4e Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 29 Oct 2019 17:28:22 +1100 Subject: [PATCH 330/376] ctdb-tcp: Drop tracking of file descriptor for incoming connections This file descriptor is owned by the incoming queue. It will be closed when the queue is torn down. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14175 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit bf47bc18bb8a94231870ef821c0352b7a15c2e28) --- ctdb/tcp/ctdb_tcp.h | 1 - ctdb/tcp/tcp_connect.c | 2 -- ctdb/tcp/tcp_init.c | 6 ------ ctdb/tcp/tcp_io.c | 2 -- 4 files changed, 11 deletions(-) diff --git a/ctdb/tcp/ctdb_tcp.h b/ctdb/tcp/ctdb_tcp.h index 9a615fc6393..daabad74297 100644 --- a/ctdb/tcp/ctdb_tcp.h +++ b/ctdb/tcp/ctdb_tcp.h @@ -37,7 +37,6 @@ struct ctdb_tcp_node { struct tevent_timer *connect_te; struct ctdb_context *ctdb; - int in_fd; struct ctdb_queue *in_queue; }; diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index df115b783e0..a75f35a809e 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -355,8 +355,6 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, return; } - tnode->in_fd = fd; - /* * Mark the connecting node as connected, but only if the * corresponding outbound connected is also up diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index a9cb9b36a01..3be16bd7d5e 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -43,11 +43,6 @@ static int tnode_destructor(struct ctdb_tcp_node *tnode) tnode->out_fd = -1; } - if (tnode->in_fd != -1) { - close(tnode->in_fd); - tnode->in_fd = -1; - } - return 0; } @@ -61,7 +56,6 @@ static int ctdb_tcp_add_node(struct ctdb_node *node) CTDB_NO_MEMORY(node->ctdb, tnode); tnode->out_fd = -1; - tnode->in_fd = -1; tnode->ctdb = node->ctdb; node->private_data = tnode; diff --git a/ctdb/tcp/tcp_io.c b/ctdb/tcp/tcp_io.c index e8ebff887e1..2d8ec0f7062 100644 --- a/ctdb/tcp/tcp_io.c +++ b/ctdb/tcp/tcp_io.c @@ -76,8 +76,6 @@ void ctdb_tcp_read_cb(uint8_t *data, size_t cnt, void *args) failed: TALLOC_FREE(tnode->in_queue); - close(tnode->in_fd); - tnode->in_fd = -1; node->ctdb->upcalls->node_dead(node); TALLOC_FREE(data); -- 2.17.1 From 70c829304e0d24c228bde79a6dd6597e7e2e185a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 7 Nov 2019 15:26:01 +0100 Subject: [PATCH 331/376] ctdb-tcp: Close inflight connecting TCP sockets after fork Commit c68b6f96f26 changed the talloc hierarchy such that outgoing TCP sockets while sitting in the async connect() syscall are not freed via ctdb_tcp_shutdown() anymore, they are hanging off a longer-running structure. Free this structure as well. If an outgoing TCP socket leaks into a long-running child process (possibly the recovery daemon), this connection will never be closed as seen by the destination node. Because with recent changes incoming connections will not be accepted as long as any incoming connection is alive, with that socket leak into the recovery daemon we will never again be able to successfully connect to the node that is affected by this leak. Further attempts to connect will be discarded by the destination as long as the recovery daemon keeps this socket alive. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14175 RN: Avoid communication breakdown on node reconnect Signed-off-by: Martin Schwenke Signed-off-by: Volker Lendecke Reviewed-by: Amitay Isaacs (cherry picked from commit a6d99d9e5c5bc58e6d56be7a6c1dbc7c8d1a882f) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Tue Nov 19 13:21:18 UTC 2019 on sn-devel-184 --- ctdb/tcp/tcp_init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index 3be16bd7d5e..0eb9799ac4a 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -137,8 +137,14 @@ static void ctdb_tcp_shutdown(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); + uint32_t i; + talloc_free(ctcp); ctdb->private_data = NULL; + + for (i=0; inum_nodes; i++) { + TALLOC_FREE(ctdb->nodes[i]->private_data); + } } /* -- 2.17.1 From dff88803584fd1c6871e95bd5dbfad8584104554 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 29 Oct 2019 11:10:52 +0100 Subject: [PATCH 332/376] VERSION: Bump version up to 4.11.3. Signed-off-by: Karolin Seeger (cherry picked from commit e704eee3083658f7dcdd4238295f8e0b229a1688) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e4636c3dc96..ac97c314eff 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=2 +SAMBA_VERSION_RELEASE=3 ######################################################## # If a official release has a serious bug # -- 2.17.1 From 026fd23cf916f8e5479af31490b5c8813966796c Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 3 Dec 2019 13:07:17 +0100 Subject: [PATCH 333/376] VERSION: Re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ac97c314eff..e9cc49c7f77 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 9324b7a9e4ce358832ca882671c25c2afe677121 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 29 Oct 2019 17:25:28 +1300 Subject: [PATCH 334/376] CVE-2019-14861: s4-rpc/dnsserver: Confirm sort behaviour in dcesrv_DnssrvEnumRecords The sort behaviour for child records is not correct in Samba so we add a flapping entry. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14138 Signed-off-by: Andrew Bartlett --- python/samba/tests/dcerpc/dnsserver.py | 101 +++++++++++++++++++++++++ selftest/flapping.d/dnsserver | 2 + 2 files changed, 103 insertions(+) create mode 100644 selftest/flapping.d/dnsserver diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py index 0da9614d066..b2dffc924cb 100644 --- a/python/samba/tests/dcerpc/dnsserver.py +++ b/python/samba/tests/dcerpc/dnsserver.py @@ -156,6 +156,107 @@ class DnsserverTests(RpcInterfaceTestCase): None) super(DnsserverTests, self).tearDown() + def test_enum_is_sorted(self): + """ + Confirm the zone is sorted + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0", record_type_str, record_str) + + # This becomes an extra A on the zone itself by server-side magic + self.add_record(self.custom_zone, self.custom_zone, record_type_str, record_str) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "@", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 6) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0") + self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1") + self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2") + self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") + self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + + def test_enum_is_sorted_children_prefix_first(self): + """ + Confirm the zone returns the selected prefix first but no more + as Samba is flappy for the full sort + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0.a.b", record_type_str, record_str) + + # Not expected to be returned + self.add_record(self.custom_zone, "atestrecord-0.b.b", record_type_str, record_str) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "a.b", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 6) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + + def test_enum_is_sorted_children(self): + """ + Confirm the zone is sorted + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4.a.b", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0.a.b", record_type_str, record_str) + + # Not expected to be returned + self.add_record(self.custom_zone, "atestrecord-0.b.b", record_type_str, record_str) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "a.b", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 6) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0") + self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1") + self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2") + self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") + self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + # This test fails against Samba (but passes against Windows), # because Samba does not return the record when we enum records. # Records can be given DNS_RANK_NONE when the zone they are in diff --git a/selftest/flapping.d/dnsserver b/selftest/flapping.d/dnsserver new file mode 100644 index 00000000000..9b33e8522a3 --- /dev/null +++ b/selftest/flapping.d/dnsserver @@ -0,0 +1,2 @@ +# This is not stable in samba due to a bug +^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_enum_is_sorted_children \ No newline at end of file -- 2.17.1 From 678888b41bd07898399b5a66739796b04dbdf33a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Oct 2019 12:12:10 +1300 Subject: [PATCH 335/376] CVE-2019-14861: s4-rpc_server: Remove special case for @ in dns_build_tree() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14138 Signed-off-by: Andrew Bartlett --- source4/rpc_server/dnsserver/dnsdata.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source4/rpc_server/dnsserver/dnsdata.c b/source4/rpc_server/dnsserver/dnsdata.c index 2dc098a64a0..0739ea3f476 100644 --- a/source4/rpc_server/dnsserver/dnsdata.c +++ b/source4/rpc_server/dnsserver/dnsdata.c @@ -801,10 +801,11 @@ struct dns_tree *dns_build_tree(TALLOC_CTX *mem_ctx, const char *name, struct ld goto failed; } - if (strcmp(ptr, "@") == 0) { - base->data = res->msgs[i]; - continue; - } else if (strcasecmp(ptr, name) == 0) { + /* + * This might be the sub-domain in the zone being + * requested, or @ for the root of the zone + */ + if (strcasecmp(ptr, name) == 0) { base->data = res->msgs[i]; continue; } -- 2.17.1 From 2318a4a7233d63a262d3e095dd2ea2b87b047bd6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 29 Oct 2019 14:15:36 +1300 Subject: [PATCH 336/376] CVE-2019-14861: s4-rpc/dnsserver: Avoid crash in ldb_qsort() via dcesrv_DnssrvEnumRecords) dns_name_compare() had logic to put @ and the top record in the tree being enumerated first, but if a domain had both then this would break the older qsort() implementation in ldb_qsort() and cause a read of memory before the base pointer. By removing this special case (not required as the base pointer is already seperatly located, no matter were it is in the returned records) the crash is avoided. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14138 Signed-off-by: Andrew Bartlett --- .../rpc_server/dnsserver/dcerpc_dnsserver.c | 21 ++++++++++++------- source4/rpc_server/dnsserver/dnsdata.c | 19 ++--------------- source4/rpc_server/dnsserver/dnsserver.h | 4 ++-- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index 993e5dc4e56..b6389f2328a 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1763,6 +1763,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, struct DNS_RPC_RECORDS_ARRAY *recs; char **add_names = NULL; char *rname; + const char *preference_name = NULL; int add_count = 0; int i, ret, len; WERROR status; @@ -1779,6 +1780,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))"); + preference_name = "@"; } else { char *encoded_name = ldb_binary_encode_string(tmp_ctx, name); @@ -1786,6 +1788,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s))(!(dNSTombstoned=TRUE)))", encoded_name, encoded_name); + preference_name = name; } if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); @@ -1799,16 +1802,18 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY); W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx); - /* Sort the names, so that the first record is the parent record */ - ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name, - (ldb_qsort_cmp_fn_t)dns_name_compare); + /* + * Sort the names, so that the records are in order by the child + * component below "name". + * + * A full tree sort is not required, so we pass in "name" so + * we know which level to sort, as only direct children are + * eventually returned + */ + LDB_TYPESAFE_QSORT(res->msgs, res->count, name, dns_name_compare); /* Build a tree of name components from dns name */ - if (strcasecmp(name, z->name) == 0) { - tree = dns_build_tree(tmp_ctx, "@", res); - } else { - tree = dns_build_tree(tmp_ctx, name, res); - } + tree = dns_build_tree(tmp_ctx, preference_name, res); W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx); /* Find the parent record in the tree */ diff --git a/source4/rpc_server/dnsserver/dnsdata.c b/source4/rpc_server/dnsserver/dnsdata.c index 0739ea3f476..47d6f5d5c88 100644 --- a/source4/rpc_server/dnsserver/dnsdata.c +++ b/source4/rpc_server/dnsserver/dnsdata.c @@ -1066,8 +1066,8 @@ WERROR dns_fill_records_array(TALLOC_CTX *mem_ctx, } -int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m2, - char *search_name) +int dns_name_compare(struct ldb_message * const *m1, struct ldb_message * const *m2, + const char *search_name) { const char *name1, *name2; const char *ptr1, *ptr2; @@ -1078,21 +1078,6 @@ int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m return 0; } - /* '@' record and the search_name record gets preference */ - if (name1[0] == '@') { - return -1; - } - if (search_name && strcasecmp(name1, search_name) == 0) { - return -1; - } - - if (name2[0] == '@') { - return 1; - } - if (search_name && strcasecmp(name2, search_name) == 0) { - return 1; - } - /* Compare the last components of names. * If search_name is not NULL, compare the second last components of names */ ptr1 = strrchr(name1, '.'); diff --git a/source4/rpc_server/dnsserver/dnsserver.h b/source4/rpc_server/dnsserver/dnsserver.h index a8307ef836a..2e46e7c66a4 100644 --- a/source4/rpc_server/dnsserver/dnsserver.h +++ b/source4/rpc_server/dnsserver/dnsserver.h @@ -188,8 +188,8 @@ struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx, struct DNS_ADDR_ int dns_split_name_components(TALLOC_CTX *mem_ctx, const char *name, char ***components); char *dns_split_node_name(TALLOC_CTX *mem_ctx, const char *node_name, const char *zone_name); -int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m2, - char *search_name); +int dns_name_compare(struct ldb_message * const *m1, struct ldb_message * const *m2, + const char *search_name); bool dns_record_match(struct dnsp_DnssrvRpcRecord *rec1, struct dnsp_DnssrvRpcRecord *rec2); void dnsp_to_dns_copy(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *dnsp, -- 2.17.1 From fae319523b07ba7a53bf7cfdbb4ea7f9d7d01981 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 30 Oct 2019 11:50:57 +1300 Subject: [PATCH 337/376] CVE-2019-14861: Test to demonstrate the bug This test does not fail every time, but when it does it casues a segfault which takes out the rpc_server master process, as this hosts the dnsserver pipe. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14138 Signed-off-by: Andrew Bartlett --- python/samba/tests/dcerpc/dnsserver.py | 47 ++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py index b2dffc924cb..c6a150c876f 100644 --- a/python/samba/tests/dcerpc/dnsserver.py +++ b/python/samba/tests/dcerpc/dnsserver.py @@ -191,6 +191,53 @@ class DnsserverTests(RpcInterfaceTestCase): self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + def test_enum_is_sorted_with_zone_dup(self): + """ + Confirm the zone is sorted + """ + + record_str = "192.168.50.50" + record_type_str = "A" + self.add_record(self.custom_zone, "atestrecord-1", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-2", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-3", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-4", record_type_str, record_str) + self.add_record(self.custom_zone, "atestrecord-0", record_type_str, record_str) + + # This triggers a bug in old Samba + self.add_record(self.custom_zone, self.custom_zone + "1", record_type_str, record_str) + + dn, record = self.get_record_from_db(self.custom_zone, self.custom_zone + "1") + + new_dn = ldb.Dn(self.samdb, str(dn)) + new_dn.set_component(0, "dc", self.custom_zone) + self.samdb.rename(dn, new_dn) + + _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, + 0, + self.server, + self.custom_zone, + "@", + None, + self.record_type_int(record_type_str), + dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA, + None, + None) + + self.assertEqual(len(result.rec), 7) + self.assertEqual(result.rec[0].dnsNodeName.str, "") + self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0") + self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1") + self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2") + self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3") + self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4") + + # Windows doesn't reload the zone fast enough, but doesn't + # have the bug anyway, it will sort last on both names (where + # it should) + if result.rec[6].dnsNodeName.str != (self.custom_zone + "1"): + self.assertEqual(result.rec[6].dnsNodeName.str, self.custom_zone) + def test_enum_is_sorted_children_prefix_first(self): """ Confirm the zone returns the selected prefix first but no more -- 2.17.1 From b69ee283de5de1f560a73ad63c10f7974afeb9f8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Nov 2019 06:53:56 +1300 Subject: [PATCH 338/376] s4-torture: Reduce flapping in SambaToolDrsTests.test_samba_tool_replicate_local This test often flaps in Samba 4.9 (where more tests and DCs run in the environment) with obj_1 being 3. This is quite OK, we just need to see some changes get replicated, not 0 changes. Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 4ae0f9ce0f5ada99cf1d236377e5a1234c879ae3) --- source4/torture/drs/python/samba_tool_drs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source4/torture/drs/python/samba_tool_drs.py b/source4/torture/drs/python/samba_tool_drs.py index 76cc86f832e..988f1dc7a3c 100644 --- a/source4/torture/drs/python/samba_tool_drs.py +++ b/source4/torture/drs/python/samba_tool_drs.py @@ -210,6 +210,7 @@ class SambaToolDrsTests(drs_base.DrsBaseTestCase): self._disable_inbound_repl(self.dnsname_dc1) self._disable_inbound_repl(self.dnsname_dc2) + self._net_drs_replicate(DC=self.dnsname_dc2, fromDC=self.dnsname_dc1) self._net_drs_replicate(DC=self.dnsname_dc1, fromDC=self.dnsname_dc2) # add an object with link on dc1 @@ -232,7 +233,7 @@ class SambaToolDrsTests(drs_base.DrsBaseTestCase): (obj_1, link_1) = get_num_obj_links(out) - self.assertEqual(obj_1, 2) + self.assertGreaterEqual(obj_1, 2) self.assertEqual(link_1, 1) # pull that change with --local into local db from dc2: shouldn't send link or object -- 2.17.1 From fbd7a4c08fdb1988d2657760e3d4578785724c45 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sun, 27 Oct 2019 14:02:00 +0200 Subject: [PATCH 339/376] samba-tool: add user-sensitive command to set not-delegated flag Signed-off-by: Isaac Boukris --- python/samba/netcmd/user.py | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py index 121050a26e6..3fd8e6fb7be 100644 --- a/python/samba/netcmd/user.py +++ b/python/samba/netcmd/user.py @@ -2642,6 +2642,63 @@ class cmd_user_move(Command): (username, full_new_parent_dn)) +class cmd_user_sensitive(Command): + """Set/unset or show UF_NOT_DELEGATED for an account.""" + + synopsis = "%prog [(show|on|off)] [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "credopts": options.CredentialsOptions, + "versionopts": options.VersionOptions, + } + + takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", type=str, + metavar="URL", dest="H"), + ] + + takes_args = ["accountname", "cmd"] + + def run(self, accountname, cmd, H=None, credopts=None, sambaopts=None, + versionopts=None): + + if cmd not in ("show", "on", "off"): + raise CommandError("invalid argument: '%s' (choose from 'show', 'on', 'off')" % cmd) + + lp = sambaopts.get_loadparm() + creds = credopts.get_credentials(lp, fallback_machine=True) + sam = SamDB(url=H, session_info=system_session(), + credentials=creds, lp=lp) + + search_filter = "sAMAccountName=%s" % ldb.binary_encode(accountname) + flag = dsdb.UF_NOT_DELEGATED; + + if cmd == "show": + res = sam.search(scope=ldb.SCOPE_SUBTREE, expression=search_filter, + attrs=["userAccountControl"]) + if len(res) == 0: + raise Exception("Unable to find account where '%s'" % search_filter) + + uac = int(res[0].get("userAccountControl")[0]) + + self.outf.write("Account-DN: %s\n" % str(res[0].dn)) + self.outf.write("UF_NOT_DELEGATED: %s\n" % bool(uac & flag)) + + return + + if cmd == "on": + on = True + elif cmd == "off": + on = False + + try: + sam.toggle_userAccountFlags(search_filter, flag, flags_str="Not-Delegated", + on=on, strict=True) + except Exception as err: + raise CommandError(err) + + class cmd_user(SuperCommand): """User management.""" @@ -2660,3 +2717,4 @@ class cmd_user(SuperCommand): subcommands["edit"] = cmd_user_edit() subcommands["show"] = cmd_user_show() subcommands["move"] = cmd_user_move() + subcommands["sensitive"] = cmd_user_sensitive() -- 2.17.1 From fc0127db4b9f2fb21cb72b6f4cddd8de6167f555 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 30 Oct 2019 15:59:16 +0100 Subject: [PATCH 340/376] CVE-2019-14870: heimdal: add S4U test for delegation_not_allowed Signed-off-by: Isaac Boukris --- selftest/knownfail.d/heimdal_not_delegated | 1 + source4/selftest/tests.py | 1 + testprogs/blackbox/test_s4u_heimdal.sh | 73 ++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 selftest/knownfail.d/heimdal_not_delegated create mode 100755 testprogs/blackbox/test_s4u_heimdal.sh diff --git a/selftest/knownfail.d/heimdal_not_delegated b/selftest/knownfail.d/heimdal_not_delegated new file mode 100644 index 00000000000..bfc382a3fc2 --- /dev/null +++ b/selftest/knownfail.d/heimdal_not_delegated @@ -0,0 +1 @@ +^samba4.blackbox.krb5.s4u diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 1772611eb53..2bc4561b87a 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -455,6 +455,7 @@ if have_heimdal_support: plantestsuite("samba4.blackbox.kinit_trust(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external", "arcfour-hmac-md5"]) plantestsuite("samba4.blackbox.export.keytab(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_heimdal.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4]) plantestsuite("samba4.blackbox.kpasswd(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"]) + plantestsuite("samba4.blackbox.krb5.s4u", "fl2008r2dc:local", [os.path.join(bbdir, "test_s4u_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', configuration]) else: plantestsuite("samba4.blackbox.kinit(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) plantestsuite("samba4.blackbox.kinit(fl2000dc:local)", "fl2000dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) diff --git a/testprogs/blackbox/test_s4u_heimdal.sh b/testprogs/blackbox/test_s4u_heimdal.sh new file mode 100755 index 00000000000..0e12c7ec096 --- /dev/null +++ b/testprogs/blackbox/test_s4u_heimdal.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +if [ $# -lt 5 ]; then +cat < $PREFIX/tmppassfile +testit "kinit with password" $samba4kinit -f --password-file=$PREFIX/tmppassfile $impersonator || failed=`expr $failed + 1` + +testit "test S4U2Self with normal user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=${USERNAME} $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy with normal user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +testit "test S4U2Self with sensitive user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` +testit_expect_failure "test S4U2Proxy with sensitive user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +rm -f $ocache +testit "unset not-delegated flag" $samba_tool user sensitive $princ off || failed=`expr $failed + 1` + +testit "test S4U2Self after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + + +rm -f $ocache $PREFIX/tmpccache tmppassfile +exit $failed -- 2.17.1 From fbc1f000cf76f2172d63c9cdf4889fd83a087b14 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 28 Oct 2019 02:54:09 +0200 Subject: [PATCH 341/376] CVE-2019-14870: heimdal: enforce delegation_not_allowed in S4U2Self Signed-off-by: Isaac Boukris --- selftest/knownfail.d/heimdal_not_delegated | 1 - source4/heimdal/kdc/krb5tgs.c | 58 ++++++++++++++-------- 2 files changed, 36 insertions(+), 23 deletions(-) delete mode 100644 selftest/knownfail.d/heimdal_not_delegated diff --git a/selftest/knownfail.d/heimdal_not_delegated b/selftest/knownfail.d/heimdal_not_delegated deleted file mode 100644 index bfc382a3fc2..00000000000 --- a/selftest/knownfail.d/heimdal_not_delegated +++ /dev/null @@ -1 +0,0 @@ -^samba4.blackbox.krb5.s4u diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index ff7d93138c0..ee3ac3d8f53 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1975,30 +1975,42 @@ server_lookup: if (ret) goto out; + ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, + NULL, &s4u2self_impersonated_clientdb, + &s4u2self_impersonated_client); + if (ret) { + const char *msg; + + /* + * If the client belongs to the same realm as our krbtgt, it + * should exist in the local database. + * + */ + + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + msg = krb5_get_error_message(context, ret); + kdc_log(context, config, 1, + "S2U4Self principal to impersonate %s not found in database: %s", + tpn, msg); + krb5_free_error_message(context, msg); + goto out; + } + + /* Ignore pw_end attributes (as Windows does), + * since S4U2Self is not password authentication. */ + free(s4u2self_impersonated_client->entry.pw_end); + s4u2self_impersonated_client->entry.pw_end = NULL; + + ret = kdc_check_flags(context, config, s4u2self_impersonated_client, tpn, + NULL, NULL, FALSE); + if (ret) + goto out; + /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */ if(rspac.data) { krb5_pac p = NULL; krb5_data_free(&rspac); - ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, - NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client); - if (ret) { - const char *msg; - - /* - * If the client belongs to the same realm as our krbtgt, it - * should exist in the local database. - * - */ - - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - msg = krb5_get_error_message(context, ret); - kdc_log(context, config, 1, - "S2U4Self principal to impersonate %s not found in database: %s", - tpn, msg); - krb5_free_error_message(context, msg); - goto out; - } ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &p); if (ret) { kdc_log(context, config, 0, "PAC generation failed for -- %s", @@ -2034,10 +2046,12 @@ server_lookup: /* * If the service isn't trusted for authentication to - * delegation, remove the forward flag. + * delegation or if the impersonate client is disallowed + * forwardable, remove the forwardable flag. */ - if (client->entry.flags.trusted_for_delegation) { + if (client->entry.flags.trusted_for_delegation && + s4u2self_impersonated_client->entry.flags.forwardable) { str = "[forwardable]"; } else { b->kdc_options.forwardable = 0; -- 2.17.1 From 1ccab20c59b651173e76918a6b84290a5be4a27d Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Thu, 21 Nov 2019 11:12:48 +0100 Subject: [PATCH 342/376] CVE-2019-14870: mit-kdc: enforce delegation_not_allowed flag Signed-off-by: Isaac Boukris --- source4/kdc/mit_samba.c | 5 +++++ source4/kdc/sdb_to_kdb.c | 17 ++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 54dcd545ea1..5a4f6e73e97 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -304,6 +304,11 @@ fetch_referral_principal: sdb_free_entry(&sentry); + if ((kflags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) == 0) { + kentry->attributes &= ~KRB5_KDB_DISALLOW_FORWARDABLE; + kentry->attributes &= ~KRB5_KDB_DISALLOW_PROXIABLE; + } + done: krb5_free_principal(ctx->context, referral_principal); referral_principal = NULL; diff --git a/source4/kdc/sdb_to_kdb.c b/source4/kdc/sdb_to_kdb.c index 1411b0f5f66..2981f180333 100644 --- a/source4/kdc/sdb_to_kdb.c +++ b/source4/kdc/sdb_to_kdb.c @@ -36,18 +36,13 @@ static int SDBFlags_to_kflags(const struct SDBFlags *s, if (s->initial) { *k |= KRB5_KDB_DISALLOW_TGT_BASED; } - /* - * Do not set any disallow rules for forwardable, proxiable, - * renewable, postdate and server. - * - * The KDC will take care setting the flags based on the incoming - * ticket. - */ - if (s->forwardable) { - ; + /* The forwardable and proxiable flags are set according to client and + * server attributes. */ + if (!s->forwardable) { + *k |= KRB5_KDB_DISALLOW_FORWARDABLE; } - if (s->proxiable) { - ; + if (!s->proxiable) { + *k |= KRB5_KDB_DISALLOW_PROXIABLE; } if (s->renewable) { ; -- 2.17.1 From b691110c2677769dae22b78a62a749a520ae48e7 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Mon, 7 Oct 2019 00:36:42 +0300 Subject: [PATCH 343/376] waf: upgrade to 2.0.18 This is required to get the new test_args parameter to conf.check, which facilitates passing arguments to configuration test programs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13846 Signed-off-by: Uri Simchoni Reviewed-by: Andrew Bartlett (cherry picked from commit 09e282ec8173f2935bdb579e0396f269ce712e0d) --- buildtools/bin/waf | 2 +- buildtools/wafsamba/wafsamba.py | 2 +- third_party/waf/waflib/Configure.py | 20 +- third_party/waf/waflib/Context.py | 6 +- third_party/waf/waflib/Scripting.py | 7 +- third_party/waf/waflib/TaskGen.py | 2 +- third_party/waf/waflib/Tools/asm.py | 37 +++- third_party/waf/waflib/Tools/c_aliases.py | 6 +- third_party/waf/waflib/Tools/c_config.py | 9 +- third_party/waf/waflib/Tools/c_tests.py | 3 +- third_party/waf/waflib/Tools/gas.py | 1 + third_party/waf/waflib/Tools/javaw.py | 2 +- third_party/waf/waflib/Tools/nasm.py | 5 + third_party/waf/waflib/Tools/python.py | 27 ++- third_party/waf/waflib/extras/doxygen.py | 11 +- third_party/waf/waflib/extras/fast_partial.py | 28 ++- third_party/waf/waflib/extras/genpybind.py | 194 ++++++++++++++++++ third_party/waf/waflib/extras/local_rpath.py | 8 +- third_party/waf/waflib/extras/objcopy.py | 9 +- 19 files changed, 329 insertions(+), 50 deletions(-) create mode 100644 third_party/waf/waflib/extras/genpybind.py diff --git a/buildtools/bin/waf b/buildtools/bin/waf index 8413f2332b7..11ce8e7480a 100755 --- a/buildtools/bin/waf +++ b/buildtools/bin/waf @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.17" +VERSION="2.0.18" REVISION="x" GIT="x" INSTALL="x" diff --git a/buildtools/wafsamba/wafsamba.py b/buildtools/wafsamba/wafsamba.py index 76d65ebfcb6..205d5b4ac32 100644 --- a/buildtools/wafsamba/wafsamba.py +++ b/buildtools/wafsamba/wafsamba.py @@ -38,7 +38,7 @@ LIB_PATH="shared" os.environ['PYTHONUNBUFFERED'] = '1' -if Context.HEXVERSION not in (0x2001100,): +if Context.HEXVERSION not in (0x2001200,): Logs.error(''' Please use the version of waf that comes with Samba, not a system installed version. See http://wiki.samba.org/index.php/Waf diff --git a/third_party/waf/waflib/Configure.py b/third_party/waf/waflib/Configure.py index db09c0e3a40..5762eb66954 100644 --- a/third_party/waf/waflib/Configure.py +++ b/third_party/waf/waflib/Configure.py @@ -524,7 +524,7 @@ def run_build(self, *k, **kw): Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. - This function also provides a limited cache. To use it, provide the following option:: + This function also features a cache which can be enabled by the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, @@ -535,10 +535,21 @@ def run_build(self, *k, **kw): $ waf configure --confcache """ - lst = [str(v) for (p, v) in kw.items() if p != 'env'] - h = Utils.h_list(lst) + buf = [] + for key in sorted(kw.keys()): + v = kw[key] + if hasattr(v, '__call__'): + buf.append(Utils.h_fun(v)) + else: + buf.append(str(v)) + h = Utils.h_list(buf) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) + cachemode = kw.get('confcache', getattr(Options.options, 'confcache', None)) + + if not cachemode and os.path.exists(dir): + shutil.rmtree(dir) + try: os.makedirs(dir) except OSError: @@ -549,7 +560,6 @@ def run_build(self, *k, **kw): except OSError: self.fatal('cannot use the configuration test folder %r' % dir) - cachemode = getattr(Options.options, 'confcache', None) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) @@ -589,7 +599,7 @@ def run_build(self, *k, **kw): else: ret = getattr(bld, 'retval', 0) finally: - if cachemode == 1: + if cachemode: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_build'] = ret diff --git a/third_party/waf/waflib/Context.py b/third_party/waf/waflib/Context.py index d0759aada58..e3305fa3341 100644 --- a/third_party/waf/waflib/Context.py +++ b/third_party/waf/waflib/Context.py @@ -11,13 +11,13 @@ from waflib import Utils, Errors, Logs import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001100 +HEXVERSION=0x2001200 """Constant updated on new releases""" -WAFVERSION="2.0.17" +WAFVERSION="2.0.18" """Constant updated on new releases""" -WAFREVISION="6bc6cb599c702e985780e9f705b291b812123693" +WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad" """Git revision when the waf version is updated""" ABI = 20 diff --git a/third_party/waf/waflib/Scripting.py b/third_party/waf/waflib/Scripting.py index ae17a8b4503..68dccf29ce0 100644 --- a/third_party/waf/waflib/Scripting.py +++ b/third_party/waf/waflib/Scripting.py @@ -332,7 +332,12 @@ def distclean(ctx): else: remove_and_log(env.out_dir, shutil.rmtree) - for k in (env.out_dir, env.top_dir, env.run_dir): + env_dirs = [env.out_dir] + if not ctx.options.no_lock_in_top: + env_dirs.append(env.top_dir) + if not ctx.options.no_lock_in_run: + env_dirs.append(env.run_dir) + for k in env_dirs: p = os.path.join(k, Options.lockfile) remove_and_log(p, os.remove) diff --git a/third_party/waf/waflib/TaskGen.py b/third_party/waf/waflib/TaskGen.py index 532b7d5cdb4..f8f92bd57c1 100644 --- a/third_party/waf/waflib/TaskGen.py +++ b/third_party/waf/waflib/TaskGen.py @@ -905,7 +905,7 @@ def process_subst(self): # paranoid safety measure for the general case foo.in->foo.h with ambiguous dependencies for xt in HEADER_EXTS: if b.name.endswith(xt): - tsk.ext_in = tsk.ext_in + ['.h'] + tsk.ext_out = tsk.ext_out + ['.h'] break inst_to = getattr(self, 'install_path', None) diff --git a/third_party/waf/waflib/Tools/asm.py b/third_party/waf/waflib/Tools/asm.py index b6f26fb3df3..a57e83bb5ec 100644 --- a/third_party/waf/waflib/Tools/asm.py +++ b/third_party/waf/waflib/Tools/asm.py @@ -34,9 +34,22 @@ Support for pure asm programs and libraries should also work:: target = 'asmtest') """ -from waflib import Task +import re +from waflib import Errors, Logs, Task from waflib.Tools.ccroot import link_task, stlink_task from waflib.TaskGen import extension +from waflib.Tools import c_preproc + +re_lines = re.compile( + '^[ \t]*(?:%)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef)[ \t]*(.*)\r*$', + re.IGNORECASE | re.MULTILINE) + +class asm_parser(c_preproc.c_parser): + def filter_comments(self, node): + code = node.read() + code = c_preproc.re_nl.sub('', code) + code = c_preproc.re_cpp.sub(c_preproc.repl, code) + return re_lines.findall(code) class asm(Task.Task): """ @@ -45,6 +58,28 @@ class asm(Task.Task): color = 'BLUE' run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' + def scan(self): + if self.env.ASM_NAME == 'gas': + return c_preproc.scan(self) + Logs.warn('There is no dependency scanner for Nasm!') + return [[], []] + elif self.env.ASM_NAME == 'nasm': + Logs.warn('The Nasm dependency scanner is incomplete!') + + try: + incn = self.generator.includes_nodes + except AttributeError: + raise Errors.WafError('%r is missing the "asm" feature' % self.generator) + + if c_preproc.go_absolute: + nodepaths = incn + else: + nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] + + tmp = asm_parser(nodepaths) + tmp.start(self.inputs[0], self.env) + return (tmp.nodes, tmp.names) + @extension('.s', '.S', '.asm', '.ASM', '.spp', '.SPP') def asm_hook(self, node): """ diff --git a/third_party/waf/waflib/Tools/c_aliases.py b/third_party/waf/waflib/Tools/c_aliases.py index c9d53692e8f..985e048bdb7 100644 --- a/third_party/waf/waflib/Tools/c_aliases.py +++ b/third_party/waf/waflib/Tools/c_aliases.py @@ -47,10 +47,12 @@ def sniff_features(**kw): if x in exts: feats.append('cxx') break - if 'c' in exts or 'vala' in exts or 'gs' in exts: feats.append('c') + if 's' in exts or 'S' in exts: + feats.append('asm') + for x in 'f f90 F F90 for FOR'.split(): if x in exts: feats.append('fc') @@ -66,7 +68,7 @@ def sniff_features(**kw): if typ in ('program', 'shlib', 'stlib'): will_link = False for x in feats: - if x in ('cxx', 'd', 'fc', 'c'): + if x in ('cxx', 'd', 'fc', 'c', 'asm'): feats.append(x + typ) will_link = True if not will_link and not kw.get('features', []): diff --git a/third_party/waf/waflib/Tools/c_config.py b/third_party/waf/waflib/Tools/c_config.py index d546be95614..80580cc9fcb 100644 --- a/third_party/waf/waflib/Tools/c_config.py +++ b/third_party/waf/waflib/Tools/c_config.py @@ -659,20 +659,21 @@ class test_exec(Task.Task): """ color = 'PINK' def run(self): + cmd = [self.inputs[0].abspath()] + getattr(self.generator, 'test_args', []) if getattr(self.generator, 'rpath', None): if getattr(self.generator, 'define_ret', False): - self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) + self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd) else: - self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()]) + self.generator.bld.retval = self.generator.bld.exec_command(cmd) else: env = self.env.env or {} env.update(dict(os.environ)) for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') if getattr(self.generator, 'define_ret', False): - self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env) + self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd, env=env) else: - self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env) + self.generator.bld.retval = self.generator.bld.exec_command(cmd, env=env) @feature('test_exec') @after_method('apply_link') diff --git a/third_party/waf/waflib/Tools/c_tests.py b/third_party/waf/waflib/Tools/c_tests.py index f858df5763c..7a4094f2450 100644 --- a/third_party/waf/waflib/Tools/c_tests.py +++ b/third_party/waf/waflib/Tools/c_tests.py @@ -224,6 +224,7 @@ def check_endianness(self): def check_msg(self): return tmp[0] self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', - msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, okmsg=check_msg) + msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, + okmsg=check_msg, confcache=None) return tmp[0] diff --git a/third_party/waf/waflib/Tools/gas.py b/third_party/waf/waflib/Tools/gas.py index 77afed7038f..4a8745afd7e 100644 --- a/third_party/waf/waflib/Tools/gas.py +++ b/third_party/waf/waflib/Tools/gas.py @@ -16,3 +16,4 @@ def configure(conf): conf.env.ASLNK_TGT_F = ['-o'] conf.find_ar() conf.load('asm') + conf.env.ASM_NAME = 'gas' diff --git a/third_party/waf/waflib/Tools/javaw.py b/third_party/waf/waflib/Tools/javaw.py index fd1cf469abf..ceb08c28c87 100644 --- a/third_party/waf/waflib/Tools/javaw.py +++ b/third_party/waf/waflib/Tools/javaw.py @@ -246,7 +246,7 @@ def use_javac_files(self): self.javac_task.dep_nodes.extend(tg.jar_task.outputs) else: if hasattr(tg, 'outdir'): - base_node = tg.outdir.abspath() + base_node = tg.outdir else: base_node = tg.path.get_bld() diff --git a/third_party/waf/waflib/Tools/nasm.py b/third_party/waf/waflib/Tools/nasm.py index 411d5826b5d..9c51c18de18 100644 --- a/third_party/waf/waflib/Tools/nasm.py +++ b/third_party/waf/waflib/Tools/nasm.py @@ -24,3 +24,8 @@ def configure(conf): conf.env.ASLNK_TGT_F = ['-o'] conf.load('asm') conf.env.ASMPATH_ST = '-I%s' + os.sep + txt = conf.cmd_and_log(conf.env.AS + ['--version']) + if 'yasm' in txt.lower(): + conf.env.ASM_NAME = 'yasm' + else: + conf.env.ASM_NAME = 'nasm' diff --git a/third_party/waf/waflib/Tools/python.py b/third_party/waf/waflib/Tools/python.py index 63a8917d7c1..7c45a76ffd2 100644 --- a/third_party/waf/waflib/Tools/python.py +++ b/third_party/waf/waflib/Tools/python.py @@ -79,14 +79,19 @@ def process_py(self, node): """ Add signature of .py file, so it will be byte-compiled when necessary """ - assert(hasattr(self, 'install_path')), 'add features="py"' + assert(hasattr(self, 'install_path')), 'add features="py" for target "%s" in "%s/wscript".' % (self.target, self.path.nice_path()) + self.install_from = getattr(self, 'install_from', None) + relative_trick = getattr(self, 'relative_trick', True) + if self.install_from: + assert isinstance(self.install_from, Node.Node), \ + 'add features="py" for target "%s" in "%s/wscript" (%s).' % (self.target, self.path.nice_path(), type(self.install_from)) # where to install the python file if self.install_path: if self.install_from: - self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=True) + self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=relative_trick) else: - self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=True) + self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=relative_trick) lst = [] if self.env.PYC: @@ -96,9 +101,11 @@ def process_py(self, node): if self.install_path: if self.install_from: - pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.install_from)), self.env) + target_dir = node.path_from(self.install_from) if relative_trick else node.name + pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) else: - pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.path)), self.env) + target_dir = node.path_from(self.path) if relative_trick else node.name + pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) else: pyd = node.abspath() @@ -115,7 +122,7 @@ def process_py(self, node): tsk.pyd = pyd if self.install_path: - self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=True) + self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=relative_trick) class pyc(Task.Task): """ @@ -433,11 +440,11 @@ def check_python_headers(conf, features='pyembed pyext'): # Code using the Python API needs to be compiled with -fno-strict-aliasing if env.CC_NAME == 'gcc': - env.append_value('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) - env.append_value('CFLAGS_PYEXT', ['-fno-strict-aliasing']) + env.append_unique('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) + env.append_unique('CFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CXX_NAME == 'gcc': - env.append_value('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) - env.append_value('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) + env.append_unique('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) + env.append_unique('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CC_NAME == "msvc": from distutils.msvccompiler import MSVCCompiler diff --git a/third_party/waf/waflib/extras/doxygen.py b/third_party/waf/waflib/extras/doxygen.py index 423d8455025..20cd9e1a852 100644 --- a/third_party/waf/waflib/extras/doxygen.py +++ b/third_party/waf/waflib/extras/doxygen.py @@ -85,6 +85,12 @@ class doxygen(Task.Task): if not getattr(self, 'pars', None): txt = self.inputs[0].read() self.pars = parse_doxy(txt) + + # Override with any parameters passed to the task generator + if getattr(self.generator, 'pars', None): + for k, v in self.generator.pars.items(): + self.pars[k] = v + if self.pars.get('OUTPUT_DIRECTORY'): # Use the path parsed from the Doxyfile as an absolute path output_node = self.inputs[0].parent.get_bld().make_node(self.pars['OUTPUT_DIRECTORY']) @@ -94,11 +100,6 @@ class doxygen(Task.Task): output_node.mkdir() self.pars['OUTPUT_DIRECTORY'] = output_node.abspath() - # Override with any parameters passed to the task generator - if getattr(self.generator, 'pars', None): - for k, v in self.generator.pars.items(): - self.pars[k] = v - self.doxy_inputs = getattr(self, 'doxy_inputs', []) if not self.pars.get('INPUT'): self.doxy_inputs.append(self.inputs[0].parent) diff --git a/third_party/waf/waflib/extras/fast_partial.py b/third_party/waf/waflib/extras/fast_partial.py index 71b8318eecb..90a94723bb8 100644 --- a/third_party/waf/waflib/extras/fast_partial.py +++ b/third_party/waf/waflib/extras/fast_partial.py @@ -18,6 +18,7 @@ Usage:: opt.load('fast_partial') Assumptions: +* Start with a clean build (run "waf distclean" after enabling) * Mostly for C/C++/Fortran targets with link tasks (object-only targets are not handled) try it in the folder generated by utils/genbench.py * For full project builds: no --targets and no pruning from subfolders @@ -131,12 +132,18 @@ class bld_proxy(object): data[x] = getattr(self, x) db = os.path.join(self.variant_dir, Context.DBFILE + self.store_key) - try: - waflib.Node.pickle_lock.acquire() + with waflib.Node.pickle_lock: waflib.Node.Nod3 = self.node_class - x = Build.cPickle.dumps(data, Build.PROTOCOL) - finally: - waflib.Node.pickle_lock.release() + try: + x = Build.cPickle.dumps(data, Build.PROTOCOL) + except Build.cPickle.PicklingError: + root = data['root'] + for node_deps in data['node_deps'].values(): + for idx, node in enumerate(node_deps): + # there may be more cross-context Node objects to fix, + # but this should be the main source + node_deps[idx] = root.find_node(node.abspath()) + x = Build.cPickle.dumps(data, Build.PROTOCOL) Logs.debug('rev_use: storing %s', db) Utils.writef(db + '.tmp', x, m='wb') @@ -393,12 +400,17 @@ def is_stale(self): Logs.debug('rev_use: must post %r because this is a clean build') return True - # 3. check if the configuration changed - if os.stat(self.bld.bldnode.find_node('c4che/build.config.py').abspath()).st_mtime > dbstat: + # 3.a check if the configuration exists + cache_node = self.bld.bldnode.find_node('c4che/build.config.py') + if not cache_node: + return True + + # 3.b check if the configuration changed + if os.stat(cache_node.abspath()).st_mtime > dbstat: Logs.debug('rev_use: must post %r because the configuration has changed', self.name) return True - # 3.a any tstamp data? + # 3.c any tstamp data? try: f_deps = self.bld.f_deps except AttributeError: diff --git a/third_party/waf/waflib/extras/genpybind.py b/third_party/waf/waflib/extras/genpybind.py new file mode 100644 index 00000000000..ac206ee8a8b --- /dev/null +++ b/third_party/waf/waflib/extras/genpybind.py @@ -0,0 +1,194 @@ +import os +import pipes +import subprocess +import sys + +from waflib import Logs, Task, Context +from waflib.Tools.c_preproc import scan as scan_impl +# ^-- Note: waflib.extras.gccdeps.scan does not work for us, +# due to its current implementation: +# The -MD flag is injected into the {C,CXX}FLAGS environment variable and +# dependencies are read out in a separate step after compiling by reading +# the .d file saved alongside the object file. +# As the genpybind task refers to a header file that is never compiled itself, +# gccdeps will not be able to extract the list of dependencies. + +from waflib.TaskGen import feature, before_method + + +def join_args(args): + return " ".join(pipes.quote(arg) for arg in args) + + +def configure(cfg): + cfg.load("compiler_cxx") + cfg.load("python") + cfg.check_python_version(minver=(2, 7)) + if not cfg.env.LLVM_CONFIG: + cfg.find_program("llvm-config", var="LLVM_CONFIG") + if not cfg.env.GENPYBIND: + cfg.find_program("genpybind", var="GENPYBIND") + + # find clang reasource dir for builtin headers + cfg.env.GENPYBIND_RESOURCE_DIR = os.path.join( + cfg.cmd_and_log(cfg.env.LLVM_CONFIG + ["--libdir"]).strip(), + "clang", + cfg.cmd_and_log(cfg.env.LLVM_CONFIG + ["--version"]).strip()) + if os.path.exists(cfg.env.GENPYBIND_RESOURCE_DIR): + cfg.msg("Checking clang resource dir", cfg.env.GENPYBIND_RESOURCE_DIR) + else: + cfg.fatal("Clang resource dir not found") + + +@feature("genpybind") +@before_method("process_source") +def generate_genpybind_source(self): + """ + Run genpybind on the headers provided in `source` and compile/link the + generated code instead. This works by generating the code on the fly and + swapping the source node before `process_source` is run. + """ + # name of module defaults to name of target + module = getattr(self, "module", self.target) + + # create temporary source file in build directory to hold generated code + out = "genpybind-%s.%d.cpp" % (module, self.idx) + out = self.path.get_bld().find_or_declare(out) + + task = self.create_task("genpybind", self.to_nodes(self.source), out) + # used to detect whether CFLAGS or CXXFLAGS should be passed to genpybind + task.features = self.features + task.module = module + # can be used to select definitions to include in the current module + # (when header files are shared by more than one module) + task.genpybind_tags = self.to_list(getattr(self, "genpybind_tags", [])) + # additional include directories + task.includes = self.to_list(getattr(self, "includes", [])) + task.genpybind = self.env.GENPYBIND + + # Tell waf to compile/link the generated code instead of the headers + # originally passed-in via the `source` parameter. (see `process_source`) + self.source = [out] + + +class genpybind(Task.Task): # pylint: disable=invalid-name + """ + Runs genpybind on headers provided as input to this task. + Generated code will be written to the first (and only) output node. + """ + quiet = True + color = "PINK" + scan = scan_impl + + @staticmethod + def keyword(): + return "Analyzing" + + def run(self): + if not self.inputs: + return + + args = self.find_genpybind() + self._arguments( + resource_dir=self.env.GENPYBIND_RESOURCE_DIR) + + output = self.run_genpybind(args) + + # For debugging / log output + pasteable_command = join_args(args) + + # write generated code to file in build directory + # (will be compiled during process_source stage) + (output_node,) = self.outputs + output_node.write("// {}\n{}\n".format( + pasteable_command.replace("\n", "\n// "), output)) + + def find_genpybind(self): + return self.genpybind + + def run_genpybind(self, args): + bld = self.generator.bld + + kwargs = dict(cwd=bld.variant_dir) + if hasattr(bld, "log_command"): + bld.log_command(args, kwargs) + else: + Logs.debug("runner: {!r}".format(args)) + proc = subprocess.Popen( + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) + stdout, stderr = proc.communicate() + + if not isinstance(stdout, str): + stdout = stdout.decode(sys.stdout.encoding, errors="replace") + if not isinstance(stderr, str): + stderr = stderr.decode(sys.stderr.encoding, errors="replace") + + if proc.returncode != 0: + bld.fatal( + "genpybind returned {code} during the following call:" + "\n{command}\n\n{stdout}\n\n{stderr}".format( + code=proc.returncode, + command=join_args(args), + stdout=stdout, + stderr=stderr, + )) + + if stderr.strip(): + Logs.debug("non-fatal warnings during genpybind run:\n{}".format(stderr)) + + return stdout + + def _include_paths(self): + return self.generator.to_incnodes(self.includes + self.env.INCLUDES) + + def _inputs_as_relative_includes(self): + include_paths = self._include_paths() + relative_includes = [] + for node in self.inputs: + for inc in include_paths: + if node.is_child_of(inc): + relative_includes.append(node.path_from(inc)) + break + else: + self.generator.bld.fatal("could not resolve {}".format(node)) + return relative_includes + + def _arguments(self, genpybind_parse=None, resource_dir=None): + args = [] + relative_includes = self._inputs_as_relative_includes() + is_cxx = "cxx" in self.features + + # options for genpybind + args.extend(["--genpybind-module", self.module]) + if self.genpybind_tags: + args.extend(["--genpybind-tag"] + self.genpybind_tags) + if relative_includes: + args.extend(["--genpybind-include"] + relative_includes) + if genpybind_parse: + args.extend(["--genpybind-parse", genpybind_parse]) + + args.append("--") + + # headers to be processed by genpybind + args.extend(node.abspath() for node in self.inputs) + + args.append("--") + + # options for clang/genpybind-parse + args.append("-D__GENPYBIND__") + args.append("-xc++" if is_cxx else "-xc") + has_std_argument = False + for flag in self.env["CXXFLAGS" if is_cxx else "CFLAGS"]: + flag = flag.replace("-std=gnu", "-std=c") + if flag.startswith("-std=c"): + has_std_argument = True + args.append(flag) + if not has_std_argument: + args.append("-std=c++14") + args.extend("-I{}".format(n.abspath()) for n in self._include_paths()) + args.extend("-D{}".format(p) for p in self.env.DEFINES) + + # point to clang resource dir, if specified + if resource_dir: + args.append("-resource-dir={}".format(resource_dir)) + + return args diff --git a/third_party/waf/waflib/extras/local_rpath.py b/third_party/waf/waflib/extras/local_rpath.py index b2507e17a10..e3923d9b9d4 100644 --- a/third_party/waf/waflib/extras/local_rpath.py +++ b/third_party/waf/waflib/extras/local_rpath.py @@ -2,18 +2,20 @@ # encoding: utf-8 # Thomas Nagy, 2011 (ita) +import copy from waflib.TaskGen import after_method, feature @after_method('propagate_uselib_vars') @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib', 'fcprogram', 'fcshlib') def add_rpath_stuff(self): - all = self.to_list(getattr(self, 'use', [])) + all = copy.copy(self.to_list(getattr(self, 'use', []))) while all: name = all.pop() try: tg = self.bld.get_tgen_by_name(name) except: continue - self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) - all.extend(self.to_list(getattr(tg, 'use', []))) + if hasattr(tg, 'link_task'): + self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) + all.extend(self.to_list(getattr(tg, 'use', []))) diff --git a/third_party/waf/waflib/extras/objcopy.py b/third_party/waf/waflib/extras/objcopy.py index 82d8359ecf7..bb7ca6ef224 100644 --- a/third_party/waf/waflib/extras/objcopy.py +++ b/third_party/waf/waflib/extras/objcopy.py @@ -15,7 +15,7 @@ objcopy_flags Additional flags passed to objcopy. """ from waflib.Utils import def_attrs -from waflib import Task +from waflib import Task, Options from waflib.TaskGen import feature, after_method class objcopy(Task.Task): @@ -46,5 +46,8 @@ def map_objcopy(self): self.add_install_files(install_to=self.objcopy_install_path, install_from=task.outputs[0]) def configure(ctx): - ctx.find_program('objcopy', var='OBJCOPY', mandatory=True) - + program_name = 'objcopy' + prefix = getattr(Options.options, 'cross_prefix', None) + if prefix: + program_name = '{}-{}'.format(prefix, program_name) + ctx.find_program(program_name, var='OBJCOPY', mandatory=True) -- 2.17.1 From e1a0813aa5c2f52648667863a082f9ebf82d0d88 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Mon, 7 Oct 2019 00:37:17 +0300 Subject: [PATCH 344/376] wafsamba: use test_args instead of exec_args to support cross-compilation exec_args seems to have been a custom addition to Samba's copy of waf. Upstream Waf has an identically-purposed parameter called test_args. This parameter is being used for addiing runtime args to test programs that are being run during configuration phases. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13846 Signed-off-by: Uri Simchoni Reviewed-by: Andrew Bartlett (cherry picked from commit e00e93350288dc212fed3f1be2adf78dcb6e58e7) --- buildtools/wafsamba/samba_autoconf.py | 6 +++--- buildtools/wafsamba/samba_cross.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildtools/wafsamba/samba_autoconf.py b/buildtools/wafsamba/samba_autoconf.py index 8e5dfb87102..62d3e20a15c 100644 --- a/buildtools/wafsamba/samba_autoconf.py +++ b/buildtools/wafsamba/samba_autoconf.py @@ -423,9 +423,9 @@ def CHECK_CODE(conf, code, define, cflags.extend(ccflags) if on_target: - exec_args = conf.SAMBA_CROSS_ARGS(msg=msg) + test_args = conf.SAMBA_CROSS_ARGS(msg=msg) else: - exec_args = [] + test_args = [] conf.COMPOUND_START(msg) @@ -440,7 +440,7 @@ def CHECK_CODE(conf, code, define, type=type, msg=msg, quote=quote, - exec_args=exec_args, + test_args=test_args, define_ret=define_ret) except Exception: if always: diff --git a/buildtools/wafsamba/samba_cross.py b/buildtools/wafsamba/samba_cross.py index 8863c2c53e7..60ddf967237 100644 --- a/buildtools/wafsamba/samba_cross.py +++ b/buildtools/wafsamba/samba_cross.py @@ -139,7 +139,7 @@ class cross_Popen(Utils.subprocess.Popen): @conf def SAMBA_CROSS_ARGS(conf, msg=None): - '''get exec_args to pass when running cross compiled binaries''' + '''get test_args to pass when running cross compiled binaries''' if not conf.env.CROSS_COMPILE: return [] -- 2.17.1 From 98dc227dce980307ec58bd326b773e41272d4c98 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Mon, 7 Oct 2019 00:37:31 +0300 Subject: [PATCH 345/376] wafsamba: avoid pre-forking if cross-compilation is enabled Waf supports pre-forking to run configuration tests, but this doesn't play well with Samba's cross-compilation support, because Samba monkey-patches the actual fork+exec, which doesn't happen in a pre-forked process pool. This patch emulates the impact of WAF_NO_PREFORK env var when cross-compilation is enabled. The blueprint for the solution has been suggested by Thomas Nagy in https://bugzilla.samba.org/show_bug.cgi?id=13846#c7 (item #2) BUG: https://bugzilla.samba.org/show_bug.cgi?id=13846 Signed-off-by: Uri Simchoni Reviewed-by: Andrew Bartlett (cherry picked from commit 5a4ade953420a4122c80d291ac53310abd6a279c) --- buildtools/wafsamba/samba_cross.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildtools/wafsamba/samba_cross.py b/buildtools/wafsamba/samba_cross.py index 60ddf967237..6fca470f2b7 100644 --- a/buildtools/wafsamba/samba_cross.py +++ b/buildtools/wafsamba/samba_cross.py @@ -147,6 +147,8 @@ def SAMBA_CROSS_ARGS(conf, msg=None): if real_Popen is None: real_Popen = Utils.subprocess.Popen Utils.subprocess.Popen = cross_Popen + Utils.run_process = Utils.run_regular_process + Utils.get_process = Utils.alloc_process_pool = Utils.nada ret = [] -- 2.17.1 From b7894c151ab2c10774a4cedde82b97fd5da26307 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Mon, 7 Oct 2019 00:37:41 +0300 Subject: [PATCH 346/376] wafsamba: pass environment to cross-execute tests This can come in handy for cross-execute scripts in general, and is particularly required by the samba-xc test for cross-answers / cross-execute, because Samba sets LD_LIBRARY_PATH during rpath checks, and the test program needs that in order to successfully run. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13846 Signed-off-by: Uri Simchoni Reviewed-by: Andrew Bartlett (cherry picked from commit fdfd69840902f4b13db2a204a0ca87a578b61b85) --- buildtools/wafsamba/samba_cross.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildtools/wafsamba/samba_cross.py b/buildtools/wafsamba/samba_cross.py index 6fca470f2b7..0868a855a0d 100644 --- a/buildtools/wafsamba/samba_cross.py +++ b/buildtools/wafsamba/samba_cross.py @@ -120,7 +120,8 @@ class cross_Popen(Utils.subprocess.Popen): if use_answers: p = real_Popen(newargs, stdout=Utils.subprocess.PIPE, - stderr=Utils.subprocess.PIPE) + stderr=Utils.subprocess.PIPE, + env=kw.get('env', {})) ce_out, ce_err = p.communicate() ans = (p.returncode, samba_utils.get_string(ce_out)) add_answer(ca_file, msg, ans) -- 2.17.1 From 1c8ac011360541bd0d1c3675ae8a99fd21dd5ab7 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Wed, 9 Oct 2019 21:53:43 +0300 Subject: [PATCH 347/376] autobuild: harden samba-xc test suite Add more checks which directly test the behavior of --cross-answers and --cross-execute. Previous test tested things in a round-about way, checking that running in all three modes (native, cross-execute, cross-answers) yields the same result. It was vulnerable to a degradation in which cross-compilation modes didn't work at all and were running native tests, which is what happened with the upgrade of waf. The added tests check the following: - That cross-excute with cross-answers sets the cross-answers file - That the content of cross-answers file actually affects the build configuration - That a missing line in cross-answers fails the build BUG: https://bugzilla.samba.org/show_bug.cgi?id=13846 Signed-off-by: Uri Simchoni Reviewed-by: Andrew Bartlett Autobuild-User(master): Uri Simchoni Autobuild-Date(master): Sun Oct 20 13:29:58 UTC 2019 on sn-devel-184 (cherry picked from commit 649d15bb969b6d27fd4554f49600366bb3df4712) --- script/autobuild.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/script/autobuild.py b/script/autobuild.py index cf665bd6a7c..41a373b9b90 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -442,12 +442,22 @@ tasks = { ("configure-native", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params), ("configure-cross-execute", "./configure.developer --out ./bin-xe --cross-compile --cross-execute=script/identity_cc.sh" \ " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xe/ab" + samba_configure_params), + ("verify-cross-execute-output", "grep '^Checking value of NSIG' ./bin-xe/cross-answers.txt"), ("configure-cross-answers", "./configure.developer --out ./bin-xa --cross-compile" \ " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xa/ab" + samba_configure_params), ("compare-results", "script/compare_cc_results.py " "./bin/c4che/default{} " "./bin-xe/c4che/default{} " "./bin-xa/c4che/default{}".format(*([CACHE_SUFFIX]*3))), + ("modify-cross-answers", "sed -i.bak -e 's/^\\(Checking value of NSIG:\\) .*/\\1 \"1234\"/' ./bin-xe/cross-answers.txt"), + ("configure-cross-answers-modified", "./configure.developer --out ./bin-xa2 --cross-compile" \ + " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xa2/ab" + samba_configure_params), + ("verify-cross-answers", "test $(sed -n -e 's/VALUEOF_NSIG = \\(.*\\)/\\1/p' ./bin-xa2/c4che/default{})" \ + " = \"'1234'\"".format(CACHE_SUFFIX)), + ("invalidate-cross-answers", "sed -i.bak -e '/^Checking value of NSIG/d' ./bin-xe/cross-answers.txt"), + ("configure-cross-answers-fail", "./configure.developer --out ./bin-xa3 --cross-compile" \ + " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xa3/ab" + samba_configure_params + \ + " ; test $? -ne 0"), ], # test build with -O3 -- catches extra warnings and bugs, tests the ad_dc environments -- 2.17.1 From c37b94fd0a7b24df93b664ad4c2d197c516c9dce Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Thu, 28 Nov 2019 21:19:51 +0200 Subject: [PATCH 348/376] ldb: Release ldb 2.0.8 * Upgrade waf to version 2.0.18 to match the rest of Samba 4.11.x BUG: https://bugzilla.samba.org/show_bug.cgi?id=13846 Signed-off-by: Uri Simchoni --- lib/ldb/ABI/ldb-2.0.8.sigs | 283 ++++++++++++++++++++++++++++++ lib/ldb/ABI/pyldb-util-2.0.8.sigs | 2 + lib/ldb/wscript | 2 +- 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 lib/ldb/ABI/ldb-2.0.8.sigs create mode 100644 lib/ldb/ABI/pyldb-util-2.0.8.sigs diff --git a/lib/ldb/ABI/ldb-2.0.8.sigs b/lib/ldb/ABI/ldb-2.0.8.sigs new file mode 100644 index 00000000000..5049dc64ce1 --- /dev/null +++ b/lib/ldb/ABI/ldb-2.0.8.sigs @@ -0,0 +1,283 @@ +ldb_add: int (struct ldb_context *, const struct ldb_message *) +ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *) +ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...) +ldb_attr_casefold: char *(TALLOC_CTX *, const char *) +ldb_attr_dn: int (const char *) +ldb_attr_in_list: int (const char * const *, const char *) +ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *) +ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *) +ldb_base64_decode: int (char *) +ldb_base64_encode: char *(TALLOC_CTX *, const char *, int) +ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *) +ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val) +ldb_binary_encode_string: char *(TALLOC_CTX *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t) +ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t) +ldb_check_critical_controls: int (struct ldb_control **) +ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **) +ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *) +ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *) +ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_debug_add: void (struct ldb_context *, const char *, ...) +ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level) +ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_delete: int (struct ldb_context *, struct ldb_dn *) +ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *) +ldb_dn_check_special: bool (struct ldb_dn *, const char *) +ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val) +ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *) +ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *) +ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *) +ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *) +ldb_dn_get_casefold: const char *(struct ldb_dn *) +ldb_dn_get_comp_num: int (struct ldb_dn *) +ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int) +ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int) +ldb_dn_get_extended_comp_num: int (struct ldb_dn *) +ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int) +ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_get_rdn_name: const char *(struct ldb_dn *) +ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *) +ldb_dn_has_extended: bool (struct ldb_dn *) +ldb_dn_is_null: bool (struct ldb_dn *) +ldb_dn_is_special: bool (struct ldb_dn *) +ldb_dn_is_valid: bool (struct ldb_dn *) +ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_minimise: bool (struct ldb_dn *) +ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...) +ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_extended_components: void (struct ldb_dn *) +ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val) +ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *) +ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *) +ldb_dn_validate: bool (struct ldb_dn *) +ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *) +ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int) +ldb_errstring: const char *(struct ldb_context *) +ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **) +ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_create_perms: unsigned int (struct ldb_context *) +ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_event_context: struct tevent_context *(struct ldb_context *) +ldb_get_flags: unsigned int (struct ldb_context *) +ldb_get_opaque: void *(struct ldb_context *, const char *) +ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *) +ldb_global_init: int (void) +ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *) +ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **) +ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *) +ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *) +ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **) +ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *) +ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *) +ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_map_add: int (struct ldb_module *, struct ldb_request *) +ldb_map_delete: int (struct ldb_module *, struct ldb_request *) +ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *) +ldb_map_modify: int (struct ldb_module *, struct ldb_request *) +ldb_map_rename: int (struct ldb_module *, struct ldb_request *) +ldb_map_search: int (struct ldb_module *, struct ldb_request *) +ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *) +ldb_match_msg_objectclass: int (const struct ldb_message *, const char *) +ldb_mod_register_control: int (struct ldb_module *, const char *) +ldb_modify: int (struct ldb_context *, const struct ldb_message *) +ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *) +ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +ldb_module_flags: uint32_t (struct ldb_context *) +ldb_module_get_ctx: struct ldb_context *(struct ldb_module *) +ldb_module_get_name: const char *(struct ldb_module *) +ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *) +ldb_module_get_private: void *(struct ldb_module *) +ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *) +ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +ldb_module_next: struct ldb_module *(struct ldb_module *) +ldb_module_popt_options: struct poptOption **(struct ldb_context *) +ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **) +ldb_module_send_referral: int (struct ldb_request *, char *) +ldb_module_set_next: void (struct ldb_module *, struct ldb_module *) +ldb_module_set_private: void (struct ldb_module *, void *) +ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_modules_load: int (const char *, const char *) +ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int) +ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **) +ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...) +ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *) +ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *) +ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *) +ldb_msg_add_string: int (struct ldb_message *, const char *, const char *) +ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **) +ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *) +ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *) +ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *) +ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **) +ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *) +ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *) +ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double) +ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t) +ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *) +ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int) +ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t) +ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t) +ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *) +ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *) +ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *) +ldb_msg_new: struct ldb_message *(TALLOC_CTX *) +ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **) +ldb_msg_remove_attr: void (struct ldb_message *, const char *) +ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *) +ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *) +ldb_msg_sort_elements: void (struct ldb_message *) +ldb_next_del_trans: int (struct ldb_module *) +ldb_next_end_trans: int (struct ldb_module *) +ldb_next_init: int (struct ldb_module *) +ldb_next_prepare_commit: int (struct ldb_module *) +ldb_next_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: int (struct ldb_module *) +ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_start_trans: int (struct ldb_module *) +ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_options_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *) +ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *) +ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *) +ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *) +ldb_register_hook: int (ldb_hook_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *) +ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *) +ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *) +ldb_req_get_custom_flags: uint32_t (struct ldb_request *) +ldb_req_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_trusted: void (struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t) +ldb_req_set_location: void (struct ldb_request *, const char *) +ldb_request: int (struct ldb_context *, struct ldb_request *) +ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_done: int (struct ldb_request *, int) +ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *) +ldb_request_get_status: int (struct ldb_request *) +ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***) +ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *) +ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *) +ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *) +ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *) +ldb_schema_attribute_remove: void (struct ldb_context *, const char *) +ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int) +ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *) +ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...) +ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *) +ldb_set_create_perms: void (struct ldb_context *, unsigned int) +ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *) +ldb_set_debug_stderr: int (struct ldb_context *) +ldb_set_default_dns: void (struct ldb_context *) +ldb_set_errstring: void (struct ldb_context *, const char *) +ldb_set_event_context: void (struct ldb_context *, struct tevent_context *) +ldb_set_flags: void (struct ldb_context *, unsigned int) +ldb_set_modules_dir: void (struct ldb_context *, const char *) +ldb_set_opaque: int (struct ldb_context *, const char *, void *) +ldb_set_require_private_event_context: void (struct ldb_context *) +ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int) +ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *) +ldb_set_utf8_default: void (struct ldb_context *) +ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t)) +ldb_setup_wellknown_attributes: int (struct ldb_context *) +ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *) +ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_strerror: const char *(int) +ldb_string_to_time: time_t (const char *) +ldb_string_utc_to_time: time_t (const char *) +ldb_timestring: char *(TALLOC_CTX *, time_t) +ldb_timestring_utc: char *(TALLOC_CTX *, time_t) +ldb_transaction_cancel: int (struct ldb_context *) +ldb_transaction_cancel_noerr: int (struct ldb_context *) +ldb_transaction_commit: int (struct ldb_context *) +ldb_transaction_prepare_commit: int (struct ldb_context *) +ldb_transaction_start: int (struct ldb_context *) +ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *) +ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *) +ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *) +ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_string_cmp: int (const struct ldb_val *, const char *) +ldb_val_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/lib/ldb/ABI/pyldb-util-2.0.8.sigs b/lib/ldb/ABI/pyldb-util-2.0.8.sigs new file mode 100644 index 00000000000..74d6719d2bc --- /dev/null +++ b/lib/ldb/ABI/pyldb-util-2.0.8.sigs @@ -0,0 +1,2 @@ +pyldb_Dn_FromDn: PyObject *(struct ldb_dn *) +pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **) diff --git a/lib/ldb/wscript b/lib/ldb/wscript index 750306fbddb..5b5c42d1431 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'ldb' -VERSION = '2.0.7' +VERSION = '2.0.8' import sys, os -- 2.17.1 From ec4381228f33f04362cd05bdba330ffc89c0e162 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Sun, 20 Oct 2019 21:36:11 +0300 Subject: [PATCH 349/376] heimdal-build: avoid hard-coded /usr/include/heimdal in asn1_compile-generated code. This fixes a cross-compilation issue, as cross-compilers (rightly) complain if host include directories are in the include path. The fix is taken from buildroot (https://github.com/buildroot/buildroot/blob/8b11b96f41a6ffa76556c9bf03a863955871ee57/package/samba4/0006-heimdal_build-wscript_build-do-not-add-host-include-.patch) where it was applied by Bernd Kuhls . This reverts some of 3fe2bfddda6149f6bf7402720226e9285f479fef, but building Samba's bundled Heimdal with a system roken is not supported anyway. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13856 Signed-off-by: Uri Simchoni Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Sun Dec 1 10:22:01 UTC 2019 on sn-devel-184 (cherry picked from commit 27fc062d7ea2207242d5a2c9933f3de5fa206488) --- source4/heimdal_build/wscript_build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/heimdal_build/wscript_build b/source4/heimdal_build/wscript_build index 163b622fca9..27adbc06dc6 100644 --- a/source4/heimdal_build/wscript_build +++ b/source4/heimdal_build/wscript_build @@ -140,7 +140,7 @@ def HEIMDAL_ASN1(name, source, samba_cflags = CURRENT_CFLAGS(bld, name, ''), depends_on = '', samba_deps = to_list('roken replace'), - samba_includes = includes + ["/usr/include/heimdal"], + samba_includes = includes, local_include = True) -- 2.17.1 From a694a00914754b4142db6abf8d3f661f86a6e969 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Wed, 4 Dec 2019 10:02:16 +0100 Subject: [PATCH 350/376] WHATSNEW: Add release notes for Samba 4.11.3. o CVE-2019-14861: Samba AD DC zone-named record Denial of Service in DNS management server (dnsserver). o CVE-2019-14870: DelegationNotAllowed not being enforced in protocol transition on Samba AD DC. Signed-off-by: Karolin Seeger --- WHATSNEW.txt | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 8c6db3b3034..8bafa38b47c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,65 @@ + ============================== + Release Notes for Samba 4.11.3 + December 10, 2019 + ============================== + + +This is a security release in order to address the following defects: + +o CVE-2019-14861: Samba AD DC zone-named record Denial of Service in DNS + management server (dnsserver). +o CVE-2019-14870: DelegationNotAllowed not being enforced in protocol transition + on Samba AD DC. + + +======= +Details +======= + +o CVE-2019-14861: + An authenticated user can crash the DCE/RPC DNS management server by creating + records with matching the zone name. + +o CVE-2019-14870: + The DelegationNotAllowed Kerberos feature restriction was not being applied + when processing protocol transition requests (S4U2Self), in the AD DC KDC. + +For more details and workarounds, please refer to the security advisories. + + +Changes since 4.11.2: +--------------------- + +o Andrew Bartlett + * BUG 14138: CVE-2019-14861: Fix DNSServer RPC server crash. + +o Isaac Boukris + * BUG 14187: CVE-2019-14870: DelegationNotAllowed not being enforced. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the "Samba 4.1 and newer" product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + ============================== Release Notes for Samba 4.11.2 October 29, 2019 @@ -69,8 +131,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================== Release Notes for Samba 4.11.1 -- 2.17.1 From 7fc8563c2f6381c0389cdbb8c833e9bb89ec068b Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Wed, 4 Dec 2019 10:03:55 +0100 Subject: [PATCH 351/376] VERSION: Disable GIT_SNAPSHOT for the 4.11.3 release. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e9cc49c7f77..ac97c314eff 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # -- 2.17.1 From 91f39dbda151f6a2768b6e5eff59f931f303721f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jul 2019 20:04:03 +0200 Subject: [PATCH 352/376] smbd: Increase a debug level This is not a real error, it happens when the share mode record is not around. Bug: https://bugzilla.samba.org/show_bug.cgi?id=14211 Signed-off-by: Volker Lendecke Reviewed-by: Uri Simchoni (cherry picked from commit 4b05fe7ca73dae30807680f0e0401340bfb2c738) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Wed Dec 4 10:15:19 UTC 2019 on sn-devel-184 --- source3/locking/share_mode_lock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 372e188c1c0..c70041ecf62 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -593,8 +593,8 @@ struct share_mode_lock *get_share_mode_lock( smb_fname, old_write_time); if (!NT_STATUS_IS_OK(status)) { - DBG_WARNING("get_static_share_mode_data failed: %s\n", - nt_errstr(status)); + DBG_DEBUG("get_static_share_mode_data failed: %s\n", + nt_errstr(status)); TALLOC_FREE(static_share_mode_record); goto fail; } -- 2.17.1 From b4fd49a46b245463eed45477fee9081e2e3c1e3a Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 10 Dec 2019 10:26:08 +0100 Subject: [PATCH 353/376] VERSION: Bump version up to 4.11.4. Signed-off-by: Karolin Seeger --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e9cc49c7f77..cb2725e300c 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=3 +SAMBA_VERSION_RELEASE=4 ######################################################## # If a official release has a serious bug # -- 2.17.1 From a7fa51a7a56236ffc29d65055ac42a5969299fc8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Nov 2019 12:02:13 -0800 Subject: [PATCH 354/376] s3: smbd: SMB2 - Ensure we use the correct session_id if encrypting an interim response. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14189 Signed-off-by: Jeremy Allison Reviewed-by: Stefan Metzmacher (cherry picked from commit eae1a45d09ef54dd6b59803eedca672ae9433902) --- source3/smbd/smb2_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index c0c4a0272d1..cc7d735d10e 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1616,7 +1616,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, outhdr = SMBD_SMB2_OUT_HDR_PTR(req); flags = IVAL(outhdr, SMB2_HDR_FLAGS); message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID); - session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID); + session_id = req->session->global->session_wire_id; async_id = message_id; /* keep it simple for now... */ -- 2.17.1 From 0521333d47737c8e2af0883590fa5384dcd045c9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Nov 2019 12:14:29 -0800 Subject: [PATCH 355/376] s3: smbd: Allow smbd_smb2_process_negprot() to return NTSTATUS as it can fail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit 868bc05cf5d575e20edcce241e3af1d0fa6d9824) --- source3/smbd/globals.h | 2 +- source3/smbd/smb2_server.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 47916ba29a1..9537aaa6b6f 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -236,7 +236,7 @@ NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, void reply_smb2002(struct smb_request *req, uint16_t choice); void reply_smb20ff(struct smb_request *req, uint16_t choice); -void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, +NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, uint64_t expected_seq_low, const uint8_t *inpdu, size_t size); diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index cc7d735d10e..1dc81b35b96 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -3613,7 +3613,7 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn return NT_STATUS_OK; } -void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, +NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, uint64_t expected_seq_low, const uint8_t *inpdu, size_t size) { @@ -3627,25 +3627,25 @@ void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, status = smbd_initialize_smb2(xconn, expected_seq_low); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(xconn, nt_errstr(status)); - return; + return status; } status = smbd_smb2_request_create(xconn, inpdu, size, &req); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(xconn, nt_errstr(status)); - return; + return status; } status = smbd_smb2_request_validate(req); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(xconn, nt_errstr(status)); - return; + return status; } status = smbd_smb2_request_setup_out(req); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(xconn, nt_errstr(status)); - return; + return status; } #ifdef WITH_PROFILE @@ -3660,16 +3660,17 @@ void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, status = smbd_smb2_request_dispatch(req); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(xconn, nt_errstr(status)); - return; + return status; } status = smbd_smb2_request_next_incoming(xconn); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(xconn, nt_errstr(status)); - return; + return status; } sconn->num_requests++; + return NT_STATUS_OK; } static int socket_error_from_errno(int ret, -- 2.17.1 From cff1d4c3421cbf56e128e5a57a9cc495a51a1f1f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Nov 2019 12:17:29 -0800 Subject: [PATCH 356/376] s3: smbd: Ensure we exit on smbd_smb2_process_negprot() fail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit a2d81d77c111379cbb6bd732c717307974eace0a) --- source3/smbd/process.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 177cb3cc505..7c45a648b77 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1969,7 +1969,14 @@ static void process_smb(struct smbXsrv_connection *xconn, if (smbd_is_smb2_header(inbuf, nread)) { const uint8_t *inpdu = inbuf + NBT_HDR_SIZE; size_t pdulen = nread - NBT_HDR_SIZE; - smbd_smb2_process_negprot(xconn, 0, inpdu, pdulen); + NTSTATUS status = smbd_smb2_process_negprot( + xconn, + 0, + inpdu, + pdulen); + if (!NT_STATUS_IS_OK(status)) { + exit_server_cleanly("SMB2 negprot fail"); + } return; } if (nread >= smb_size && valid_smb_header(inbuf) -- 2.17.1 From ce67f60822ea626df8e69022b139b20bc9637a3d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Nov 2019 12:21:06 -0800 Subject: [PATCH 357/376] s3: smbd: Change reply_smb20xx() to return NTSTATUS. Not yet used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit 836219c479b047403d2b0839a6b92ad637dbaea0) --- source3/smbd/smb2_negprot.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 528d3f8cc74..5cd9a9d7e3c 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -36,7 +36,7 @@ extern fstring remote_proto; * this is the entry point if SMB2 is selected via * the SMB negprot and the given dialect. */ -static void reply_smb20xx(struct smb_request *req, uint16_t dialect) +static NTSTATUS reply_smb20xx(struct smb_request *req, uint16_t dialect) { uint8_t *smb2_inpdu; uint8_t *smb2_hdr; @@ -48,7 +48,7 @@ static void reply_smb20xx(struct smb_request *req, uint16_t dialect) if (smb2_inpdu == NULL) { DEBUG(0, ("Could not push spnego blob\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } smb2_hdr = smb2_inpdu; smb2_body = smb2_hdr + SMB2_HDR_BODY; @@ -64,8 +64,7 @@ static void reply_smb20xx(struct smb_request *req, uint16_t dialect) req->outbuf = NULL; - smbd_smb2_process_negprot(req->xconn, 0, smb2_inpdu, len); - return; + return smbd_smb2_process_negprot(req->xconn, 0, smb2_inpdu, len); } /* -- 2.17.1 From e76ceea1debfcd5d530fe89dab1ebea27bc7ea60 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Nov 2019 12:43:25 -0800 Subject: [PATCH 358/376] s3: smbd: Change (*proto_reply_fn()) to return an NTSTATUS. That way the caller can know if the negprot really succeeded or not. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit f4caa4159bd3db5127e114718e606867348a4f47) --- source3/smbd/globals.h | 4 ++-- source3/smbd/negprot.c | 29 +++++++++++++++-------------- source3/smbd/smb2_negprot.c | 8 ++++---- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 9537aaa6b6f..3b56283679b 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -234,8 +234,8 @@ bool smbd_smb2_is_compound(const struct smbd_smb2_request *req); NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, struct smbXsrv_connection **_xconn); -void reply_smb2002(struct smb_request *req, uint16_t choice); -void reply_smb20ff(struct smb_request *req, uint16_t choice); +NTSTATUS reply_smb2002(struct smb_request *req, uint16_t choice); +NTSTATUS reply_smb20ff(struct smb_request *req, uint16_t choice); NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn, uint64_t expected_seq_low, const uint8_t *inpdu, size_t size); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 2d5edf1282c..3b2555e3d21 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -66,7 +66,7 @@ static void get_challenge(struct smbXsrv_connection *xconn, uint8_t buff[8]) Reply for the lanman 1.0 protocol. ****************************************************************************/ -static void reply_lanman1(struct smb_request *req, uint16_t choice) +static NTSTATUS reply_lanman1(struct smb_request *req, uint16_t choice) { int secword=0; time_t t = time(NULL); @@ -100,7 +100,7 @@ static void reply_lanman1(struct smb_request *req, uint16_t choice) status = smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN1); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - return; + return status; } /* Reply, SMBlockread, SMBwritelock supported. */ @@ -115,14 +115,14 @@ static void reply_lanman1(struct smb_request *req, uint16_t choice) srv_put_dos_date((char *)req->outbuf,smb_vwv8,t); - return; + return NT_STATUS_OK; } /**************************************************************************** Reply for the lanman 2.0 protocol. ****************************************************************************/ -static void reply_lanman2(struct smb_request *req, uint16_t choice) +static NTSTATUS reply_lanman2(struct smb_request *req, uint16_t choice) { int secword=0; time_t t = time(NULL); @@ -158,7 +158,7 @@ static void reply_lanman2(struct smb_request *req, uint16_t choice) status = smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN2); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - return; + return status; } /* Reply, SMBlockread, SMBwritelock supported. */ @@ -169,6 +169,7 @@ static void reply_lanman2(struct smb_request *req, uint16_t choice) SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60); srv_put_dos_date((char *)req->outbuf,smb_vwv8,t); + return NT_STATUS_OK; } /**************************************************************************** @@ -266,7 +267,7 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn) Reply for the nt protocol. ****************************************************************************/ -static void reply_nt1(struct smb_request *req, uint16_t choice) +static NTSTATUS reply_nt1(struct smb_request *req, uint16_t choice) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| @@ -359,7 +360,7 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) status = smbXsrv_connection_init_tables(xconn, PROTOCOL_NT1); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - return; + return status; } SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */ @@ -385,7 +386,7 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) if (ret == -1) { DEBUG(0, ("Could not push challenge\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } SCVAL(req->outbuf, smb_vwv16+1, ret); } @@ -395,7 +396,7 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) if (ret == -1) { DEBUG(0, ("Could not push workgroup string\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } ret = message_push_string(&req->outbuf, lp_netbios_name(), STR_UNICODE|STR_TERMINATE @@ -403,7 +404,7 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) if (ret == -1) { DEBUG(0, ("Could not push netbios name string\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } DEBUG(3,("not using SPNEGO\n")); } else { @@ -411,14 +412,14 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) if (spnego_blob.data == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } ret = message_push_blob(&req->outbuf, spnego_blob); if (ret == -1) { DEBUG(0, ("Could not push spnego blob\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } data_blob_free(&spnego_blob); @@ -426,7 +427,7 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) DEBUG(3,("using SPNEGO\n")); } - return; + return NT_STATUS_OK; } /* these are the protocol lists used for auto architecture detection: @@ -540,7 +541,7 @@ protocol [SMB 2.???] static const struct { const char *proto_name; const char *short_name; - void (*proto_reply_fn)(struct smb_request *req, uint16_t choice); + NTSTATUS (*proto_reply_fn)(struct smb_request *req, uint16_t choice); int protocol_level; } supported_protocols[] = { {"SMB 2.???", "SMB2_FF", reply_smb20ff, PROTOCOL_SMB2_10}, diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 5cd9a9d7e3c..f68bd8cd122 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -71,20 +71,20 @@ static NTSTATUS reply_smb20xx(struct smb_request *req, uint16_t dialect) * this is the entry point if SMB2 is selected via * the SMB negprot and the "SMB 2.002" dialect. */ -void reply_smb2002(struct smb_request *req, uint16_t choice) +NTSTATUS reply_smb2002(struct smb_request *req, uint16_t choice) { - reply_smb20xx(req, SMB2_DIALECT_REVISION_202); + return reply_smb20xx(req, SMB2_DIALECT_REVISION_202); } /* * this is the entry point if SMB2 is selected via * the SMB negprot and the "SMB 2.???" dialect. */ -void reply_smb20ff(struct smb_request *req, uint16_t choice) +NTSTATUS reply_smb20ff(struct smb_request *req, uint16_t choice) { struct smbXsrv_connection *xconn = req->xconn; xconn->smb2.allow_2ff = true; - reply_smb20xx(req, SMB2_DIALECT_REVISION_2FF); + return reply_smb20xx(req, SMB2_DIALECT_REVISION_2FF); } enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn, -- 2.17.1 From 5f8fef17042d9795b42b2d4c6ec7e1b6f2568be0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Nov 2019 12:46:16 -0800 Subject: [PATCH 359/376] s3: smbd: Ensure we exit if supported_protocols[protocol].proto_reply_fn() fails. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit e84910d919e02feab2a297fccbbf95f333e32119) --- source3/smbd/negprot.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 3b2555e3d21..8317dc49086 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -580,6 +580,7 @@ void reply_negprot(struct smb_request *req) bool signing_required = true; int max_proto; int min_proto; + NTSTATUS status; START_PROFILE(SMBnegprot); @@ -768,7 +769,11 @@ void reply_negprot(struct smb_request *req) fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(sconn, conn_snum_used, true); - supported_protocols[protocol].proto_reply_fn(req, choice); + status = supported_protocols[protocol].proto_reply_fn(req, choice); + if (!NT_STATUS_IS_OK(status)) { + exit_server_cleanly("negprot function failed\n"); + } + DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); DBG_INFO("negprot index=%zu\n", choice); -- 2.17.1 From cfa22afe0a77cd56f25b6b7aa93f36a790ed6deb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Dec 2019 17:23:21 -0800 Subject: [PATCH 360/376] python: tests. Add test for fuzzing smbd crash bug. Mark knownfail for now. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Andrew Bartlett (cherry picked from commit 46899ecf836d350c0c29b615869851da7d0ad6fb) --- python/samba/tests/smbd_fuzztest.py | 77 +++++++++++++++++++++++++++++ selftest/knownfail.d/smb1_fuzz_smbd | 1 + selftest/tests.py | 1 + 3 files changed, 79 insertions(+) create mode 100644 python/samba/tests/smbd_fuzztest.py create mode 100644 selftest/knownfail.d/smb1_fuzz_smbd diff --git a/python/samba/tests/smbd_fuzztest.py b/python/samba/tests/smbd_fuzztest.py new file mode 100644 index 00000000000..900cddf3880 --- /dev/null +++ b/python/samba/tests/smbd_fuzztest.py @@ -0,0 +1,77 @@ +# Unix SMB/CIFS implementation. Tests for smbd fuzzing. +# Copyright (C) Jeremy Allison 2019. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import sys +import samba +import os +import binascii +import socket + +class fuzzsmbd(samba.tests.TestCase): + def test_bug_14205(self): + # + # badblob consists of an incorrectly + # terminated SMB1 Negprot, with a valid SessionSetup after. + # BUG: #14205 causes the smbd server to crash. + # + state = True; + badblob = binascii.a2b_base64("AAAA1P9TTUJyAAAAABhDyAAAAAAAAAAAAAAAACcA/v8AAAAAALEAAlBDIE5F" + "VFdPUksgUFJPR1JBTSD//jAAAk1JQ1JPU09GVCBOR1RXT1JLUyAxLjANDAJN" + "SR3hkXOl0mb+QXW4Da/jp0f+AAAA1P9TTUJyAAAAABgDyAAABDQAAAAAAAAA" + "ACcA/v8AAAAAALEAAlBDIE5FVFdPUksgUFJPR1JBFBX//jAAAk1JQ1JPU09G" + "VCBOR1RXT1JLUyAxLjANDAJNSR3hkUal0mb+QXW4Da/jp0f+AAAA1P9TTUJz" + "LTE0OEF1uA2v46dH/gqAIIwiAoRiVHWgODu8OdksJQAAAAAnAP7/AAAAAACx" + "AAJQQyBORVRXT1JLIFBST0dSQU0g//4wAAJNSUNST1NPRlQgTkdUV09SS1Mg" + "MS4wDQwCTUkd4ZFGpdJm/kF1uA2v46dH/gAAANT/U01Ccy0xNDgyMTIyOTE3" + "Nzk2MzIAAAAAGAPIAAAAAAAAAAAAAAAAJwD+/wAAAAAAsQACUEMgTkVUV09S" + "SyBQUk9HUkFNIP/+MAACTUlDUk9TT0ZUIE5HVFdPUktTIDEuMA0GAAAAAAAA" + "AKXSZv5BdbgNr+OnR/4AAADU/1NNQnMtMTQ4MjEyMjkxNzc5NjMyNDQ4NDNA" + "ujcyNjgAsQACUEMgTkVUF09SSyAgAAAAAAAAAP/+MAACTUlDUk9TT0bAIE5H" + "BwAtMjMxODIxMjE4MTM5OTU0ODA2OP5BdbgNr+OnR/4KgCCMIgKEYlR1oDg7" + "vDnZLCWy") + s = None + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(("fileserver", 445)) + s.send(badblob) + # Read the 39-byte SMB1 reply to the SMB1 Negprot. + # This is an error message saying the Negprot was + # invalid. + rb = s.recv(1024) + try: + # Read again to wait for the server to exit. + rb = s.recv(1024) + except socket.error as e: + # We expect a socket error here as + # in both success and fail cases the + # server just resets the connection. + pass + finally: + pass + finally: + if s is not None: + s.close() + # + # If the server crashed there is the + # following message in the debug log. + # + for line in open(os.environ['SMBD_TEST_LOG']): + if "INTERNAL ERROR: Signal 11 in pid" in line: + print("Found crash in smbd log") + state = False; + break + self.assertTrue(state) diff --git a/selftest/knownfail.d/smb1_fuzz_smbd b/selftest/knownfail.d/smb1_fuzz_smbd new file mode 100644 index 00000000000..82b1b26254f --- /dev/null +++ b/selftest/knownfail.d/smb1_fuzz_smbd @@ -0,0 +1 @@ +^samba.tests.smbd_fuzztest diff --git a/selftest/tests.py b/selftest/tests.py index bbb5709ee47..1cadaf94423 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -90,6 +90,7 @@ planpythontestsuite( "none", "wafsamba.tests.test_suite", extra_path=[os.path.join(samba4srcdir, "..", "buildtools"), os.path.join(samba4srcdir, "..", "third_party", "waf")]) +planpythontestsuite("fileserver", "samba.tests.smbd_fuzztest") def cmdline(script, *args): -- 2.17.1 From 36da9ac22d893219bfeff2e019b332716e4733ca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Nov 2019 12:53:09 -0800 Subject: [PATCH 361/376] s3: smbd: Only set xconn->smb1.negprot.done = true after supported_protocols[protocol].proto_reply_fn() succeeds. Otherwise we can end up with negprot.done set, but without smbXsrv_connection_init_tables() being called. This can cause a client self-crash. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14205 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Dec 4 21:27:24 UTC 2019 on sn-devel-184 (cherry picked from commit 8db0c1bff6f42feabd2e4d9dfb13ae12cc29607b) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Fri Dec 13 12:30:57 UTC 2019 on sn-devel-184 --- selftest/knownfail.d/smb1_fuzz_smbd | 1 - source3/smbd/negprot.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 selftest/knownfail.d/smb1_fuzz_smbd diff --git a/selftest/knownfail.d/smb1_fuzz_smbd b/selftest/knownfail.d/smb1_fuzz_smbd deleted file mode 100644 index 82b1b26254f..00000000000 --- a/selftest/knownfail.d/smb1_fuzz_smbd +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.smbd_fuzztest diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 8317dc49086..e77c8f52261 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -588,7 +588,6 @@ void reply_negprot(struct smb_request *req) END_PROFILE(SMBnegprot); exit_server_cleanly("multiple negprot's are not permitted"); } - xconn->smb1.negprot.done = true; if (req->buflen == 0) { DEBUG(0, ("negprot got no protocols\n")); @@ -778,6 +777,8 @@ void reply_negprot(struct smb_request *req) DBG_INFO("negprot index=%zu\n", choice); + xconn->smb1.negprot.done = true; + /* We always have xconn->smb1.signing_state also for >= SMB2_02 */ signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state); if (signing_required && (chosen_level < PROTOCOL_NT1)) { -- 2.17.1 From a3e0dc33741044f68788796fe669b6a5f0004ea7 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Mon, 16 Dec 2019 15:53:05 +0100 Subject: [PATCH 362/376] VERSION: Disable GIT_SNAPSHOT for the 4.11.4 release. Signed-off-by: Karolin Seeger --- VERSION | 2 +- WHATSNEW.txt | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index cb2725e300c..b53fc3ab1db 100644 --- a/VERSION +++ b/VERSION @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 8bafa38b47c..830081446ab 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,84 @@ + ============================== + Release Notes for Samba 4.11.4 + December 16, 2019 + ============================== + + +This is the latest stable release of the Samba 4.11 release series. + + +Changes since 4.11.3: +--------------------- + +o Jeremy Allison + * BUG 14161: s3: libsmb: Ensure SMB1 cli_qpathinfo2() doesn't return an inode + number. + * BUG 14174: s3: utils: smbtree. Ensure we don't call cli_RNetShareEnum() + on an SMB1 connection. + * BUG 14176: NT_STATUS_ACCESS_DENIED becomes EINVAL when using SMB2 in + SMBC_opendir_ctx. + * BUG 14189: s3: smbd: SMB2 - Ensure we use the correct session_id if + encrypting an interim response. + * BUG 14205: Prevent smbd crash after invalid SMB1 negprot. + +o Ralph Boehme + * BUG 13745: s3:printing: Fix %J substition. + * BUG 13925: s3: Remove now unneeded call to cmdline_messaging_context(). + * BUG 14069: Incomplete conversion of former parametric options. + * BUG 14070: Fix sync dosmode fallback in async dosmode codepath. + * BUG 14171: vfs_fruit returns capped resource fork length. + +o Isaac Boukris + * BUG 14116: libnet_join: Add SPNs for additional-dns-hostnames entries. + +o Volker Lendecke + * BUG 14211: smbd: Increase a debug level. + +o Stefan Metzmacher + * BUG 14153: Prevent azure ad connect from reporting discovery errors: + reference-value-not-ldap-conformant. + +o Christof Schmitt + * BUG 14179: krb5_plugin: Fix developer build with newer heimdal system + library. + +o Andreas Schneider + * BUG 14168: replace: Only link libnsl and libsocket if requrired. + +o Martin Schwenke + * BUG 14175: ctdb: Incoming queue can be orphaned causing communication + breakdown. + +o Uri Simchoni + * BUG 13846: ldb: Release ldb 2.0.8. Cross-compile will not take + cross-answers or cross-execute. + * BUG 13856: heimdal-build: Avoid hard-coded /usr/include/heimdal in + asn1_compile-generated code. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the "Samba 4.1 and newer" product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + ============================== Release Notes for Samba 4.11.3 December 10, 2019 @@ -57,8 +138,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================== Release Notes for Samba 4.11.2 -- 2.17.1 From 5a75d9814091631001be8d7d8ccec66ea6380cfb Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Mon, 16 Dec 2019 15:54:00 +0100 Subject: [PATCH 363/376] VERSION: Bump version up to 4.11.5... and re-enable GIT_SNAPSHOT. Signed-off-by: Karolin Seeger --- VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index b53fc3ab1db..7bbd4754860 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=11 -SAMBA_VERSION_RELEASE=4 +SAMBA_VERSION_RELEASE=5 ######################################################## # If a official release has a serious bug # @@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=no +SAMBA_VERSION_IS_GIT_SNAPSHOT=yes ######################################################## # This is for specifying a release nickname # -- 2.17.1 From a7505aabbe9710a0b025f40ffd5c4db1a6d78ed0 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 3 Dec 2019 11:17:26 +1300 Subject: [PATCH 364/376] pygpo: use correct method flags The METH_KEYWORDS argument must always be combined with METH_VARARGS. In Python up to 3.7 this was checked at runtime, and as we had no callers to get_unix_path() in Python we never noticed. In Python 3.8 it is checked at import time, and everyone notices even if they aren't directly using GPOs. Found and reported by Val Kulkov. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14209 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett (cherry picked from commit 12cccf3447333dfd4f5e437cd57ca5ec68724fdd) --- libgpo/pygpo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c index 581d20e0649..97bbb3ec528 100644 --- a/libgpo/pygpo.c +++ b/libgpo/pygpo.c @@ -118,7 +118,7 @@ out: static PyMethodDef GPO_methods[] = { {"get_unix_path", PY_DISCARD_FUNC_SIG(PyCFunction, py_gpo_get_unix_path), - METH_KEYWORDS, + METH_VARARGS | METH_KEYWORDS, NULL }, {NULL} }; -- 2.17.1 From db5c0d6c05b7d15ca0503642bb7741bf57d2d489 Mon Sep 17 00:00:00 2001 From: Torsten Fohrer Date: Sun, 15 Dec 2019 16:58:40 +0100 Subject: [PATCH 365/376] Avoiding bad call flags with python 3.8, using METH_NOARGS instead of zero. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (C) SBE network solutions GmbH BUG: https://bugzilla.samba.org/show_bug.cgi?id=14209 Signed-off-by: Torsten Fohrer Reviewed-by: Douglas Bagnall Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Wed Dec 18 14:33:58 UTC 2019 on sn-devel-184 (cherry picked from commit f0eb1e623f76d3dbd0c22f96cabebd1041c147df) --- source4/auth/gensec/pygensec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index b2c1e9c279a..c866180edb3 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -678,7 +678,7 @@ static PyMethodDef py_gensec_security_methods[] = { "S.have_feature()\n Return True if GENSEC negotiated a particular feature." }, { "set_max_update_size", (PyCFunction)py_gensec_set_max_update_size, METH_VARARGS, "S.set_max_update_size(max_size) \n Some mechs can fragment update packets, needs to be use before the mech is started." }, - { "max_update_size", (PyCFunction)py_gensec_max_update_size, 0, + { "max_update_size", (PyCFunction)py_gensec_max_update_size, METH_NOARGS, "S.max_update_size() \n Return the current max_update_size." }, { "update", (PyCFunction)py_gensec_update, METH_VARARGS, "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance. Repeat with new packets until finished is true or exception." }, -- 2.17.1 From 3659b26bcb4a3592534a88d1e59712bb272b0d92 Mon Sep 17 00:00:00 2001 From: Anoop C S Date: Tue, 12 Nov 2019 19:58:43 +0530 Subject: [PATCH 366/376] s3: VFS: glusterfs: Reset nlinks for symlink entries during readdir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On receiving an already initialized stat_ex buffer for readdir() call we invoke readdirplus() GlusterFS API, an optimized variant of readdir(), which then returns stat information along with dir entry result. But for symlink entries we don't know if link or target info is needed. In that case it is better to leave this decision back to caller by resetting nlinks value inside stat information to make it invalid. This was also preventing us from displaying msdfs link as directories inside the share. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14182 Signed-off-by: Anoop C S Reviewed-by: Günther Deschner Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Dec 17 21:53:07 UTC 2019 on sn-devel-184 (cherry picked from commit fca2d3e0d1fa5af59e7b729f7c1d126f7b81e149) Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Thu Dec 19 09:52:17 UTC 2019 on sn-devel-184 --- source3/modules/vfs_glusterfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 8827bf018ab..f23a8821add 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -564,7 +564,10 @@ static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle, } if (sbuf != NULL) { - smb_stat_ex_from_stat(sbuf, &stat); + SET_STAT_INVALID(*sbuf); + if (!S_ISLNK(stat.st_mode)) { + smb_stat_ex_from_stat(sbuf, &stat); + } } END_PROFILE(syscall_readdir); -- 2.17.1 From 276a07d8eff6273734437ed5acb2ec1217cf7cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Tue, 7 Jan 2020 10:21:18 +0100 Subject: [PATCH 367/376] docs-xml/winbindnssinfo: clarify interaction with idmap_ad etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=14122 RN: docs: clarify interaction between winbind nss info and idmap backend Signed-off-by: Bjoern Jacke Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Wed Jan 8 15:37:46 UTC 2020 on sn-devel-184 (cherry picked from commit 55fbd4c05b477e95920b53b94eda2572e075e6e1) --- docs-xml/smbdotconf/winbind/winbindnssinfo.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs-xml/smbdotconf/winbind/winbindnssinfo.xml b/docs-xml/smbdotconf/winbind/winbindnssinfo.xml index d8347442a8d..e6d17c256a1 100644 --- a/docs-xml/smbdotconf/winbind/winbindnssinfo.xml +++ b/docs-xml/smbdotconf/winbind/winbindnssinfo.xml @@ -22,11 +22,10 @@ Domain Controller does support the Microsoft "Services for Unix" (SFU) LDAP schema, winbind can retrieve the login shell and the home directory attributes directly from your Directory Server. For SFU 3.0 or 3.5 simply choose - "sfu", if you use SFU 2.0 please choose "sfu20". Note that - retrieving UID and GID from your ADS-Server requires to - use idmap config DOMAIN:backend = ad - as well. The primary group membership is currently - always calculated via the "primaryGroupID" LDAP attribute. + "sfu", if you use SFU 2.0 please choose "sfu20". + Note that for the idmap backend idmap_ad + you need to configure those settings in the idmap configuration section. + Make sure to consult the documentation of the idmap backend that you are using. -- 2.17.1 From 75d088aede531bfe721c397fd1900cc26095b9f3 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 19 Dec 2019 16:31:24 +1300 Subject: [PATCH 368/376] test upgradedns: ensure lmdb lock files linked Add tests to check that the '-lock' files for the dns partitions as well as the data files are linked when running samba_dnsupgrade --dns-backend=BIND9_DLZ failure to create these links can cause corruption of the corresponding data file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14199 Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett (cherry picked from commit f0cebbe4dd0317e2abfcbe252977383e6f37f3bd) --- python/samba/tests/samba_upgradedns_lmdb.py | 75 +++++++++++++++++++++ selftest/knownfail.d/bug-14199 | 1 + source4/selftest/tests.py | 2 + 3 files changed, 78 insertions(+) create mode 100644 python/samba/tests/samba_upgradedns_lmdb.py create mode 100644 selftest/knownfail.d/bug-14199 diff --git a/python/samba/tests/samba_upgradedns_lmdb.py b/python/samba/tests/samba_upgradedns_lmdb.py new file mode 100644 index 00000000000..048993152e2 --- /dev/null +++ b/python/samba/tests/samba_upgradedns_lmdb.py @@ -0,0 +1,75 @@ +# Unix SMB/CIFS implementation. +# Copyright (C) Catalyst IT Ltd. 2019 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +from samba.tests.samba_tool.base import SambaToolCmdTest +import os +import shutil + + +class UpgradeDnsLmdbTestCase(SambaToolCmdTest): + """ + Tests for dns upgrade on a lmdb backend + """ + + def setUp(self): + super(UpgradeDnsLmdbTestCase, self).setUp() + self.tempsambadir = os.path.join(self.tempdir, "samba") + os.mkdir(self.tempsambadir) + + # provision a domain + # + # returns the tuple (ret, stdout, stderr) + def provision(self): + command = ( + "samba-tool " + "domain provision " + "--realm=foo.example.com " + "--domain=FOO " + "--targetdir=%s " + "--backend-store=mdb " + "--use-ntvfs " % self.tempsambadir) + return self.run_command(command) + + # upgrade a domains dns to BIND9 + # + # returns the tuple (ret, stdout, stderr) + def upgrade_dns(self): + command = ( + "samba_upgradedns " + "--dns-backend=BIND9_DLZ " + "--configfile %s/etc/smb.conf" % self.tempsambadir) + return self.run_command(command) + + def tearDown(self): + super(UpgradeDnsLmdbTestCase, self).tearDown() + shutil.rmtree(self.tempsambadir) + + def test_lmdb_lock_files_linked_on_upgrade_to_bind9_dlz(self): + """ + Ensure that links are created for the lock files as well as the + data files + """ + self.provision() + self.upgrade_dns() + directory = ("%s/bind-dns/dns/sam.ldb.d" % self.tempsambadir) + for filename in os.listdir(directory): + if filename.endswith(".ldb") and "DNSZONES" in filename: + lock_file = ("%s/%s-lock" % (directory, filename)) + self.assertTrue( + os.path.isfile(lock_file), + msg=("Lock file %s/%s-lock for %s, does not exist" % + (directory, filename, filename))) diff --git a/selftest/knownfail.d/bug-14199 b/selftest/knownfail.d/bug-14199 new file mode 100644 index 00000000000..f9508910b79 --- /dev/null +++ b/selftest/knownfail.d/bug-14199 @@ -0,0 +1 @@ +^samba.tests.samba_upgradedns_lmdb.samba.tests.samba_upgradedns_lmdb. diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 2bc4561b87a..f8fb0074c02 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -700,6 +700,8 @@ planpythontestsuite("none", "samba.tests.samba_tool.help") planpythontestsuite("ad_dc_default:local", "samba.tests.samba_tool.passwordsettings") planpythontestsuite("ad_dc:local", "samba.tests.samba_tool.dsacl") +planpythontestsuite("none", "samba.tests.samba_upgradedns_lmdb") + # Run these against chgdcpass to share the runtime load planpythontestsuite("chgdcpass:local", "samba.tests.samba_tool.sites") planpythontestsuite("chgdcpass:local", "samba.tests.samba_tool.dnscmd") -- 2.17.1 From 54a028bd32b41e1ba7e10b3f64877494a121d655 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 19 Dec 2019 16:31:46 +1300 Subject: [PATCH 369/376] upgradedns: ensure lmdb lock files linked Ensure that the '-lock' files for the dns partitions as well as the data files are linked when running samba_dnsupgrade --dns-backend=BIND9_DLZ failure to create these links can cause corruption of the corresponding data file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14199 Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett (cherry picked from commit 0bd479140c18ab79479ced4f25f366744c3afe18) --- python/samba/provision/sambadns.py | 10 ++++++++++ selftest/knownfail.d/bug-14199 | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/bug-14199 diff --git a/python/samba/provision/sambadns.py b/python/samba/provision/sambadns.py index 9b245608c63..239c99ff0b9 100644 --- a/python/samba/provision/sambadns.py +++ b/python/samba/provision/sambadns.py @@ -858,9 +858,19 @@ def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid): os.path.join(dns_samldb_dir, metadata_file)) os.link(os.path.join(private_dir, domainzone_file), os.path.join(dns_dir, domainzone_file)) + if backend_store == "mdb": + # If the file is an lmdb data file need to link the + # lock file as well + os.link(os.path.join(private_dir, domainzone_file + "-lock"), + os.path.join(dns_dir, domainzone_file + "-lock")) if forestzone_file: os.link(os.path.join(private_dir, forestzone_file), os.path.join(dns_dir, forestzone_file)) + if backend_store == "mdb": + # If the database file is an lmdb data file need to link the + # lock file as well + os.link(os.path.join(private_dir, forestzone_file + "-lock"), + os.path.join(dns_dir, forestzone_file + "-lock")) except OSError: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") diff --git a/selftest/knownfail.d/bug-14199 b/selftest/knownfail.d/bug-14199 deleted file mode 100644 index f9508910b79..00000000000 --- a/selftest/knownfail.d/bug-14199 +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.samba_upgradedns_lmdb.samba.tests.samba_upgradedns_lmdb. -- 2.17.1 From 67e429d86aed47f36a2bf8c05ae2e47e356bfa12 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 12 Dec 2019 22:14:50 +0100 Subject: [PATCH 370/376] vfs_ceph_snapshots: fix root relative path handling For file paths relative to root, ceph_snap_get_parent_path() may return an empty parent dir string, in which case the CephFS snashot path should be ".snap". Bug: https://bugzilla.samba.org/show_bug.cgi?id=14216 Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 54293f92cd83efc3a5a78fc29a85643921da9d32) --- source3/modules/vfs_ceph_snapshots.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source3/modules/vfs_ceph_snapshots.c b/source3/modules/vfs_ceph_snapshots.c index 4d935a55a1a..0b5f7ab59a5 100644 --- a/source3/modules/vfs_ceph_snapshots.c +++ b/source3/modules/vfs_ceph_snapshots.c @@ -390,8 +390,12 @@ static int ceph_snap_get_shadow_copy_data(struct vfs_handle_struct *handle, parent_dir = tmp; } - ret = snprintf(snaps_path, sizeof(snaps_path), "%s/%s", - parent_dir, snapdir); + if (strlen(parent_dir) == 0) { + ret = strlcpy(snaps_path, snapdir, sizeof(snaps_path)); + } else { + ret = snprintf(snaps_path, sizeof(snaps_path), "%s/%s", + parent_dir, snapdir); + } if (ret >= sizeof(snaps_path)) { ret = -EINVAL; goto err_out; @@ -534,7 +538,11 @@ static int ceph_snap_gmt_convert_dir(struct vfs_handle_struct *handle, /* * Temporally use the caller's return buffer for this. */ - ret = snprintf(_converted_buf, buflen, "%s/%s", name, snapdir); + if (strlen(name) == 0) { + ret = strlcpy(_converted_buf, snapdir, buflen); + } else { + ret = snprintf(_converted_buf, buflen, "%s/%s", name, snapdir); + } if (ret >= buflen) { ret = -EINVAL; goto err_out; -- 2.17.1 From 3889444e00866eafebcdfb42be5f07990b881c56 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Sun, 15 Dec 2019 17:08:24 +0100 Subject: [PATCH 371/376] lib/ldb/tests: include stdint.h before cmocka.h This fix the following build failures: [2466/3864] Linking bin/default/lib/ldb/ldbmodify In file included from /home/buildroot/autobuild/instance-0/output-1/host/opt/ext-toolchain/lib/gcc/mips64el-buildroot-linux-uclibc/5.5.0/include/stdint.h:9:0, from ../../lib/tevent/tevent.h:31, from ../../lib/ldb/include/ldb.h:51, from ../../lib/ldb/tests/test_ldb_dn.c:25: /home/buildroot/autobuild/instance-0/output-1/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/stdint.h:122:27: error: conflicting types for 'uintptr_t' typedef unsigned long int uintptr_t; ^ In file included from ../../lib/ldb/tests/test_ldb_dn.c:23:0: /home/buildroot/autobuild/instance-0/output-1/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/cmocka.h:132:28: note: previous declaration of 'uintptr_t' was here typedef unsigned int uintptr_t; ^ In file included from /home/buildroot/autobuild/instance-0/output-1/host/opt/ext-toolchain/lib/gcc/mips64el-buildroot-linux-uclibc/5.5.0/include/stdint.h:9:0, from ../../lib/tevent/tevent.h:31, from ../../lib/ldb/tests/ldb_key_value_test.c:48: /home/buildroot/autobuild/instance-0/output-1/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/stdint.h:122:27: error: conflicting types for 'uintptr_t' typedef unsigned long int uintptr_t; ^ In file included from ../../lib/ldb/tests/ldb_key_value_test.c:43:0: /home/buildroot/autobuild/instance-0/output-1/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/cmocka.h:132:28: note: previous declaration of 'uintptr_t' was here typedef unsigned int uintptr_t; ^ Fixes: - http://autobuild.buildroot.org/results/9507739b3d5d51024ee9c60b74c2f85d5004e7e2 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14218 Signed-off-by: Fabrice Fontaine Reviewed-by: Uri Simchoni Reviewed-by: Andreas Schneider (cherry picked from commit f8799bf076d647d73aa749f3864d022a366c3904) --- lib/ldb/tests/ldb_key_value_sub_txn_test.c | 1 + lib/ldb/tests/ldb_key_value_test.c | 1 + lib/ldb/tests/ldb_lmdb_size_test.c | 1 + lib/ldb/tests/ldb_lmdb_test.c | 1 + lib/ldb/tests/ldb_no_lmdb_test.c | 1 + lib/ldb/tests/test_ldb_dn.c | 1 + 6 files changed, 6 insertions(+) diff --git a/lib/ldb/tests/ldb_key_value_sub_txn_test.c b/lib/ldb/tests/ldb_key_value_sub_txn_test.c index e71f81b866e..1eafd2d79e9 100644 --- a/lib/ldb/tests/ldb_key_value_sub_txn_test.c +++ b/lib/ldb/tests/ldb_key_value_sub_txn_test.c @@ -37,6 +37,7 @@ */ #include #include +#include #include #include diff --git a/lib/ldb/tests/ldb_key_value_test.c b/lib/ldb/tests/ldb_key_value_test.c index 3f31bb98350..458452e5dc4 100644 --- a/lib/ldb/tests/ldb_key_value_test.c +++ b/lib/ldb/tests/ldb_key_value_test.c @@ -39,6 +39,7 @@ */ #include #include +#include #include #include diff --git a/lib/ldb/tests/ldb_lmdb_size_test.c b/lib/ldb/tests/ldb_lmdb_size_test.c index af015fa72b5..cd7ab03a1f0 100644 --- a/lib/ldb/tests/ldb_lmdb_size_test.c +++ b/lib/ldb/tests/ldb_lmdb_size_test.c @@ -43,6 +43,7 @@ */ #include #include +#include #include #include diff --git a/lib/ldb/tests/ldb_lmdb_test.c b/lib/ldb/tests/ldb_lmdb_test.c index 78758bbbe16..798a1916281 100644 --- a/lib/ldb/tests/ldb_lmdb_test.c +++ b/lib/ldb/tests/ldb_lmdb_test.c @@ -40,6 +40,7 @@ */ #include #include +#include #include #include diff --git a/lib/ldb/tests/ldb_no_lmdb_test.c b/lib/ldb/tests/ldb_no_lmdb_test.c index 8e5a6eee8d2..be23d744004 100644 --- a/lib/ldb/tests/ldb_no_lmdb_test.c +++ b/lib/ldb/tests/ldb_no_lmdb_test.c @@ -40,6 +40,7 @@ */ #include #include +#include #include #include diff --git a/lib/ldb/tests/test_ldb_dn.c b/lib/ldb/tests/test_ldb_dn.c index 05f30e4ac67..000ffa72796 100644 --- a/lib/ldb/tests/test_ldb_dn.c +++ b/lib/ldb/tests/test_ldb_dn.c @@ -19,6 +19,7 @@ #include #include +#include #include #include -- 2.17.1 From 1d28d27070a7ade82283dab11c9ef7cadfbf54fb Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Mon, 16 Dec 2019 10:28:53 +0100 Subject: [PATCH 372/376] source4/utils/oLschema2ldif: include stdint.h before cmocka.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix the following build failure: In file included from /home/fabrice/buildroot/output/host/opt/ext-toolchain/lib/gcc/mips64el-buildroot-linux-uclibc/5.5.0/include/stdint.h:9:0, from /home/fabrice/buildroot/output/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/inttypes.h:27, from ../../lib/replace/../replace/replace.h:64, from ../../source4/include/includes.h:23, from ../../source4/utils/oLschema2ldif/test.c:25: /home/fabrice/buildroot/output/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/stdint.h:122:27: error: conflicting types for ‘uintptr_t’ typedef unsigned long int uintptr_t; ^ In file included from ../../source4/utils/oLschema2ldif/test.c:23:0: /home/fabrice/buildroot/output/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/cmocka.h:132:28: note: previous declaration of ‘uintptr_t’ was here typedef unsigned int uintptr_t; Fixes: - http://autobuild.buildroot.org/results/9507739b3d5d51024ee9c60b74c2f85d5004e7e2 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14218 Signed-off-by: Fabrice Fontaine Reviewed-by: Uri Simchoni Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Wed Dec 18 16:57:52 UTC 2019 on sn-devel-184 (cherry picked from commit 1bfb384018deb2ee5c27dbea9fa2cdd98901fdcc) --- source4/utils/oLschema2ldif/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source4/utils/oLschema2ldif/test.c b/source4/utils/oLschema2ldif/test.c index 6748ce08c33..3834ea462fd 100644 --- a/source4/utils/oLschema2ldif/test.c +++ b/source4/utils/oLschema2ldif/test.c @@ -19,6 +19,7 @@ #include #include +#include #include #include -- 2.17.1 From 890513b5b3cf8c8b14fc21c1f095b9d4a3f94e04 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 16 Dec 2019 15:50:17 +0100 Subject: [PATCH 373/376] librpc: Fix string length checking in ndr_pull_charset_to_null() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14219 Pair-Programmed-With: Guenther Deschner Signed-off-by: Guenther Deschner Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit f11e207e01c52566c47e350ff240fe95392de0c3) --- librpc/ndr/ndr_string.c | 49 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c index 0fefc887c30..3def351072c 100644 --- a/librpc/ndr/ndr_string.c +++ b/librpc/ndr/ndr_string.c @@ -553,6 +553,47 @@ _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size) return i+1; } +/** + * @brief Get the string length including the null terminator if available. + * + * This checks the string length based on the elements. The returned number + * includes the terminating null byte(s) if found. + * + * @param[in] _var The string the calculate the length for. + * + * @param[in] length The length of the buffer passed by _var. + * + * @param[in] element_size The element_size of a string char in bytes. + * + * @return The length of the strings or 0. + */ +static uint32_t ndr_string_n_length(const void *_var, + size_t length, + uint32_t element_size) +{ + size_t i = 0; + uint8_t zero[4] = {0,0,0,0}; + const char *var = (const char *)_var; + int cmp; + + if (element_size > 4) { + return 0; + } + + for (i = 0; i < length; i++, var += element_size) { + cmp = memcmp(var, zero, element_size); + if (cmp == 0) { + break; + } + } + + if (i == length) { + return length; + } + + return i + 1; +} + _PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size) { uint32_t i; @@ -622,8 +663,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, int nd NDR_PULL_NEED_BYTES(ndr, length*byte_mul); - str_len = ndr_string_length(ndr->data+ndr->offset, byte_mul); - str_len = MIN(str_len, length); /* overrun protection */ + str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul); + if (str_len == 0) { + return ndr_pull_error(ndr, NDR_ERR_LENGTH, + "Invalid length"); + } + if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX, ndr->data+ndr->offset, str_len*byte_mul, discard_const_p(void *, var), -- 2.17.1 From 103d94566f15d2fdf880cfb5f654896c67d02a42 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Fri, 13 Dec 2019 11:09:04 +1100 Subject: [PATCH 374/376] ctdb-scripts: Strip square brackets when gathering connection info ss added square brackets around IPv6 addresses in versions > 4.12.0 via commit aba9c23a6e1cb134840c998df14888dca469a485. CentOS 7 added this feature somewhere mid-release. So, backward compatibility is obviously needed. As per the comment protocol/protocol_util.c should probably print and parse such square brackets. However, for backward compatibility the brackets would have to be stripped in both places in update_tickles()... or added to the ss output when missing. Best to leave this until we have a connection tracking daemon. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14227 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs (cherry picked from commit 693080abe4d8bec96280af5a6aa668251a98ec5d) --- ctdb/config/functions | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ctdb/config/functions b/ctdb/config/functions index 1dc16532890..2e9c3ef6bf0 100755 --- a/ctdb/config/functions +++ b/ctdb/config/functions @@ -977,10 +977,16 @@ update_tickles () _my_connections="${tickledir}/${_port}.connections.$$" # Parentheses are needed around the filters for precedence but # the parentheses can't be empty! + # + # Recent versions of ss print square brackets around IPv6 + # addresses. While it is desirable to update CTDB's address + # parsing and printing code, something needs to be done here + # for backward compatibility, so just delete the brackets. ss -tn state established \ "${_ip_filter:+( ${_ip_filter} )}" \ "${_port_filter:+( ${_port_filter} )}" | awk 'NR > 1 {print $4, $3}' | + tr -d '][' | sort >"$_my_connections" # Record our current tickles in a temporary file -- 2.17.1 From ee215ff101d6e3de23264fbbca9c9753a4751413 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Thu, 28 Nov 2019 14:00:58 +1100 Subject: [PATCH 375/376] ctdb-tests: Skip some tests that don't work with IPv6 See the comments added to the tests. It may be possible to rewrite these so they do something sane for IPv6... some other time. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14227 RN: Fix IPv6 issues (NFS connection tracking, tests) Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Fri Jan 3 00:00:55 UTC 2020 on sn-devel-184 (backported from commit 9edf15afc219a1a782ec1e4d29909361bbabc744) Signed-off-by: Martin Schwenke Autobuild-User(v4-11-test): Karolin Seeger Autobuild-Date(v4-11-test): Tue Jan 14 10:28:01 UTC 2020 on sn-devel-184 --- ctdb/tests/complex/60_rogueip_releaseip.sh | 10 ++++++++++ ctdb/tests/complex/61_rogueip_takeip.sh | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/ctdb/tests/complex/60_rogueip_releaseip.sh b/ctdb/tests/complex/60_rogueip_releaseip.sh index 88e4e554c34..99d0d406e6f 100755 --- a/ctdb/tests/complex/60_rogueip_releaseip.sh +++ b/ctdb/tests/complex/60_rogueip_releaseip.sh @@ -21,6 +21,16 @@ select_test_node_and_ips echo "Using $test_ip, which is onnode $test_node" +# This test depends on being able to assign a duplicate address on a +# 2nd node. However, IPv6 guards against this and causes the test to +# fail. +case "$test_ip" in +*:*) + echo "SKIPPING TEST: not supported for IPv6 addresses" + exit 0 + ;; +esac + get_test_ip_mask_and_iface echo "Finding another node that knows about $test_ip" diff --git a/ctdb/tests/complex/61_rogueip_takeip.sh b/ctdb/tests/complex/61_rogueip_takeip.sh index 2c5f7c5c999..e1981eba572 100755 --- a/ctdb/tests/complex/61_rogueip_takeip.sh +++ b/ctdb/tests/complex/61_rogueip_takeip.sh @@ -21,6 +21,20 @@ select_test_node_and_ips echo "Running test against node $test_node and IP $test_ip" +# This test puts an address on an interface and then needs to quickly +# configure that address and cause an IP takeover. However, an IPv6 +# address will be tentative for a while so "quickly" is not possible". +# When ctdb_control_takeover_ip() calls ctdb_sys_have_ip() it will +# decide that the address is not present. It then attempts a takeip, +# which can fail if the address is suddenly present because it is no +# longer tentative. +case "$test_ip" in +*:*) + echo "SKIPPING TEST: not supported for IPv6 addresses" + exit 0 + ;; +esac + get_test_ip_mask_and_iface echo "Deleting IP $test_ip from all nodes" -- 2.17.1 From 16720fb5730a56512f3fa0a305e0f97c47f6d9b9 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Wed, 15 Jan 2020 12:37:06 +1300 Subject: [PATCH 376/376] ndr: Unsigned overflow in ndr_pull_advance ndr_pull_advance was not checking for unsigned overflow, when checking the length. Credit to OSS-Fuzz BUG: https://bugzilla.samba.org/show_bug.cgi?id=14236 Signed-off-by: Gary Lockyer --- librpc/ndr/ndr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index d478eb69c01..2f72d255c3e 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -189,7 +189,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr) _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size) { ndr->offset += size; - if (ndr->offset > ndr->data_size) { + if (ndr->offset > ndr->data_size || ndr->offset < size) { return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "ndr_pull_advance by %u failed", size); -- 2.17.1