From a944a36b093ffcb7071290ad21a295018cf98232 Mon Sep 17 00:00:00 2001 From: Fabian Fritz Date: Tue, 7 Nov 2017 22:45:23 +0100 Subject: [PATCH 01/92] Fix #12961 --- lib/ldb/tests/ldb_mod_op_test.c | 8 ++++---- lib/replace/wscript | 6 +++++- source3/wscript_build | 1 + third_party/cmocka/cmocka.h | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c index 48ad20c7662..1b0baee3038 100644 --- a/lib/ldb/tests/ldb_mod_op_test.c +++ b/lib/ldb/tests/ldb_mod_op_test.c @@ -1914,22 +1914,22 @@ static void test_ldb_modify_during_search(void **state, bool add_index, static void test_ldb_modify_during_indexed_search(void **state) { - return test_ldb_modify_during_search(state, true, false); + test_ldb_modify_during_search(state, true, false); } static void test_ldb_modify_during_unindexed_search(void **state) { - return test_ldb_modify_during_search(state, false, false); + test_ldb_modify_during_search(state, false, false); } static void test_ldb_rename_during_indexed_search(void **state) { - return test_ldb_modify_during_search(state, true, true); + test_ldb_modify_during_search(state, true, true); } static void test_ldb_rename_during_unindexed_search(void **state) { - return test_ldb_modify_during_search(state, false, true); + test_ldb_modify_during_search(state, false, true); } /* diff --git a/lib/replace/wscript b/lib/replace/wscript index 7436a90c003..548ead737f5 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -81,6 +81,8 @@ def configure(conf): conf.CHECK_HEADERS('sys/atomic.h') conf.CHECK_HEADERS('libgen.h') + if conf.CHECK_CFLAGS('-Wno-format-zero-length'): + conf.define('HAVE_WNO_FORMAT_ZERO_LENGTH', '1') if conf.CHECK_CFLAGS('-Wno-format-truncation'): conf.define('HAVE_WNO_FORMAT_TRUNCATION', '1') @@ -734,7 +736,9 @@ def build(bld): private_library=True, deps='crypt dl nsl socket rt attr' + extra_libs) - replace_test_cflags="-Wno-format-zero-length" + replace_test_cflags = "" + if bld.CONFIG_SET('HAVE_WNO_FORMAT_ZERO_LENGTH'): + replace_test_cflags += "-Wno-format-zero-length" if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): replace_test_cflags += " -Wno-format-truncation" bld.SAMBA_SUBSYSTEM('replace-test', diff --git a/source3/wscript_build b/source3/wscript_build index dc7a51cc97a..037ceeab910 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -569,6 +569,7 @@ bld.SAMBA3_SUBSYSTEM('SMBCONF_PARAM', PARAM_UTIL ldap lber + krb5 LOADPARM_CTX samba3core param_local.h diff --git a/third_party/cmocka/cmocka.h b/third_party/cmocka/cmocka.h index 72d6ae21c90..440686f3b3f 100644 --- a/third_party/cmocka/cmocka.h +++ b/third_party/cmocka/cmocka.h @@ -56,7 +56,7 @@ int __stdcall IsDebuggerPresent(); /* If __WORDSIZE is not set, try to figure it out and default to 32 bit. */ #ifndef __WORDSIZE -# if defined(__x86_64__) && !defined(__ILP32__) +# if (defined(__x86_64__) || defined(_LP64)) && !defined(__ILP32__) # define __WORDSIZE 64 # else # define __WORDSIZE 32 From f3f119e4568f3cfc13140c6a449bece4fc58d9f9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 7 Sep 2017 17:26:58 +0200 Subject: [PATCH 02/92] selftest: split out failing owner related subtest from samba3.raw.acls.create_file|dir All the other subtests in samba3.raw.acls.create_file|dir pass with nfs4acl_xattr, it's just the subtest that tries to set the owner which fails with everything else then acl_xattr. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 11 +++---- source4/torture/raw/acls.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 15e6b1d5c70..258548ec858 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -22,14 +22,14 @@ ^samba3.raw.samba3hide.samba3hide\((nt4_dc|ad_dc)\) # This test fails against an smbd environment with NT ACLs enabled ^samba3.raw.samba3closeerr.samba3closeerr\(nt4_dc\) # This test fails against an smbd environment with NT ACLs enabled ^samba3.raw.acls nfs4acl_xattr-simple.INHERITFLAGS\(nt4_dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet. -^samba3.raw.acls nfs4acl_xattr-simple.create_file\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-simple.create_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.generic\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.inheritance\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.INHERITFLAGS\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.create_file\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.create_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.generic\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.inheritance\(nt4_dc\) @@ -106,7 +106,8 @@ ^samba4.raw.streams.*.perms ^samba4.raw.acls.INHERITFLAGS ^samba4.raw.acls.*.create_dir -^samba4.raw.acls.*.create_file +^samba4.raw.acls.*.create_owner_dir +^samba4.raw.acls.*.create_owner_file ^samba4.smb2.create.*.acldir ^samba4.smb2.create.*.impersonation ^samba4.smb2.acls.*.generic diff --git a/source4/torture/raw/acls.c b/source4/torture/raw/acls.c index dfeb13df560..9e3202b6fbd 100644 --- a/source4/torture/raw/acls.c +++ b/source4/torture/raw/acls.c @@ -342,6 +342,60 @@ static bool test_nttrans_create_ext(struct torture_context *tctx, status = delete_func(cli->tree, fname); CHECK_STATUS(status, NT_STATUS_OK); + done: + smbcli_close(cli->tree, fnum); + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + return ret; +} + +/* + test using nttrans create to create a file and directory with an initial acl + and owner. +*/ +static bool test_nttrans_create_ext_owner( + struct torture_context *tctx, + struct smbcli_state *cli, bool test_dir) +{ + NTSTATUS status; + union smb_open io; + const char *fname = BASEDIR "\\foo.txt"; + bool ret = true; + int fnum = -1; + struct security_ace ace; + struct security_descriptor *sd; + uint32_t attrib = + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM | + (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0); + NTSTATUS (*delete_func)(struct smbcli_tree *, const char *) = + test_dir ? smbcli_rmdir : smbcli_unlink; + + ZERO_STRUCT(ace); + + smbcli_deltree(cli->tree, BASEDIR); + + if (!torture_setup_dir(cli, BASEDIR)) + return false; + + io.generic.level = RAW_OPEN_NTTRANS_CREATE; + io.ntcreatex.in.root_fid.fnum = 0; + io.ntcreatex.in.flags = 0; + io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + io.ntcreatex.in.create_options = + test_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = fname; + io.ntcreatex.in.sec_desc = NULL; + io.ntcreatex.in.ea_list = NULL; + torture_comment(tctx, "creating with attributes, ACL and owner\n"); sd = security_descriptor_dacl_create(tctx, @@ -389,6 +443,22 @@ static bool test_nttrans_create_dir(struct torture_context *tctx, return test_nttrans_create_ext(tctx, cli, true); } +static bool test_nttrans_create_owner_file(struct torture_context *tctx, + struct smbcli_state *cli) +{ + torture_comment(tctx, "Testing nttrans create with sec_desc with owner on file\n"); + + return test_nttrans_create_ext_owner(tctx, cli, false); +} + +static bool test_nttrans_create_owner_dir(struct torture_context *tctx, + struct smbcli_state *cli) +{ + torture_comment(tctx, "Testing nttrans create with sec_desc with owner on directory\n"); + + return test_nttrans_create_ext_owner(tctx, cli, true); +} + #define CHECK_ACCESS_FLAGS(_fnum, flags) do { \ union smb_fileinfo _q; \ _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \ @@ -2466,6 +2536,8 @@ struct torture_suite *torture_raw_acls(TALLOC_CTX *mem_ctx) torture_suite_add_1smb_test(suite, "sd", test_sd); torture_suite_add_1smb_test(suite, "create_file", test_nttrans_create_file); torture_suite_add_1smb_test(suite, "create_dir", test_nttrans_create_dir); + torture_suite_add_1smb_test(suite, "create_owner_file", test_nttrans_create_owner_file); + torture_suite_add_1smb_test(suite, "create_owner_dir", test_nttrans_create_owner_dir); torture_suite_add_1smb_test(suite, "nulldacl", test_nttrans_create_null_dacl); torture_suite_add_1smb_test(suite, "creator", test_creator_sid); torture_suite_add_1smb_test(suite, "generic", test_generic_bits); From c373102f35a6fd6d474e419631e1718cdda4ce3a Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 28 Sep 2017 07:48:59 +0200 Subject: [PATCH 03/92] vfs_acl_common: directly pass default_acl_style This is in preperation of moving make_default_filesystem_acl() and making it globally accessible. No change in behaviour. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_acl_common.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 7958fd1ca72..5e63b580378 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -565,16 +565,16 @@ static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx, return NT_STATUS_OK; } -static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx, - struct acl_common_config *config, - const char *name, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **ppdesc) +static NTSTATUS make_default_filesystem_acl( + TALLOC_CTX *ctx, + enum default_acl_style acl_style, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **ppdesc) { NTSTATUS status; - switch (config->default_acl_style) { - + switch (acl_style) { case DEFAULT_ACL_POSIX: status = make_default_acl_posix(ctx, name, psbuf, ppdesc); break; @@ -584,7 +584,7 @@ static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx, break; default: - DBG_ERR("unknown acl style %d", config->default_acl_style); + DBG_ERR("unknown acl style %d", acl_style); status = NT_STATUS_INTERNAL_ERROR; break; } @@ -908,7 +908,7 @@ NTSTATUS get_nt_acl_common( status = make_default_filesystem_acl( mem_ctx, - config, + config->default_acl_style, smb_fname->base_name, psbuf, &psd); From 33c0b0df01e21c9e031bfe79986e1cfdb993ef6f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 28 Sep 2017 07:53:48 +0200 Subject: [PATCH 04/92] s3/smbd: make make_default_filesystem_acl public This will be used by another VFS module in a subsequent commit. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_acl_common.c | 216 +-------------------------------------- source3/modules/vfs_acl_common.h | 2 +- source3/smbd/posix_acls.c | 216 +++++++++++++++++++++++++++++++++++++++ source3/smbd/proto.h | 11 ++ 4 files changed, 232 insertions(+), 213 deletions(-) diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 5e63b580378..546e97b9b5d 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -41,15 +41,13 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd, SECINFO_DACL | \ SECINFO_SACL) -static const struct enum_list default_acl_style[] = { - {DEFAULT_ACL_POSIX, "posix"}, - {DEFAULT_ACL_WINDOWS, "windows"} -}; - bool init_acl_common_config(vfs_handle_struct *handle, const char *module_name) { struct acl_common_config *config = NULL; + const struct enum_list *default_acl_style_list = NULL; + + default_acl_style_list = get_default_acl_style_list(); config = talloc_zero(handle->conn, struct acl_common_config); if (config == NULL) { @@ -65,7 +63,7 @@ bool init_acl_common_config(vfs_handle_struct *handle, config->default_acl_style = lp_parm_enum(SNUM(handle->conn), module_name, "default acl style", - default_acl_style, + default_acl_style_list, DEFAULT_ACL_POSIX); SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, @@ -386,212 +384,6 @@ static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle, return NT_STATUS_OK; } -static NTSTATUS make_default_acl_posix(TALLOC_CTX *ctx, - const char *name, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **ppdesc) -{ - struct dom_sid owner_sid, group_sid; - size_t size = 0; - struct security_ace aces[4]; - uint32_t access_mask = 0; - mode_t mode = psbuf->st_ex_mode; - struct security_acl *new_dacl = NULL; - int idx = 0; - - DBG_DEBUG("file %s mode = 0%o\n",name, (int)mode); - - uid_to_sid(&owner_sid, psbuf->st_ex_uid); - gid_to_sid(&group_sid, psbuf->st_ex_gid); - - /* - We provide up to 4 ACEs - - Owner - - Group - - Everyone - - NT System - */ - - if (mode & S_IRUSR) { - if (mode & S_IWUSR) { - access_mask |= SEC_RIGHTS_FILE_ALL; - } else { - access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; - } - } - if (mode & S_IWUSR) { - access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE; - } - - init_sec_ace(&aces[idx], - &owner_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, - access_mask, - 0); - idx++; - - access_mask = 0; - if (mode & S_IRGRP) { - access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; - } - if (mode & S_IWGRP) { - /* note that delete is not granted - this matches posix behaviour */ - access_mask |= SEC_RIGHTS_FILE_WRITE; - } - if (access_mask) { - init_sec_ace(&aces[idx], - &group_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, - access_mask, - 0); - idx++; - } - - access_mask = 0; - if (mode & S_IROTH) { - access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; - } - if (mode & S_IWOTH) { - access_mask |= SEC_RIGHTS_FILE_WRITE; - } - if (access_mask) { - init_sec_ace(&aces[idx], - &global_sid_World, - SEC_ACE_TYPE_ACCESS_ALLOWED, - access_mask, - 0); - idx++; - } - - init_sec_ace(&aces[idx], - &global_sid_System, - SEC_ACE_TYPE_ACCESS_ALLOWED, - SEC_RIGHTS_FILE_ALL, - 0); - idx++; - - new_dacl = make_sec_acl(ctx, - NT4_ACL_REVISION, - idx, - aces); - - if (!new_dacl) { - return NT_STATUS_NO_MEMORY; - } - - *ppdesc = make_sec_desc(ctx, - SECURITY_DESCRIPTOR_REVISION_1, - SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT, - &owner_sid, - &group_sid, - NULL, - new_dacl, - &size); - if (!*ppdesc) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx, - const char *name, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **ppdesc) -{ - struct dom_sid owner_sid, group_sid; - size_t size = 0; - struct security_ace aces[4]; - uint32_t access_mask = 0; - mode_t mode = psbuf->st_ex_mode; - struct security_acl *new_dacl = NULL; - int idx = 0; - - DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode); - - uid_to_sid(&owner_sid, psbuf->st_ex_uid); - gid_to_sid(&group_sid, psbuf->st_ex_gid); - - /* - * We provide 2 ACEs: - * - Owner - * - NT System - */ - - if (mode & S_IRUSR) { - if (mode & S_IWUSR) { - access_mask |= SEC_RIGHTS_FILE_ALL; - } else { - access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; - } - } - if (mode & S_IWUSR) { - access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE; - } - - init_sec_ace(&aces[idx], - &owner_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, - access_mask, - 0); - idx++; - - init_sec_ace(&aces[idx], - &global_sid_System, - SEC_ACE_TYPE_ACCESS_ALLOWED, - SEC_RIGHTS_FILE_ALL, - 0); - idx++; - - new_dacl = make_sec_acl(ctx, - NT4_ACL_REVISION, - idx, - aces); - - if (!new_dacl) { - return NT_STATUS_NO_MEMORY; - } - - *ppdesc = make_sec_desc(ctx, - SECURITY_DESCRIPTOR_REVISION_1, - SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT, - &owner_sid, - &group_sid, - NULL, - new_dacl, - &size); - if (!*ppdesc) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -static NTSTATUS make_default_filesystem_acl( - TALLOC_CTX *ctx, - enum default_acl_style acl_style, - const char *name, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **ppdesc) -{ - NTSTATUS status; - - switch (acl_style) { - case DEFAULT_ACL_POSIX: - status = make_default_acl_posix(ctx, name, psbuf, ppdesc); - break; - - case DEFAULT_ACL_WINDOWS: - status = make_default_acl_windows(ctx, name, psbuf, ppdesc); - break; - - default: - DBG_ERR("unknown acl style %d", acl_style); - status = NT_STATUS_INTERNAL_ERROR; - break; - } - - return status; -} - /** * Validate an ACL blob * diff --git a/source3/modules/vfs_acl_common.h b/source3/modules/vfs_acl_common.h index c52fc5094c5..24803e0215e 100644 --- a/source3/modules/vfs_acl_common.h +++ b/source3/modules/vfs_acl_common.h @@ -22,7 +22,7 @@ #ifndef __VFS_ACL_COMMON_H__ #define __VFS_ACL_COMMON_H__ -enum default_acl_style {DEFAULT_ACL_POSIX, DEFAULT_ACL_WINDOWS}; +#include "smbd/proto.h" struct acl_common_config { bool ignore_system_acls; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7bd65390406..7337c5e8ecb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4857,3 +4857,219 @@ int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle, TALLOC_FREE(frame); return 0; } + +static NTSTATUS make_default_acl_posix(TALLOC_CTX *ctx, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **ppdesc) +{ + struct dom_sid owner_sid, group_sid; + size_t size = 0; + struct security_ace aces[4]; + uint32_t access_mask = 0; + mode_t mode = psbuf->st_ex_mode; + struct security_acl *new_dacl = NULL; + int idx = 0; + + DBG_DEBUG("file %s mode = 0%o\n",name, (int)mode); + + uid_to_sid(&owner_sid, psbuf->st_ex_uid); + gid_to_sid(&group_sid, psbuf->st_ex_gid); + + /* + We provide up to 4 ACEs + - Owner + - Group + - Everyone + - NT System + */ + + if (mode & S_IRUSR) { + if (mode & S_IWUSR) { + access_mask |= SEC_RIGHTS_FILE_ALL; + } else { + access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; + } + } + if (mode & S_IWUSR) { + access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE; + } + + init_sec_ace(&aces[idx], + &owner_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, + access_mask, + 0); + idx++; + + access_mask = 0; + if (mode & S_IRGRP) { + access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; + } + if (mode & S_IWGRP) { + /* note that delete is not granted - this matches posix behaviour */ + access_mask |= SEC_RIGHTS_FILE_WRITE; + } + if (access_mask) { + init_sec_ace(&aces[idx], + &group_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, + access_mask, + 0); + idx++; + } + + access_mask = 0; + if (mode & S_IROTH) { + access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; + } + if (mode & S_IWOTH) { + access_mask |= SEC_RIGHTS_FILE_WRITE; + } + if (access_mask) { + init_sec_ace(&aces[idx], + &global_sid_World, + SEC_ACE_TYPE_ACCESS_ALLOWED, + access_mask, + 0); + idx++; + } + + init_sec_ace(&aces[idx], + &global_sid_System, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_RIGHTS_FILE_ALL, + 0); + idx++; + + new_dacl = make_sec_acl(ctx, + NT4_ACL_REVISION, + idx, + aces); + + if (!new_dacl) { + return NT_STATUS_NO_MEMORY; + } + + *ppdesc = make_sec_desc(ctx, + SECURITY_DESCRIPTOR_REVISION_1, + SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT, + &owner_sid, + &group_sid, + NULL, + new_dacl, + &size); + if (!*ppdesc) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **ppdesc) +{ + struct dom_sid owner_sid, group_sid; + size_t size = 0; + struct security_ace aces[4]; + uint32_t access_mask = 0; + mode_t mode = psbuf->st_ex_mode; + struct security_acl *new_dacl = NULL; + int idx = 0; + + DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode); + + uid_to_sid(&owner_sid, psbuf->st_ex_uid); + gid_to_sid(&group_sid, psbuf->st_ex_gid); + + /* + * We provide 2 ACEs: + * - Owner + * - NT System + */ + + if (mode & S_IRUSR) { + if (mode & S_IWUSR) { + access_mask |= SEC_RIGHTS_FILE_ALL; + } else { + access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE; + } + } + if (mode & S_IWUSR) { + access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE; + } + + init_sec_ace(&aces[idx], + &owner_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, + access_mask, + 0); + idx++; + + init_sec_ace(&aces[idx], + &global_sid_System, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_RIGHTS_FILE_ALL, + 0); + idx++; + + new_dacl = make_sec_acl(ctx, + NT4_ACL_REVISION, + idx, + aces); + + if (!new_dacl) { + return NT_STATUS_NO_MEMORY; + } + + *ppdesc = make_sec_desc(ctx, + SECURITY_DESCRIPTOR_REVISION_1, + SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT, + &owner_sid, + &group_sid, + NULL, + new_dacl, + &size); + if (!*ppdesc) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +static const struct enum_list default_acl_style_list[] = { + {DEFAULT_ACL_POSIX, "posix"}, + {DEFAULT_ACL_WINDOWS, "windows"} +}; + +const struct enum_list *get_default_acl_style_list(void) +{ + return default_acl_style_list; +} + +NTSTATUS make_default_filesystem_acl( + TALLOC_CTX *ctx, + enum default_acl_style acl_style, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **ppdesc) +{ + NTSTATUS status; + + switch (acl_style) { + case DEFAULT_ACL_POSIX: + status = make_default_acl_posix(ctx, name, psbuf, ppdesc); + break; + + case DEFAULT_ACL_WINDOWS: + status = make_default_acl_windows(ctx, name, psbuf, ppdesc); + break; + + default: + DBG_ERR("unknown acl style %d", acl_style); + status = NT_STATUS_INTERNAL_ERROR; + break; + } + + return status; +} diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index a688341c64d..2e40711df41 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -806,6 +806,17 @@ int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle, char **blob_description, DATA_BLOB *blob); +enum default_acl_style {DEFAULT_ACL_POSIX, DEFAULT_ACL_WINDOWS}; + +const struct enum_list *get_default_acl_style_list(void); + +NTSTATUS make_default_filesystem_acl( + TALLOC_CTX *ctx, + enum default_acl_style acl_style, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **ppdesc); + /* The following definitions come from smbd/process.c */ void smbd_setup_sig_term_handler(struct smbd_server_connection *sconn); From dd3660631bace6d847955ebc9f410f0811dcd2d4 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 17 Oct 2017 15:18:52 +0200 Subject: [PATCH 05/92] s3/posix_acls: add default ACL style "everyone" This synthesizes an ACL with a single ACE with full permissions for everyone. Not used for now, this comes later. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- docs-xml/manpages/vfs_acl_tdb.8.xml | 6 +++- docs-xml/manpages/vfs_acl_xattr.8.xml | 6 +++- source3/smbd/posix_acls.c | 58 ++++++++++++++++++++++++++++++++++- source3/smbd/proto.h | 2 +- 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/docs-xml/manpages/vfs_acl_tdb.8.xml b/docs-xml/manpages/vfs_acl_tdb.8.xml index e36ccd91aa2..58cc0914c22 100644 --- a/docs-xml/manpages/vfs_acl_tdb.8.xml +++ b/docs-xml/manpages/vfs_acl_tdb.8.xml @@ -89,7 +89,7 @@ - acl_tdb:default acl style = [posix|windows] + acl_tdb:default acl style = [posix|windows|everyone] This parameter determines the type of ACL that is synthesized in @@ -108,6 +108,10 @@ owner and NT Authority\SYSTEM. + When set to everyone, an ACL is synthesized + giving full permissions to everyone (S-1-1-0). + + The default for this option is posix. diff --git a/docs-xml/manpages/vfs_acl_xattr.8.xml b/docs-xml/manpages/vfs_acl_xattr.8.xml index 43731f7ee92..f70e17c6ffe 100644 --- a/docs-xml/manpages/vfs_acl_xattr.8.xml +++ b/docs-xml/manpages/vfs_acl_xattr.8.xml @@ -93,7 +93,7 @@ - acl_xattr:default acl style = [posix|windows] + acl_xattr:default acl style = [posix|windows|everyone] This parameter determines the type of ACL that is synthesized in @@ -112,6 +112,10 @@ owner and NT Authority\SYSTEM. + When set to everyone, an ACL is synthesized + giving full permissions to everyone (S-1-1-0). + + The default for this option is posix. diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7337c5e8ecb..e4b16b9c3b4 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -5037,9 +5037,61 @@ static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx, return NT_STATUS_OK; } +static NTSTATUS make_default_acl_everyone(TALLOC_CTX *ctx, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **ppdesc) +{ + struct dom_sid owner_sid, group_sid; + size_t size = 0; + struct security_ace aces[1]; + mode_t mode = psbuf->st_ex_mode; + struct security_acl *new_dacl = NULL; + int idx = 0; + + DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode); + + uid_to_sid(&owner_sid, psbuf->st_ex_uid); + gid_to_sid(&group_sid, psbuf->st_ex_gid); + + /* + * We provide one ACEs: full access for everyone + */ + + init_sec_ace(&aces[idx], + &global_sid_World, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_RIGHTS_FILE_ALL, + 0); + idx++; + + new_dacl = make_sec_acl(ctx, + NT4_ACL_REVISION, + idx, + aces); + + if (!new_dacl) { + return NT_STATUS_NO_MEMORY; + } + + *ppdesc = make_sec_desc(ctx, + SECURITY_DESCRIPTOR_REVISION_1, + SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT, + &owner_sid, + &group_sid, + NULL, + new_dacl, + &size); + if (!*ppdesc) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + static const struct enum_list default_acl_style_list[] = { {DEFAULT_ACL_POSIX, "posix"}, - {DEFAULT_ACL_WINDOWS, "windows"} + {DEFAULT_ACL_WINDOWS, "windows"}, + {DEFAULT_ACL_EVERYONE, "everyone"}, }; const struct enum_list *get_default_acl_style_list(void) @@ -5065,6 +5117,10 @@ NTSTATUS make_default_filesystem_acl( status = make_default_acl_windows(ctx, name, psbuf, ppdesc); break; + case DEFAULT_ACL_EVERYONE: + status = make_default_acl_everyone(ctx, name, psbuf, ppdesc); + break; + default: DBG_ERR("unknown acl style %d", acl_style); status = NT_STATUS_INTERNAL_ERROR; diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 2e40711df41..c85a6cccd5b 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -806,7 +806,7 @@ int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle, char **blob_description, DATA_BLOB *blob); -enum default_acl_style {DEFAULT_ACL_POSIX, DEFAULT_ACL_WINDOWS}; +enum default_acl_style {DEFAULT_ACL_POSIX, DEFAULT_ACL_WINDOWS, DEFAULT_ACL_EVERYONE}; const struct enum_list *get_default_acl_style_list(void); From 914dfe6ed48440c66692604f5b3216009a7e8f07 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 16 Oct 2017 17:04:01 +0200 Subject: [PATCH 06/92] vfs_nfs4acl_xattr: remove a layer of indirection Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 951faa47849..909c624948c 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -331,18 +331,6 @@ static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, return ret == 0; } -/* nfs4_set_nt_acl() - * set the local file's acls obtaining it in NT form - * using the NFSv4 format conversion - */ -static NTSTATUS nfs4_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, - uint32_t security_info_sent, - const struct security_descriptor *psd) -{ - return smb_set_nt_acl_nfs4(handle, fsp, NULL, security_info_sent, psd, - nfs4acl_xattr_fset_smb4acl); -} - static struct SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx) { struct SMB4ACL_T *pacl = NULL; @@ -590,7 +578,8 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle, uint32_t security_info_sent, const struct security_descriptor *psd) { - return nfs4_set_nt_acl(handle, fsp, security_info_sent, psd); + return smb_set_nt_acl_nfs4(handle, fsp, NULL, security_info_sent, + psd, nfs4acl_xattr_fset_smb4acl); } /* From afe11cbdfa7b8546d3315046d8f43fffdb051036 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 15:50:07 +0200 Subject: [PATCH 07/92] vfs_nfs4acl_xattr: move interesting functions pointers to the top Move interesting functions to the top of the vfs_fn_pointers struct, no change in behaviour. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 909c624948c..7465ba8afbf 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -643,6 +643,10 @@ static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, fi /* VFS operations structure */ static struct vfs_fn_pointers nfs4acl_xattr_fns = { + .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl, + .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl, + .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl, + .sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file, .sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd, .sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file, @@ -650,9 +654,6 @@ static struct vfs_fn_pointers nfs4acl_xattr_fns = { .sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file, .sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd, .sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file, - .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl, - .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl, - .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl, }; NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *); From 20d3ae6a45f0ead6cefa5e47ca9b5552e4d470c0 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 12:29:47 +0200 Subject: [PATCH 08/92] librpc/idl: rename NFS4 ACL xattr name define No change in behaviour. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- librpc/idl/nfs4acl.idl | 2 +- source3/modules/vfs_nfs4acl_xattr.c | 8 ++++---- source4/ntvfs/posix/pvfs_acl_nfs4.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl index 5a3d0268f21..3d6894a604c 100644 --- a/librpc/idl/nfs4acl.idl +++ b/librpc/idl/nfs4acl.idl @@ -13,7 +13,7 @@ import "misc.idl", "security.idl"; ] interface nfs4acl_interface { - const char *NFS4ACL_XATTR_NAME = "system.nfs4acl"; + const char *NFS4ACL_NDR_XATTR_NAME = "system.nfs4acl"; const char *NFS4ACL_XATTR_OWNER_WHO = "OWNER@"; const char *NFS4ACL_XATTR_GROUP_WHO = "GROUP@"; diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 7465ba8afbf..fd47b86255e 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -135,7 +135,7 @@ static NTSTATUS nfs4_fget_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ct errno = ENOMEM; return NT_STATUS_NO_MEMORY; } - length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length); + length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length); blob.length = length; } while (length == -1 && errno == ERANGE); if (length == -1) { @@ -167,7 +167,7 @@ static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, return NT_STATUS_NO_MEMORY; } length = SMB_VFS_NEXT_GETXATTR(handle, smb_fname, - NFS4ACL_XATTR_NAME, blob.data, blob.length); + NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length); blob.length = length; } while (length == -1 && errno == ERANGE); if (length == -1) { @@ -281,7 +281,7 @@ static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle, errno = EINVAL; return false; } - ret = SMB_VFS_NEXT_SETXATTR(handle, smb_fname, NFS4ACL_XATTR_NAME, + ret = SMB_VFS_NEXT_SETXATTR(handle, smb_fname, NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length, 0); if (ret != 0) { DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno))); @@ -322,7 +322,7 @@ static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, if (fsp->fh->fd == -1) { DEBUG(0, ("Error: fsp->fh->fd == -1\n")); } - ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, + ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length, 0); if (ret != 0) { DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno))); diff --git a/source4/ntvfs/posix/pvfs_acl_nfs4.c b/source4/ntvfs/posix/pvfs_acl_nfs4.c index b07d2ba9b41..fc6c230817d 100644 --- a/source4/ntvfs/posix/pvfs_acl_nfs4.c +++ b/source4/ntvfs/posix/pvfs_acl_nfs4.c @@ -47,7 +47,7 @@ static NTSTATUS pvfs_acl_load_nfs4(struct pvfs_state *pvfs, struct pvfs_filename NT_STATUS_HAVE_NO_MEMORY(acl); status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, fd, - NFS4ACL_XATTR_NAME, + NFS4ACL_NDR_XATTR_NAME, acl, (void *) ndr_pull_nfs4acl); if (!NT_STATUS_IS_OK(status)) { talloc_free(acl); @@ -176,7 +176,7 @@ static NTSTATUS pvfs_acl_save_nfs4(struct pvfs_state *pvfs, struct pvfs_filename privs = root_privileges(); status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, - NFS4ACL_XATTR_NAME, + NFS4ACL_NDR_XATTR_NAME, &acl, (void *) ndr_push_nfs4acl); talloc_free(privs); From df99ac27106dededcf0a98a251e58c24b90bf6d1 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 2 Nov 2017 12:17:48 +0100 Subject: [PATCH 09/92] librpc/idl: rename NFS4 ACL xattr name The "system" xattr namespace is reserved for the kernel. Any attempt to use xattrs in that namesspace will fail with EOPNOTSUPP, regardless of priveleges. In autobuild we're using the xattr_tdb VFS module, so it works there. Using the "security" namespace instead makes this module generally usable with Linux filesystem xattrs as storage backend. Additionally prefix the xattr name with "_ndr". This is in preperation of later commits that add a ACL blob marshalling format based on XDR. To avoid xattr name collision, both format will use distinct xattr names by default. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- librpc/idl/nfs4acl.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl index 3d6894a604c..79e742c90e7 100644 --- a/librpc/idl/nfs4acl.idl +++ b/librpc/idl/nfs4acl.idl @@ -13,7 +13,7 @@ import "misc.idl", "security.idl"; ] interface nfs4acl_interface { - const char *NFS4ACL_NDR_XATTR_NAME = "system.nfs4acl"; + const char *NFS4ACL_NDR_XATTR_NAME = "security.nfs4acl_ndr"; const char *NFS4ACL_XATTR_OWNER_WHO = "OWNER@"; const char *NFS4ACL_XATTR_GROUP_WHO = "GROUP@"; From 5890c74f824630a317f202b5299f47f611732ccf Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 14:22:00 +0200 Subject: [PATCH 10/92] librpc/idl: add versions consts to nfs4acl.idl Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- librpc/idl/nfs4acl.idl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl index 79e742c90e7..1f0cfbf7a04 100644 --- a/librpc/idl/nfs4acl.idl +++ b/librpc/idl/nfs4acl.idl @@ -19,6 +19,10 @@ interface nfs4acl_interface const char *NFS4ACL_XATTR_GROUP_WHO = "GROUP@"; const char *NFS4ACL_XATTR_EVERYONE_WHO = "EVERYONE@"; + const uint8 ACL4_XATTR_VERSION_40 = 0x00; + const uint8 ACL4_XATTR_VERSION_41 = 0x01; + const uint8 ACL4_XATTR_VERSION_DEFAULT = ACL4_XATTR_VERSION_40; + /* these structures use the same bit values and other constants as in security.idl */ typedef [flag(NDR_BIG_ENDIAN)] struct { From 31a8fbff8d2e5bd27b44a0eb14608f8f43ce2a6b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 16:34:44 +0200 Subject: [PATCH 11/92] vfs_nfs4acl_xattr: add a runtime configuration object No change in behaviour, all option defaults are set to the original behaviour. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/nfs4acl_xattr.h | 32 ++++++++++++++ source3/modules/vfs_nfs4acl_xattr.c | 88 +++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 source3/modules/nfs4acl_xattr.h diff --git a/source3/modules/nfs4acl_xattr.h b/source3/modules/nfs4acl_xattr.h new file mode 100644 index 00000000000..3eeb4703bc8 --- /dev/null +++ b/source3/modules/nfs4acl_xattr.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) Ralph Boehme 2017 + * + * 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 . + * + */ + +#ifndef __NFS4ACL_XATTR_H__ +#define __NFS4ACL_XATTR_H__ + +enum nfs4acl_encoding {NFS4ACL_ENCODING_NDR, NFS4ACL_ENCODING_XDR}; + +struct nfs4acl_config { + unsigned nfs_version; + enum nfs4acl_encoding encoding; + char *xattr_name; + struct smbacl4_vfs_params nfs4_params; + enum default_acl_style default_acl_style; +}; + +#endif /* __NFS4ACL_XATTR_H__ */ diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index fd47b86255e..312123a265f 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -9,6 +9,7 @@ * Copyright (C) Tim Potter, 1999-2000 * Copyright (C) Alexander Bokovoy, 2002 * Copyright (C) Andrew Bartlett, 2002,2012 + * Copyright (C) Ralph Boehme 2017 * * 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 @@ -30,10 +31,16 @@ #include "smbd/smbd.h" #include "nfs4_acls.h" #include "librpc/gen_ndr/ndr_nfs4acl.h" +#include "nfs4acl_xattr.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +static const struct enum_list nfs4acl_encoding[] = { + {NFS4ACL_ENCODING_NDR, "ndr"}, + {NFS4ACL_ENCODING_XDR, "xdr"}, +}; + static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) { enum ndr_err_code ndr_err; @@ -582,6 +589,86 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle, psd, nfs4acl_xattr_fset_smb4acl); } +static int nfs4acl_connect(struct vfs_handle_struct *handle, + const char *service, + const char *user) +{ + struct nfs4acl_config *config = NULL; + const struct enum_list *default_acl_style_list = NULL; + const char *default_xattr_name = NULL; + int enumval; + unsigned nfs_version; + int ret; + + default_acl_style_list = get_default_acl_style_list(); + + config = talloc_zero(handle->conn, struct nfs4acl_config); + if (config == NULL) { + DBG_ERR("talloc_zero() failed\n"); + return -1; + } + + ret = SMB_VFS_NEXT_CONNECT(handle, service, user); + if (ret < 0) { + TALLOC_FREE(config); + return ret; + } + + ret = smbacl4_get_vfs_params(handle->conn, &config->nfs4_params); + if (ret < 0) { + TALLOC_FREE(config); + return ret; + } + + enumval = lp_parm_enum(SNUM(handle->conn), + "nfs4acl_xattr", + "encoding", + nfs4acl_encoding, + NFS4ACL_ENCODING_NDR); + if (enumval == -1) { + DBG_ERR("Invalid \"nfs4acl_xattr:encoding\" parameter\n"); + return -1; + } + config->encoding = (enum nfs4acl_encoding)enumval; + + switch (config->encoding) { + case NFS4ACL_ENCODING_NDR: + default: + default_xattr_name = NFS4ACL_NDR_XATTR_NAME; + break; + } + + nfs_version = (unsigned)lp_parm_int(SNUM(handle->conn), + "nfs4acl_xattr", + "version", + 40); + switch (nfs_version) { + case 40: + config->nfs_version = ACL4_XATTR_VERSION_40; + break; + default: + config->nfs_version = ACL4_XATTR_VERSION_DEFAULT; + break; + } + + config->default_acl_style = lp_parm_enum(SNUM(handle->conn), + "nfs4acl_xattr", + "default acl style", + default_acl_style_list, + DEFAULT_ACL_EVERYONE); + + config->xattr_name = lp_parm_talloc_string(config, + SNUM(handle->conn), + "nfs4acl_xattr", + "xattr_name", + default_xattr_name); + + SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct nfs4acl_config, + return -1); + + return 0; +} + /* As long as Samba does not support an exiplicit method for a module to define conflicting vfs methods, we should override all conflicting @@ -643,6 +730,7 @@ static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, fi /* VFS operations structure */ static struct vfs_fn_pointers nfs4acl_xattr_fns = { + .connect_fn = nfs4acl_connect, .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl, .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl, .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl, From 7f62b16a12980b203e44a9e95d8e96d12f479453 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 16 Oct 2017 18:05:51 +0200 Subject: [PATCH 12/92] vfs_nfs4acl_xattr: modernize ACL inheritance This changes the way ACL inheritance is achieved in this module. Previously the module recursed to the next parent directory until the share root was reached or a directory with an ACL xattr. If the share root didn't contain an ACL xattr either a default ACL would be used. This commit removed this recursive scanning and replaces it with the same mechanism used by vfs_acl_xattr: by setting "inherit acls = yes" just let smbd do the heavy lefting and inheritance. For any file without ACL xattr we still synthesize a default ACL, leveraging the existing default ACL function used by vfs_acl_xattr. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 2 - source3/modules/vfs_nfs4acl_xattr.c | 277 ++++++++---------------------------- 2 files changed, 57 insertions(+), 222 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 258548ec858..030520f7e58 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -26,13 +26,11 @@ ^samba3.raw.acls nfs4acl_xattr-simple.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.generic\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-simple.inheritance\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.INHERITFLAGS\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.create_owner_file\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.generic\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.inheritance\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_owner\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_group\(nt4_dc\) ^samba3.base.delete.deltest16a diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 312123a265f..fc30f66f1d4 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -260,43 +260,6 @@ static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, return true; } -static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle, - const struct smb_filename *smb_fname, - struct SMB4ACL_T *smbacl) -{ - TALLOC_CTX *frame = talloc_stackframe(); - struct nfs4acl *nfs4acl; - int ret; - bool denymissingspecial; - DATA_BLOB blob; - - denymissingspecial = lp_parm_bool(handle->conn->params->service, - "nfs4acl_xattr", - "denymissingspecial", false); - - if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl, - denymissingspecial)) { - DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n")); - TALLOC_FREE(frame); - return false; - } - - blob = nfs4acl_acl2blob(frame, nfs4acl); - if (!blob.data) { - DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n")); - TALLOC_FREE(frame); - errno = EINVAL; - return false; - } - ret = SMB_VFS_NEXT_SETXATTR(handle, smb_fname, NFS4ACL_NDR_XATTR_NAME, - blob.data, blob.length, 0); - if (ret != 0) { - DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno))); - } - TALLOC_FREE(frame); - return ret == 0; -} - /* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */ static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, files_struct *fsp, @@ -338,194 +301,47 @@ static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, return ret == 0; } -static struct SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx) -{ - struct SMB4ACL_T *pacl = NULL; - struct SMB4ACE_T *pace; - SMB_ACE4PROP_T ace = { - .flags = SMB_ACE4_ID_SPECIAL, - .who = { - .id = SMB_ACE4_WHO_EVERYONE, - }, - .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, - .aceFlags = 0, - .aceMask = SMB_ACE4_ALL_MASKS, - }; - - DEBUG(10, ("Building default full access acl\n")); - - pacl = smb_create_smb4acl(mem_ctx); - if (pacl == NULL) { - DEBUG(0, ("talloc failed\n")); - errno = ENOMEM; - return NULL; - } - - pace = smb_add_ace4(pacl, &ace); - if (pace == NULL) { - DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(pacl); - errno = ENOMEM; - return NULL; - } - - return pacl; -} - -/* - * Because there is no good way to guarantee that a new xattr will be - * created on file creation there might be no acl xattr on a file when - * trying to read the acl. In this case the acl xattr will get - * constructed at that time from the parent acl. - * If the parent ACL doesn't have an xattr either the call will - * recurse to the next parent directory until the share root is - * reached. If the share root doesn't contain an ACL xattr either a - * default ACL will be used. - * Also a default ACL will be set if a non inheriting ACL is encountered. - * - * Basic algorithm: - * read acl xattr blob - * if acl xattr blob doesn't exist - * stat current directory to know if it's a file or directory - * read acl xattr blob from parent dir - * acl xattr blob to smb nfs4 acl - * calculate inherited smb nfs4 acl - * without inheritance use default smb nfs4 acl - * smb nfs4 acl to acl xattr blob - * set acl xattr blob - * return smb nfs4 acl - * else - * acl xattr blob to smb nfs4 acl - * - * Todo: Really use mem_ctx after fixing interface of nfs4_acls - */ -static struct SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle, - const struct smb_filename *smb_fname_in, - TALLOC_CTX *mem_ctx) +static NTSTATUS nfs4acl_xattr_default_sd( + struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + TALLOC_CTX *mem_ctx, + struct security_descriptor **sd) { - char *parent_dir = NULL; - struct SMB4ACL_T *pparentacl = NULL; - struct SMB4ACL_T *pchildacl = NULL; - struct SMB4ACE_T *pace; - SMB_ACE4PROP_T ace; - bool isdir; - struct smb_filename *smb_fname = NULL; - struct smb_filename *smb_fname_parent = NULL; - NTSTATUS status; + struct nfs4acl_config *config = NULL; + enum default_acl_style default_acl_style; + mode_t required_mode; + SMB_STRUCT_STAT sbuf = smb_fname->st; int ret; - TALLOC_CTX *frame = talloc_stackframe(); - DEBUG(10, ("nfs4acls_inheritacl invoked for %s\n", - smb_fname_in->base_name)); - smb_fname = cp_smb_filename_nostream(frame, smb_fname_in); - if (smb_fname == NULL) { - TALLOC_FREE(frame); - errno = ENOMEM; - return NULL; - } + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); - ret = SMB_VFS_STAT(handle->conn, smb_fname); - if (ret == -1) { - DEBUG(0,("nfs4acls_inheritacl: failed to stat " - "directory %s. Error was %s\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(frame); - return NULL; - } - isdir = S_ISDIR(smb_fname->st.st_ex_mode); + default_acl_style = config->default_acl_style; - if (!parent_dirname(talloc_tos(), - smb_fname->base_name, - &parent_dir, - NULL)) { - TALLOC_FREE(frame); - errno = ENOMEM; - return NULL; - } - - smb_fname_parent = synthetic_smb_fname(talloc_tos(), - parent_dir, - NULL, - NULL, - 0); - if (smb_fname_parent == NULL) { - TALLOC_FREE(frame); - errno = ENOMEM; - return NULL; - } - - status = nfs4_get_nfs4_acl(handle, frame, smb_fname_parent, - &pparentacl); - if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) - && strncmp(parent_dir, ".", 2) != 0) { - pparentacl = nfs4acls_inheritacl(handle, - smb_fname_parent, - frame); - } - else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { - pparentacl = nfs4acls_defaultacl(frame); - - } - else if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(frame); - return NULL; - } - - pchildacl = smb_create_smb4acl(mem_ctx); - if (pchildacl == NULL) { - DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(frame); - errno = ENOMEM; - return NULL; - } - - for (pace = smb_first_ace4(pparentacl); pace != NULL; - pace = smb_next_ace4(pace)) { - struct SMB4ACE_T *pchildace; - ace = *smb_get_ace4(pace); - if ((isdir && !(ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) || - (!isdir && !(ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE))) { - DEBUG(10, ("non inheriting ace type: %d, iflags: %x, " - "flags: %x, mask: %x, who: %d\n", - ace.aceType, ace.flags, ace.aceFlags, - ace.aceMask, ace.who.id)); - continue; - } - DEBUG(10, ("inheriting ace type: %d, iflags: %x, " - "flags: %x, mask: %x, who: %d\n", - ace.aceType, ace.flags, ace.aceFlags, - ace.aceMask, ace.who.id)); - ace.aceFlags |= SMB_ACE4_INHERITED_ACE; - if (ace.aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) { - ace.aceFlags &= ~SMB_ACE4_INHERIT_ONLY_ACE; - } - if (ace.aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE) { - ace.aceFlags &= ~SMB_ACE4_FILE_INHERIT_ACE; - ace.aceFlags &= ~SMB_ACE4_DIRECTORY_INHERIT_ACE; - ace.aceFlags &= ~SMB_ACE4_NO_PROPAGATE_INHERIT_ACE; - } - pchildace = smb_add_ace4(pchildacl, &ace); - if (pchildace == NULL) { - DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(frame); - errno = ENOMEM; - return NULL; + if (!VALID_STAT(sbuf)) { + ret = vfs_stat_smb_basename(handle->conn, + smb_fname, + &sbuf); + if (ret != 0) { + return map_nt_error_from_unix(errno); } } - /* Set a default ACL if we didn't inherit anything. */ - if (smb_first_ace4(pchildacl) == NULL) { - TALLOC_FREE(pchildacl); - pchildacl = nfs4acls_defaultacl(mem_ctx); + if (S_ISDIR(sbuf.st_ex_mode)) { + required_mode = 0777; + } else { + required_mode = 0666; + } + if ((sbuf.st_ex_mode & required_mode) != required_mode) { + default_acl_style = DEFAULT_ACL_POSIX; } - /* store the returned ACL to get it directly in the - future and avoid dynamic inheritance behavior. */ - nfs4acl_xattr_set_smb4acl(handle, smb_fname, pchildacl); - - TALLOC_FREE(frame); - return pchildacl; + return make_default_filesystem_acl(mem_ctx, + default_acl_style, + smb_fname->base_name, + &sbuf, + sd); } static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, @@ -540,10 +356,11 @@ static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { - pacl = nfs4acls_inheritacl(handle, fsp->fsp_name, - frame); + TALLOC_FREE(frame); + return nfs4acl_xattr_default_sd( + handle, fsp->fsp_name, mem_ctx, ppdesc); } - else if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } @@ -566,9 +383,11 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle, status = nfs4_get_nfs4_acl(handle, frame, smb_fname, &pacl); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { - pacl = nfs4acls_inheritacl(handle, smb_fname, frame); + TALLOC_FREE(frame); + return nfs4acl_xattr_default_sd( + handle, smb_fname, mem_ctx, ppdesc); } - else if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } @@ -666,6 +485,24 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle, SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct nfs4acl_config, return -1); + /* + * Ensure we have the parameters correct if we're using this module. + */ + DBG_NOTICE("Setting 'inherit acls = true', " + "'dos filemode = true', " + "'force unknown acl user = true', " + "'create mask = 0666', " + "'directory mask = 0777' and " + "'store dos attributes = yes' " + "for service [%s]\n", service); + + lp_do_parameter(SNUM(handle->conn), "inherit acls", "true"); + lp_do_parameter(SNUM(handle->conn), "dos filemode", "true"); + lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true"); + lp_do_parameter(SNUM(handle->conn), "create mask", "0666"); + lp_do_parameter(SNUM(handle->conn), "directory mask", "0777"); + lp_do_parameter(SNUM(handle->conn), "store dos attributes", "yes"); + return 0; } From 383312abdc2afc6849b2dcc613c02e073806e101 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 21:53:40 +0200 Subject: [PATCH 13/92] vfs_nfs4acl_xattr: code polish README.Coding adjustments, DEBUG macro modernisation, variable name sanitizing. No change in behaviour. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 90 ++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index fc30f66f1d4..700a15b8151 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -44,8 +44,9 @@ static const struct enum_list nfs4acl_encoding[] = { static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) { enum ndr_err_code ndr_err; - struct nfs4acl *acl = talloc(mem_ctx, struct nfs4acl); - if (!acl) { + struct nfs4acl *acl = talloc_zero(mem_ctx, struct nfs4acl); + + if (acl == NULL) { errno = ENOMEM; return NULL; } @@ -54,8 +55,7 @@ static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) (ndr_pull_flags_fn_t)ndr_pull_nfs4acl); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(0, ("ndr_pull_acl_t failed: %s\n", - ndr_errstr(ndr_err))); + DBG_ERR("ndr_pull_acl_t failed: %s\n", ndr_errstr(ndr_err)); TALLOC_FREE(acl); return NULL; } @@ -66,12 +66,12 @@ static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) { enum ndr_err_code ndr_err; DATA_BLOB blob; + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl, (ndr_push_flags_fn_t)ndr_push_nfs4acl); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(0, ("ndr_push_acl_t failed: %s\n", - ndr_errstr(ndr_err))); + DBG_ERR("ndr_push_acl_t failed: %s\n", ndr_errstr(ndr_err)); return data_blob_null; } return blob; @@ -79,26 +79,33 @@ static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, - struct SMB4ACL_T **ppacl) + struct SMB4ACL_T **_smb4acl) { - int i; struct nfs4acl *nfs4acl = NULL; - struct SMB4ACL_T *pacl = NULL; + struct SMB4ACL_T *smb4acl = NULL; TALLOC_CTX *frame = talloc_stackframe(); + int i; + nfs4acl = nfs4acl_blob2acl(blob, frame); + if (nfs4acl == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_INTERNAL_ERROR; + } - /* create SMB4ACL data */ - if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) { + smb4acl = smb_create_smb4acl(mem_ctx); + if (smb4acl == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } - for(i=0; ia_count; i++) { + + for (i = 0; i < nfs4acl->a_count; i++) { SMB_ACE4PROP_T aceprop; aceprop.aceType = (uint32_t) nfs4acl->ace[i].e_type; aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags; aceprop.aceMask = (uint32_t) nfs4acl->ace[i].e_mask; aceprop.who.id = (uint32_t) nfs4acl->ace[i].e_id; + if (!strcmp(nfs4acl->ace[i].e_who, NFS4ACL_XATTR_OWNER_WHO)) { aceprop.flags = SMB_ACE4_ID_SPECIAL; @@ -114,13 +121,13 @@ static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx, } else { aceprop.flags = 0; } - if(smb_add_ace4(pacl, &aceprop) == NULL) { + if (smb_add_ace4(smb4acl, &aceprop) == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } } - *ppacl = pacl; + *_smb4acl = smb4acl; TALLOC_FREE(frame); return NT_STATUS_OK; } @@ -188,17 +195,16 @@ static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, struct SMB4ACL_T *smbacl, - struct nfs4acl **pnfs4acl, + struct nfs4acl **_nfs4acl, bool denymissingspecial) { - struct nfs4acl *nfs4acl; - struct SMB4ACE_T *smbace; + struct nfs4acl *nfs4acl = NULL; + struct SMB4ACE_T *smbace = NULL; bool have_special_id = false; int i; - /* allocate the field of NFS4 aces */ nfs4acl = talloc_zero(mem_ctx, struct nfs4acl); - if(nfs4acl == NULL) { + if (nfs4acl == NULL) { errno = ENOMEM; return false; } @@ -207,16 +213,16 @@ static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace, nfs4acl->a_count); - if(nfs4acl->ace == NULL) { + if (nfs4acl->ace == NULL) { TALLOC_FREE(nfs4acl); errno = ENOMEM; return false; } - /* handle all aces */ - for(smbace = smb_first_ace4(smbacl), i = 0; - smbace!=NULL; - smbace = smb_next_ace4(smbace), i++) { + for (smbace = smb_first_ace4(smbacl), i = 0; + smbace != NULL; + smbace = smb_next_ace4(smbace), i++) + { SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace); nfs4acl->ace[i].e_type = aceprop->aceType; @@ -238,8 +244,8 @@ static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, NFS4ACL_XATTR_GROUP_WHO; break; default: - DEBUG(8, ("unsupported special_id %d\n", \ - aceprop->who.special_id)); + DBG_DEBUG("unsupported special_id %d\n", + aceprop->who.special_id); continue; /* don't add it !!! */ } have_special_id = true; @@ -256,7 +262,7 @@ static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, SMB_ASSERT(i == nfs4acl->a_count); - *pnfs4acl = nfs4acl; + *_nfs4acl = nfs4acl; return true; } @@ -284,7 +290,7 @@ static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, blob = nfs4acl_acl2blob(frame, nfs4acl); if (!blob.data) { - DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n")); + DBG_ERR("Failed to convert ACL to linear blob for xattr\n"); TALLOC_FREE(frame); errno = EINVAL; return false; @@ -295,7 +301,7 @@ static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length, 0); if (ret != 0) { - DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno))); + DBG_ERR("can't store acl in xattr: %s\n", strerror(errno)); } TALLOC_FREE(frame); return ret == 0; @@ -348,17 +354,17 @@ static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32_t security_info, TALLOC_CTX *mem_ctx, - struct security_descriptor **ppdesc) + struct security_descriptor **sd) { - struct SMB4ACL_T *pacl; - NTSTATUS status; + struct SMB4ACL_T *smb4acl = NULL; TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; - status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl); + status = nfs4_fget_nfs4_acl(handle, frame, fsp, &smb4acl); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { TALLOC_FREE(frame); return nfs4acl_xattr_default_sd( - handle, fsp->fsp_name, mem_ctx, ppdesc); + handle, fsp->fsp_name, mem_ctx, sd); } if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); @@ -366,7 +372,7 @@ static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, } status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx, - ppdesc, pacl); + sd, smb4acl); TALLOC_FREE(frame); return status; } @@ -375,17 +381,17 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, uint32_t security_info, TALLOC_CTX *mem_ctx, - struct security_descriptor **ppdesc) + struct security_descriptor **sd) { - struct SMB4ACL_T *pacl; - NTSTATUS status; + struct SMB4ACL_T *smb4acl = NULL; TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; - status = nfs4_get_nfs4_acl(handle, frame, smb_fname, &pacl); + status = nfs4_get_nfs4_acl(handle, frame, smb_fname, &smb4acl); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { TALLOC_FREE(frame); return nfs4acl_xattr_default_sd( - handle, smb_fname, mem_ctx, ppdesc); + handle, smb_fname, mem_ctx, sd); } if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); @@ -393,8 +399,8 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle, } status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, NULL, - security_info, mem_ctx, ppdesc, - pacl); + security_info, mem_ctx, sd, + smb4acl); TALLOC_FREE(frame); return status; } From 2fb6b0c2dafd5f59218eb11f0cc8e27b5a0432bc Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 16:35:52 +0200 Subject: [PATCH 14/92] vfs_nfs4acl_xattr: refactoring Refactor the code in preperation of factoring out ACL blob to smb4acl and vice versa mapping functions. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 273 +++++++++++++++++++++++------------- 1 file changed, 176 insertions(+), 97 deletions(-) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 700a15b8151..2bc546150e0 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -41,6 +41,64 @@ static const struct enum_list nfs4acl_encoding[] = { {NFS4ACL_ENCODING_XDR, "xdr"}, }; +static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle, + files_struct *fsp, + const struct smb_filename *smb_fname_in, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + struct nfs4acl_config *config = NULL; + const struct smb_filename *smb_fname = NULL; + size_t allocsize = 256; + ssize_t length; + bool ok; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + *blob = data_blob_null; + + if (fsp == NULL && smb_fname_in == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + smb_fname = smb_fname_in; + if (smb_fname == NULL) { + smb_fname = fsp->fsp_name; + } + if (smb_fname == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + + do { + allocsize *= 4; + ok = data_blob_realloc(mem_ctx, blob, allocsize); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } + + if (fsp != NULL && fsp->fh->fd != -1) { + length = SMB_VFS_NEXT_FGETXATTR(handle, + fsp, + config->xattr_name, + blob->data, + blob->length); + } else { + length = SMB_VFS_NEXT_GETXATTR(handle, + smb_fname, + config->xattr_name, + blob->data, + blob->length); + } + } while (length == -1 && errno == ERANGE && allocsize <= 65536); + + if (length == -1) { + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; +} + static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) { enum ndr_err_code ndr_err; @@ -77,15 +135,21 @@ static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) return blob; } -static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, - struct SMB4ACL_T **_smb4acl) +static NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + struct SMB4ACL_T **_smb4acl) { struct nfs4acl *nfs4acl = NULL; struct SMB4ACL_T *smb4acl = NULL; TALLOC_CTX *frame = talloc_stackframe(); + struct nfs4acl_config *config = NULL; int i; + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + nfs4acl = nfs4acl_blob2acl(blob, frame); if (nfs4acl == NULL) { TALLOC_FREE(frame); @@ -132,67 +196,6 @@ static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */ -static NTSTATUS nfs4_fget_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, - files_struct *fsp, struct SMB4ACL_T **ppacl) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - ssize_t length; - TALLOC_CTX *frame = talloc_stackframe(); - - do { - blob.length += 1000; - blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length); - if (!blob.data) { - TALLOC_FREE(frame); - errno = ENOMEM; - return NT_STATUS_NO_MEMORY; - } - length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length); - blob.length = length; - } while (length == -1 && errno == ERANGE); - if (length == -1) { - TALLOC_FREE(frame); - return map_nt_error_from_unix(errno); - } - status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl); - TALLOC_FREE(frame); - return status; -} - -/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */ -static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, - TALLOC_CTX *mem_ctx, - const struct smb_filename *smb_fname, - struct SMB4ACL_T **ppacl) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - ssize_t length; - TALLOC_CTX *frame = talloc_stackframe(); - - do { - blob.length += 1000; - blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length); - if (!blob.data) { - TALLOC_FREE(frame); - errno = ENOMEM; - return NT_STATUS_NO_MEMORY; - } - length = SMB_VFS_NEXT_GETXATTR(handle, smb_fname, - NFS4ACL_NDR_XATTR_NAME, blob.data, blob.length); - blob.length = length; - } while (length == -1 && errno == ERANGE); - if (length == -1) { - TALLOC_FREE(frame); - return map_nt_error_from_unix(errno); - } - status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl); - TALLOC_FREE(frame); - return status; -} - static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, struct SMB4ACL_T *smbacl, struct nfs4acl **_nfs4acl, @@ -266,45 +269,36 @@ static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, return true; } -/* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */ -static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle, - files_struct *fsp, - struct SMB4ACL_T *smbacl) +static NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smb4acl, + DATA_BLOB *_blob) { - TALLOC_CTX *frame = talloc_stackframe(); - struct nfs4acl *nfs4acl; - int ret; - bool denymissingspecial; + struct nfs4acl *nfs4acl = NULL; DATA_BLOB blob; + bool denymissingspecial; + bool ok; - denymissingspecial = lp_parm_bool(fsp->conn->params->service, + denymissingspecial = lp_parm_bool(SNUM(handle->conn), "nfs4acl_xattr", "denymissingspecial", false); - if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl, - denymissingspecial)) { - DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n")); - TALLOC_FREE(frame); - return false; + ok = nfs4acl_smb4acl2nfs4acl(talloc_tos(), smb4acl, &nfs4acl, + denymissingspecial); + if (!ok) { + DBG_ERR("Failed to convert smb ACL to nfs4 ACL.\n"); + return NT_STATUS_INTERNAL_ERROR; } - blob = nfs4acl_acl2blob(frame, nfs4acl); - if (!blob.data) { + blob = nfs4acl_acl2blob(mem_ctx, nfs4acl); + TALLOC_FREE(nfs4acl); + if (blob.data == NULL) { DBG_ERR("Failed to convert ACL to linear blob for xattr\n"); - TALLOC_FREE(frame); - errno = EINVAL; - return false; - } - if (fsp->fh->fd == -1) { - DEBUG(0, ("Error: fsp->fh->fd == -1\n")); - } - ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_NDR_XATTR_NAME, - blob.data, blob.length, 0); - if (ret != 0) { - DBG_ERR("can't store acl in xattr: %s\n", strerror(errno)); + return NT_STATUS_INTERNAL_ERROR; } - TALLOC_FREE(frame); - return ret == 0; + + *_blob = blob; + return NT_STATUS_OK; } static NTSTATUS nfs4acl_xattr_default_sd( @@ -350,6 +344,30 @@ static NTSTATUS nfs4acl_xattr_default_sd( sd); } +static NTSTATUS nfs4acl_blob_to_smb4(struct vfs_handle_struct *handle, + DATA_BLOB *blob, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T **smb4acl) +{ + struct nfs4acl_config *config = NULL; + NTSTATUS status; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + switch (config->encoding) { + case NFS4ACL_ENCODING_NDR: + status = nfs4acl_ndr_blob_to_smb4(handle, mem_ctx, blob, smb4acl); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } + + return status; +} + static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32_t security_info, @@ -358,9 +376,10 @@ static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, { struct SMB4ACL_T *smb4acl = NULL; TALLOC_CTX *frame = talloc_stackframe(); + DATA_BLOB blob; NTSTATUS status; - status = nfs4_fget_nfs4_acl(handle, frame, fsp, &smb4acl); + status = nfs4acl_get_blob(handle, fsp, NULL, frame, &blob); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { TALLOC_FREE(frame); return nfs4acl_xattr_default_sd( @@ -371,6 +390,12 @@ static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle, return status; } + status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx, sd, smb4acl); TALLOC_FREE(frame); @@ -385,9 +410,10 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle, { struct SMB4ACL_T *smb4acl = NULL; TALLOC_CTX *frame = talloc_stackframe(); + DATA_BLOB blob; NTSTATUS status; - status = nfs4_get_nfs4_acl(handle, frame, smb_fname, &smb4acl); + status = nfs4acl_get_blob(handle, NULL, smb_fname, frame, &blob); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { TALLOC_FREE(frame); return nfs4acl_xattr_default_sd( @@ -398,6 +424,12 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle, return status; } + status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, NULL, security_info, mem_ctx, sd, smb4acl); @@ -405,13 +437,60 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle, return status; } +static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle, + files_struct *fsp, + struct SMB4ACL_T *smb4acl) +{ + struct nfs4acl_config *config = NULL; + DATA_BLOB blob; + NTSTATUS status; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return false); + + switch (config->encoding) { + case NFS4ACL_ENCODING_NDR: + status = nfs4acl_smb4acl_to_ndr_blob(handle, talloc_tos(), + smb4acl, &blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, config->xattr_name, + blob.data, blob.length, 0); + data_blob_free(&blob); + if (ret != 0) { + DBG_ERR("can't store acl in xattr: %s\n", strerror(errno)); + return false; + } + + return true; +} + static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd) { - return smb_set_nt_acl_nfs4(handle, fsp, NULL, security_info_sent, - psd, nfs4acl_xattr_fset_smb4acl); + struct nfs4acl_config *config = NULL; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + return smb_set_nt_acl_nfs4(handle, + fsp, + &config->nfs4_params, + security_info_sent, + psd, + nfs4acl_smb4acl_set_fn); } static int nfs4acl_connect(struct vfs_handle_struct *handle, From d4d7e38bf6fcde3ef1fde6c5f83c4f5e983818e1 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 16:38:51 +0200 Subject: [PATCH 15/92] vfs_nfs4acl_xattr: fsp->fh->fd can legally be -1 We only open the underlying file if the open access mode contains FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 2 -- source3/modules/vfs_nfs4acl_xattr.c | 10 ++++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 030520f7e58..f3c605ba582 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -25,12 +25,10 @@ ^samba3.raw.acls nfs4acl_xattr-simple.create_owner_file\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple.nulldacl\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-simple.generic\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.INHERITFLAGS\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.create_owner_file\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.nulldacl\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.generic\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_owner\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_group\(nt4_dc\) ^samba3.base.delete.deltest16a diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 2bc546150e0..b3b5e497061 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -463,8 +463,14 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle, return false; } - ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, config->xattr_name, - blob.data, blob.length, 0); + if (fsp->fh->fd != -1) { + ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, config->xattr_name, + blob.data, blob.length, 0); + } else { + ret = SMB_VFS_NEXT_SETXATTR(handle, fsp->fsp_name, + config->xattr_name, + blob.data, blob.length, 0); + } data_blob_free(&blob); if (ret != 0) { DBG_ERR("can't store acl in xattr: %s\n", strerror(errno)); From f5b2c66e44e9178ceef36630c9daabbc68ad4a57 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 17 Oct 2017 12:02:53 +0200 Subject: [PATCH 16/92] vfs_nfs4acl_xattr: move the meat of the implementation to a seperate file This is in preperation of modularizing the storage backend. Currently we store the NFS4 ACL as an IDL/NDR encoded blob in a xattr. Later commits will add a different backend storing the NFS4 ACL as an XDR encoded blob in a xattr. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/nfs4acl_xattr_ndr.c | 241 ++++++++++++++++++++++++++++++++++++ source3/modules/nfs4acl_xattr_ndr.h | 42 +++++++ source3/modules/vfs_nfs4acl_xattr.c | 203 +----------------------------- source3/modules/wscript_build | 2 +- 4 files changed, 285 insertions(+), 203 deletions(-) create mode 100644 source3/modules/nfs4acl_xattr_ndr.c create mode 100644 source3/modules/nfs4acl_xattr_ndr.h diff --git a/source3/modules/nfs4acl_xattr_ndr.c b/source3/modules/nfs4acl_xattr_ndr.c new file mode 100644 index 00000000000..af100184c5f --- /dev/null +++ b/source3/modules/nfs4acl_xattr_ndr.c @@ -0,0 +1,241 @@ +/* + * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa. + * + * Copyright (C) Jiri Sasek, 2007 + * based on the foobar.c module which is copyrighted by Volker Lendecke + * based on pvfs_acl_nfs4.c Copyright (C) Andrew Tridgell 2006 + * + * based on vfs_fake_acls: + * Copyright (C) Tim Potter, 1999-2000 + * Copyright (C) Alexander Bokovoy, 2002 + * Copyright (C) Andrew Bartlett, 2002,2012 + * Copyright (C) Ralph Boehme 2017 + * + * 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/filesys.h" +#include "smbd/smbd.h" +#include "nfs4_acls.h" +#include "librpc/gen_ndr/ndr_nfs4acl.h" +#include "nfs4acl_xattr.h" +#include "nfs4acl_xattr_ndr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + enum ndr_err_code ndr_err; + struct nfs4acl *acl = talloc_zero(mem_ctx, struct nfs4acl); + + if (acl == NULL) { + errno = ENOMEM; + return NULL; + } + + ndr_err = ndr_pull_struct_blob(blob, acl, acl, + (ndr_pull_flags_fn_t)ndr_pull_nfs4acl); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DBG_ERR("ndr_pull_acl_t failed: %s\n", ndr_errstr(ndr_err)); + TALLOC_FREE(acl); + return NULL; + } + return acl; +} + +static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) +{ + enum ndr_err_code ndr_err; + DATA_BLOB blob; + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl, + (ndr_push_flags_fn_t)ndr_push_nfs4acl); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DBG_ERR("ndr_push_acl_t failed: %s\n", ndr_errstr(ndr_err)); + return data_blob_null; + } + return blob; +} + +NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + struct SMB4ACL_T **_smb4acl) +{ + struct nfs4acl *nfs4acl = NULL; + struct SMB4ACL_T *smb4acl = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + struct nfs4acl_config *config = NULL; + int i; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + nfs4acl = nfs4acl_blob2acl(blob, frame); + if (nfs4acl == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_INTERNAL_ERROR; + } + + smb4acl = smb_create_smb4acl(mem_ctx); + if (smb4acl == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < nfs4acl->a_count; i++) { + SMB_ACE4PROP_T aceprop; + + aceprop.aceType = (uint32_t) nfs4acl->ace[i].e_type; + aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags; + aceprop.aceMask = (uint32_t) nfs4acl->ace[i].e_mask; + aceprop.who.id = (uint32_t) nfs4acl->ace[i].e_id; + + if (!strcmp(nfs4acl->ace[i].e_who, + NFS4ACL_XATTR_OWNER_WHO)) { + aceprop.flags = SMB_ACE4_ID_SPECIAL; + aceprop.who.special_id = SMB_ACE4_WHO_OWNER; + } else if (!strcmp(nfs4acl->ace[i].e_who, + NFS4ACL_XATTR_GROUP_WHO)) { + aceprop.flags = SMB_ACE4_ID_SPECIAL; + aceprop.who.special_id = SMB_ACE4_WHO_GROUP; + } else if (!strcmp(nfs4acl->ace[i].e_who, + NFS4ACL_XATTR_EVERYONE_WHO)) { + aceprop.flags = SMB_ACE4_ID_SPECIAL; + aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE; + } else { + aceprop.flags = 0; + } + + if (smb_add_ace4(smb4acl, &aceprop) == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + } + + *_smb4acl = smb4acl; + TALLOC_FREE(frame); + return NT_STATUS_OK; +} + +static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smbacl, + struct nfs4acl **_nfs4acl, + bool denymissingspecial) +{ + struct nfs4acl *nfs4acl = NULL; + struct SMB4ACE_T *smbace = NULL; + bool have_special_id = false; + int i; + + nfs4acl = talloc_zero(mem_ctx, struct nfs4acl); + if (nfs4acl == NULL) { + errno = ENOMEM; + return false; + } + + nfs4acl->a_count = smb_get_naces(smbacl); + + nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace, + nfs4acl->a_count); + if (nfs4acl->ace == NULL) { + TALLOC_FREE(nfs4acl); + errno = ENOMEM; + return false; + } + + for (smbace = smb_first_ace4(smbacl), i = 0; + smbace != NULL; + smbace = smb_next_ace4(smbace), i++) + { + SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace); + + nfs4acl->ace[i].e_type = aceprop->aceType; + nfs4acl->ace[i].e_flags = aceprop->aceFlags; + nfs4acl->ace[i].e_mask = aceprop->aceMask; + nfs4acl->ace[i].e_id = aceprop->who.id; + if(aceprop->flags & SMB_ACE4_ID_SPECIAL) { + switch(aceprop->who.special_id) { + case SMB_ACE4_WHO_EVERYONE: + nfs4acl->ace[i].e_who = + NFS4ACL_XATTR_EVERYONE_WHO; + break; + case SMB_ACE4_WHO_OWNER: + nfs4acl->ace[i].e_who = + NFS4ACL_XATTR_OWNER_WHO; + break; + case SMB_ACE4_WHO_GROUP: + nfs4acl->ace[i].e_who = + NFS4ACL_XATTR_GROUP_WHO; + break; + default: + DBG_DEBUG("unsupported special_id %d\n", + aceprop->who.special_id); + continue; /* don't add it !!! */ + } + have_special_id = true; + } else { + nfs4acl->ace[i].e_who = ""; + } + } + + if (!have_special_id && denymissingspecial) { + TALLOC_FREE(nfs4acl); + errno = EACCES; + return false; + } + + SMB_ASSERT(i == nfs4acl->a_count); + + *_nfs4acl = nfs4acl; + return true; +} + +NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smb4acl, + DATA_BLOB *_blob) +{ + struct nfs4acl *nfs4acl = NULL; + DATA_BLOB blob; + bool denymissingspecial; + bool ok; + + denymissingspecial = lp_parm_bool(SNUM(handle->conn), + "nfs4acl_xattr", + "denymissingspecial", false); + + ok = nfs4acl_smb4acl2nfs4acl(talloc_tos(), smb4acl, &nfs4acl, + denymissingspecial); + if (!ok) { + DBG_ERR("Failed to convert smb ACL to nfs4 ACL.\n"); + return NT_STATUS_INTERNAL_ERROR; + } + + blob = nfs4acl_acl2blob(mem_ctx, nfs4acl); + TALLOC_FREE(nfs4acl); + if (blob.data == NULL) { + DBG_ERR("Failed to convert ACL to linear blob for xattr\n"); + return NT_STATUS_INTERNAL_ERROR; + } + + *_blob = blob; + return NT_STATUS_OK; +} diff --git a/source3/modules/nfs4acl_xattr_ndr.h b/source3/modules/nfs4acl_xattr_ndr.h new file mode 100644 index 00000000000..7db4ce734f5 --- /dev/null +++ b/source3/modules/nfs4acl_xattr_ndr.h @@ -0,0 +1,42 @@ +/* + * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa. + * + * Copyright (C) Jiri Sasek, 2007 + * based on the foobar.c module which is copyrighted by Volker Lendecke + * based on pvfs_acl_nfs4.c Copyright (C) Andrew Tridgell 2006 + * + * based on vfs_fake_acls: + * Copyright (C) Tim Potter, 1999-2000 + * Copyright (C) Alexander Bokovoy, 2002 + * Copyright (C) Andrew Bartlett, 2002,2012 + * Copyright (C) Ralph Boehme 2017 + * + * 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 . + * + */ + +#ifndef __NFS4ACL_XATTR_NDR_H__ +#define __NFS4ACL_XATTR_NDR_H__ + +NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + struct SMB4ACL_T **_smb4acl); + +NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smbacl, + DATA_BLOB *blob); + +#endif /* _VFS_NFS4ACL_XATTR_NDR_H */ diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index b3b5e497061..b8ff28b75c0 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -32,6 +32,7 @@ #include "nfs4_acls.h" #include "librpc/gen_ndr/ndr_nfs4acl.h" #include "nfs4acl_xattr.h" +#include "nfs4acl_xattr_ndr.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -99,208 +100,6 @@ static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle, return NT_STATUS_OK; } -static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) -{ - enum ndr_err_code ndr_err; - struct nfs4acl *acl = talloc_zero(mem_ctx, struct nfs4acl); - - if (acl == NULL) { - errno = ENOMEM; - return NULL; - } - - ndr_err = ndr_pull_struct_blob(blob, acl, acl, - (ndr_pull_flags_fn_t)ndr_pull_nfs4acl); - - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DBG_ERR("ndr_pull_acl_t failed: %s\n", ndr_errstr(ndr_err)); - TALLOC_FREE(acl); - return NULL; - } - return acl; -} - -static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) -{ - enum ndr_err_code ndr_err; - DATA_BLOB blob; - - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl, - (ndr_push_flags_fn_t)ndr_push_nfs4acl); - - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DBG_ERR("ndr_push_acl_t failed: %s\n", ndr_errstr(ndr_err)); - return data_blob_null; - } - return blob; -} - -static NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, - TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, - struct SMB4ACL_T **_smb4acl) -{ - struct nfs4acl *nfs4acl = NULL; - struct SMB4ACL_T *smb4acl = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - struct nfs4acl_config *config = NULL; - int i; - - SMB_VFS_HANDLE_GET_DATA(handle, config, - struct nfs4acl_config, - return NT_STATUS_INTERNAL_ERROR); - - nfs4acl = nfs4acl_blob2acl(blob, frame); - if (nfs4acl == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_INTERNAL_ERROR; - } - - smb4acl = smb_create_smb4acl(mem_ctx); - if (smb4acl == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < nfs4acl->a_count; i++) { - SMB_ACE4PROP_T aceprop; - - aceprop.aceType = (uint32_t) nfs4acl->ace[i].e_type; - aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags; - aceprop.aceMask = (uint32_t) nfs4acl->ace[i].e_mask; - aceprop.who.id = (uint32_t) nfs4acl->ace[i].e_id; - - if (!strcmp(nfs4acl->ace[i].e_who, - NFS4ACL_XATTR_OWNER_WHO)) { - aceprop.flags = SMB_ACE4_ID_SPECIAL; - aceprop.who.special_id = SMB_ACE4_WHO_OWNER; - } else if (!strcmp(nfs4acl->ace[i].e_who, - NFS4ACL_XATTR_GROUP_WHO)) { - aceprop.flags = SMB_ACE4_ID_SPECIAL; - aceprop.who.special_id = SMB_ACE4_WHO_GROUP; - } else if (!strcmp(nfs4acl->ace[i].e_who, - NFS4ACL_XATTR_EVERYONE_WHO)) { - aceprop.flags = SMB_ACE4_ID_SPECIAL; - aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE; - } else { - aceprop.flags = 0; - } - if (smb_add_ace4(smb4acl, &aceprop) == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; - } - } - - *_smb4acl = smb4acl; - TALLOC_FREE(frame); - return NT_STATUS_OK; -} - -static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, - struct SMB4ACL_T *smbacl, - struct nfs4acl **_nfs4acl, - bool denymissingspecial) -{ - struct nfs4acl *nfs4acl = NULL; - struct SMB4ACE_T *smbace = NULL; - bool have_special_id = false; - int i; - - nfs4acl = talloc_zero(mem_ctx, struct nfs4acl); - if (nfs4acl == NULL) { - errno = ENOMEM; - return false; - } - - nfs4acl->a_count = smb_get_naces(smbacl); - - nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace, - nfs4acl->a_count); - if (nfs4acl->ace == NULL) { - TALLOC_FREE(nfs4acl); - errno = ENOMEM; - return false; - } - - for (smbace = smb_first_ace4(smbacl), i = 0; - smbace != NULL; - smbace = smb_next_ace4(smbace), i++) - { - SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace); - - nfs4acl->ace[i].e_type = aceprop->aceType; - nfs4acl->ace[i].e_flags = aceprop->aceFlags; - nfs4acl->ace[i].e_mask = aceprop->aceMask; - nfs4acl->ace[i].e_id = aceprop->who.id; - if(aceprop->flags & SMB_ACE4_ID_SPECIAL) { - switch(aceprop->who.special_id) { - case SMB_ACE4_WHO_EVERYONE: - nfs4acl->ace[i].e_who = - NFS4ACL_XATTR_EVERYONE_WHO; - break; - case SMB_ACE4_WHO_OWNER: - nfs4acl->ace[i].e_who = - NFS4ACL_XATTR_OWNER_WHO; - break; - case SMB_ACE4_WHO_GROUP: - nfs4acl->ace[i].e_who = - NFS4ACL_XATTR_GROUP_WHO; - break; - default: - DBG_DEBUG("unsupported special_id %d\n", - aceprop->who.special_id); - continue; /* don't add it !!! */ - } - have_special_id = true; - } else { - nfs4acl->ace[i].e_who = ""; - } - } - - if (!have_special_id && denymissingspecial) { - TALLOC_FREE(nfs4acl); - errno = EACCES; - return false; - } - - SMB_ASSERT(i == nfs4acl->a_count); - - *_nfs4acl = nfs4acl; - return true; -} - -static NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle, - TALLOC_CTX *mem_ctx, - struct SMB4ACL_T *smb4acl, - DATA_BLOB *_blob) -{ - struct nfs4acl *nfs4acl = NULL; - DATA_BLOB blob; - bool denymissingspecial; - bool ok; - - denymissingspecial = lp_parm_bool(SNUM(handle->conn), - "nfs4acl_xattr", - "denymissingspecial", false); - - ok = nfs4acl_smb4acl2nfs4acl(talloc_tos(), smb4acl, &nfs4acl, - denymissingspecial); - if (!ok) { - DBG_ERR("Failed to convert smb ACL to nfs4 ACL.\n"); - return NT_STATUS_INTERNAL_ERROR; - } - - blob = nfs4acl_acl2blob(mem_ctx, nfs4acl); - TALLOC_FREE(nfs4acl); - if (blob.data == NULL) { - DBG_ERR("Failed to convert ACL to linear blob for xattr\n"); - return NT_STATUS_INTERNAL_ERROR; - } - - *_blob = blob; - return NT_STATUS_OK; -} - static NTSTATUS nfs4acl_xattr_default_sd( struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index b9f2b9da25c..6943d474826 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -219,7 +219,7 @@ bld.SAMBA3_MODULE('vfs_zfsacl', bld.SAMBA3_MODULE('vfs_nfs4acl_xattr', subsystem='vfs', - source='vfs_nfs4acl_xattr.c', + source='vfs_nfs4acl_xattr.c nfs4acl_xattr_ndr.c', deps='NFS4_ACLS sunacl NDR_NFS4ACL', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_nfs4acl_xattr'), From e2950327ffbe66ec03020f6afb0bccf4c6a377ac Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 22:44:38 +0200 Subject: [PATCH 17/92] librpc/idl: add NFS 4.1 ACL flags Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- librpc/idl/nfs4acl.idl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl index 1f0cfbf7a04..f836436dc6e 100644 --- a/librpc/idl/nfs4acl.idl +++ b/librpc/idl/nfs4acl.idl @@ -23,6 +23,11 @@ interface nfs4acl_interface const uint8 ACL4_XATTR_VERSION_41 = 0x01; const uint8 ACL4_XATTR_VERSION_DEFAULT = ACL4_XATTR_VERSION_40; + const uint8 ACL4_AUTO_INHERIT = 0x01; + const uint8 ACL4_PROTECTED = 0x02; + const uint8 ACL4_DEFAULTED = 0x04; + const uint8 ACL4_WRITE_THROUGH = 0x40; + /* these structures use the same bit values and other constants as in security.idl */ typedef [flag(NDR_BIG_ENDIAN)] struct { From 0697f794b6851a2cd8a81b0cfd2daab9ebec7223 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 15:40:52 +0200 Subject: [PATCH 18/92] vfs_nfs4acl_xattr: add support for NFS 4.1 ACL flags in the NDR backend Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/nfs4acl_xattr_ndr.c | 63 +++++++++++++++++++++++++++++++++++-- source3/modules/vfs_nfs4acl_xattr.c | 3 ++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/source3/modules/nfs4acl_xattr_ndr.c b/source3/modules/nfs4acl_xattr_ndr.c index af100184c5f..ffa3e69cbb5 100644 --- a/source3/modules/nfs4acl_xattr_ndr.c +++ b/source3/modules/nfs4acl_xattr_ndr.c @@ -73,6 +73,23 @@ static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) return blob; } +static uint16_t nfs4acl_to_smb4acl_flags(uint8_t nfs4acl_flags) +{ + uint16_t smb4acl_flags = SEC_DESC_SELF_RELATIVE; + + if (nfs4acl_flags & ACL4_AUTO_INHERIT) { + smb4acl_flags |= SEC_DESC_DACL_AUTO_INHERITED; + } + if (nfs4acl_flags & ACL4_PROTECTED) { + smb4acl_flags |= SEC_DESC_DACL_PROTECTED; + } + if (nfs4acl_flags & ACL4_DEFAULTED) { + smb4acl_flags |= SEC_DESC_DACL_DEFAULTED; + } + + return smb4acl_flags; +} + NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, @@ -100,6 +117,15 @@ NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, return NT_STATUS_NO_MEMORY; } + if (config->nfs_version > ACL4_XATTR_VERSION_40 && + nfs4acl->a_version > ACL4_XATTR_VERSION_40) + { + uint16_t smb4acl_flags; + + smb4acl_flags = nfs4acl_to_smb4acl_flags(nfs4acl->a_flags); + smbacl4_set_controlflags(smb4acl, smb4acl_flags); + } + for (i = 0; i < nfs4acl->a_count; i++) { SMB_ACE4PROP_T aceprop; @@ -135,16 +161,39 @@ NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle, return NT_STATUS_OK; } -static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, +static uint8_t smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags) +{ + uint8_t flags = 0; + + if (smb4acl_flags & SEC_DESC_DACL_AUTO_INHERITED) { + flags |= ACL4_AUTO_INHERIT; + } + if (smb4acl_flags & SEC_DESC_DACL_PROTECTED) { + flags |= ACL4_PROTECTED; + } + if (smb4acl_flags & SEC_DESC_DACL_DEFAULTED) { + flags |= ACL4_DEFAULTED; + } + + return flags; +} + +static bool nfs4acl_smb4acl2nfs4acl(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, struct SMB4ACL_T *smbacl, struct nfs4acl **_nfs4acl, bool denymissingspecial) { + struct nfs4acl_config *config = NULL; struct nfs4acl *nfs4acl = NULL; struct SMB4ACE_T *smbace = NULL; bool have_special_id = false; int i; + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return false); + nfs4acl = talloc_zero(mem_ctx, struct nfs4acl); if (nfs4acl == NULL) { errno = ENOMEM; @@ -161,6 +210,16 @@ static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx, return false; } + nfs4acl->a_version = config->nfs_version; + if (nfs4acl->a_version > ACL4_XATTR_VERSION_40) { + uint16_t smb4acl_flags; + uint8_t flags; + + smb4acl_flags = smbacl4_get_controlflags(smbacl); + flags = smb4acl_to_nfs4acl_flags(smb4acl_flags); + nfs4acl->a_flags = flags; + } + for (smbace = smb_first_ace4(smbacl), i = 0; smbace != NULL; smbace = smb_next_ace4(smbace), i++) @@ -222,7 +281,7 @@ NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle, "nfs4acl_xattr", "denymissingspecial", false); - ok = nfs4acl_smb4acl2nfs4acl(talloc_tos(), smb4acl, &nfs4acl, + ok = nfs4acl_smb4acl2nfs4acl(handle, talloc_tos(), smb4acl, &nfs4acl, denymissingspecial); if (!ok) { DBG_ERR("Failed to convert smb ACL to nfs4 ACL.\n"); diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index b8ff28b75c0..e0266d23657 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -355,6 +355,9 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle, case 40: config->nfs_version = ACL4_XATTR_VERSION_40; break; + case 41: + config->nfs_version = ACL4_XATTR_VERSION_41; + break; default: config->nfs_version = ACL4_XATTR_VERSION_DEFAULT; break; From 12f4263b285ca85601206905d22f06d9650e6f5d Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 13:35:49 +0200 Subject: [PATCH 19/92] selftest: add explicit default NFS4 acl version This is the current default, just make it explicit. A subsequent commit will bump the default to 4.1. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 20 ++++++++++---------- selftest/target/Samba3.pm | 6 ++++-- source3/selftest/tests.py | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index f3c605ba582..19c0b6973bd 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -21,16 +21,16 @@ ^samba3.blackbox.smbclient_machine_auth.plain \(nt4_dc:local\)# the NT4 DC does not currently set up a self-join ^samba3.raw.samba3hide.samba3hide\((nt4_dc|ad_dc)\) # This test fails against an smbd environment with NT ACLs enabled ^samba3.raw.samba3closeerr.samba3closeerr\(nt4_dc\) # This test fails against an smbd environment with NT ACLs enabled -^samba3.raw.acls nfs4acl_xattr-simple.INHERITFLAGS\(nt4_dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet. -^samba3.raw.acls nfs4acl_xattr-simple.create_owner_file\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-simple.create_owner_dir\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-simple.nulldacl\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.INHERITFLAGS\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.create_owner_file\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.create_owner_dir\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.nulldacl\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_owner\(nt4_dc\) -^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_group\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple-40.INHERITFLAGS\(nt4_dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet. +^samba3.raw.acls nfs4acl_xattr-simple-40.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple-40.create_owner_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple-40.nulldacl\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special-40.INHERITFLAGS\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special-40.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special-40.create_owner_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special-40.nulldacl\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special-40.inherit_creator_owner\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-special-40.inherit_creator_group\(nt4_dc\) ^samba3.base.delete.deltest16a ^samba3.base.delete.deltest17a ^samba3.unix.whoami anonymous connection.whoami\(ad_dc\) # We need to resolve if we should be including SID_NT_WORLD and SID_NT_NETWORK in this token diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index f4d033d0c7a..87191841589 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1862,16 +1862,18 @@ sub provision($$$$$$$$$) [lp] copy = print1 -[nfs4acl_simple] +[nfs4acl_simple_40] path = $shrdir comment = smb username is [%U] nfs4:mode = simple + nfs4acl_xattr:version = 40 vfs objects = nfs4acl_xattr xattr_tdb -[nfs4acl_special] +[nfs4acl_special_40] path = $shrdir comment = smb username is [%U] nfs4:mode = special + nfs4acl_xattr:version = 40 vfs objects = nfs4acl_xattr xattr_tdb [xcopy_share] diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index c1e08d56731..bee4315845a 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -461,8 +461,8 @@ def plansmbtorture4testsuite(name, env, options, description=''): plantestsuite(t, "ad_member_idmap_ad", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_ad.sh"), '$DOMAIN', '$DC_SERVER', '$DC_PASSWORD']) elif t == "raw.acls": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') - plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple') - plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_special -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-special') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-40') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_special_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-special-40') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD') elif t == "smb2.ioctl": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/fs_specific -U$USERNAME%$PASSWORD', 'fs_specific') From 60c8090631d46124f9c8ae750e4a5053b43ac988 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 2 Nov 2017 12:45:48 +0100 Subject: [PATCH 20/92] nfs4acls: update default NFS4 ACL version to 4.1 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- librpc/idl/nfs4acl.idl | 2 +- source3/modules/vfs_nfs4acl_xattr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl index f836436dc6e..10a60ed1caf 100644 --- a/librpc/idl/nfs4acl.idl +++ b/librpc/idl/nfs4acl.idl @@ -21,7 +21,7 @@ interface nfs4acl_interface const uint8 ACL4_XATTR_VERSION_40 = 0x00; const uint8 ACL4_XATTR_VERSION_41 = 0x01; - const uint8 ACL4_XATTR_VERSION_DEFAULT = ACL4_XATTR_VERSION_40; + const uint8 ACL4_XATTR_VERSION_DEFAULT = ACL4_XATTR_VERSION_41; const uint8 ACL4_AUTO_INHERIT = 0x01; const uint8 ACL4_PROTECTED = 0x02; diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index e0266d23657..31b85aea13f 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -350,7 +350,7 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle, nfs_version = (unsigned)lp_parm_int(SNUM(handle->conn), "nfs4acl_xattr", "version", - 40); + 41); switch (nfs_version) { case 40: config->nfs_version = ACL4_XATTR_VERSION_40; From 08a6ae44196ff747c57e75a42a946978e89a2cd9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 14:05:19 +0200 Subject: [PATCH 21/92] selftest: test vfs_nfs4acl_xattr with NFS 4.1 ACLs Only tests with "nfs4:mode = simple" as mode special is supposed to be broken anyway and simple is recommended. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 3 +++ selftest/target/Samba3.pm | 6 ++++++ source3/selftest/tests.py | 1 + 3 files changed, 10 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index 19c0b6973bd..36c1697f9a4 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -25,6 +25,9 @@ ^samba3.raw.acls nfs4acl_xattr-simple-40.create_owner_file\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple-40.create_owner_dir\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-simple-40.nulldacl\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple-41.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple-41.create_owner_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-simple-41.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special-40.INHERITFLAGS\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special-40.create_owner_file\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special-40.create_owner_dir\(nt4_dc\) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 87191841589..57db4fa1c60 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1876,6 +1876,12 @@ sub provision($$$$$$$$$) nfs4acl_xattr:version = 40 vfs objects = nfs4acl_xattr xattr_tdb +[nfs4acl_simple_41] + path = $shrdir + comment = smb username is [%U] + nfs4:mode = simple + vfs objects = nfs4acl_xattr xattr_tdb + [xcopy_share] path = $shrdir comment = smb username is [%U] diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index bee4315845a..4dc7f753fb5 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -463,6 +463,7 @@ def plansmbtorture4testsuite(name, env, options, description=''): plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-40') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_special_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-special-40') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-41') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD') elif t == "smb2.ioctl": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/fs_specific -U$USERNAME%$PASSWORD', 'fs_specific') From b4072961c691dbe7434b077147a89d927a299570 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 14:15:12 +0200 Subject: [PATCH 22/92] vfs_nfs4acl_xattr: do xattr ops as root This ensures we can always fetch the ACL xattr blob when we wanted, unrestricted of filesystem permissions or Linux xattr security namespace restrictions. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 31b85aea13f..2515d0c7987 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -72,12 +72,15 @@ static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle, } do { + int saved_errno = 0; + allocsize *= 4; ok = data_blob_realloc(mem_ctx, blob, allocsize); if (!ok) { return NT_STATUS_NO_MEMORY; } + become_root(); if (fsp != NULL && fsp->fh->fd != -1) { length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, @@ -91,6 +94,13 @@ static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle, blob->data, blob->length); } + if (length == -1) { + saved_errno = errno; + } + unbecome_root(); + if (saved_errno != 0) { + errno = saved_errno; + } } while (length == -1 && errno == ERANGE && allocsize <= 65536); if (length == -1) { @@ -243,6 +253,7 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle, struct nfs4acl_config *config = NULL; DATA_BLOB blob; NTSTATUS status; + int saved_errno = 0; int ret; SMB_VFS_HANDLE_GET_DATA(handle, config, @@ -262,6 +273,7 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle, return false; } + become_root(); if (fsp->fh->fd != -1) { ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, config->xattr_name, blob.data, blob.length, 0); @@ -270,7 +282,14 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle, config->xattr_name, blob.data, blob.length, 0); } + if (ret != 0) { + saved_errno = errno; + } + unbecome_root(); data_blob_free(&blob); + if (saved_errno != 0) { + errno = saved_errno; + } if (ret != 0) { DBG_ERR("can't store acl in xattr: %s\n", strerror(errno)); return false; From 0fdbe624fd708f372b9a1fe4176e04ebb1b040d6 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 18 Oct 2017 20:45:05 +0200 Subject: [PATCH 23/92] vfs_nfs4acl_xattr: add POSIX mode check and reset The vfs_nfs4acl_xattr VFS module is supposed to work the same as vfs_acl_xattr|tdb with "ignore system acls" set to true. That is, filesystem permissions should never restrict access and the actual access checks are done by smbd in userspace. To better cope with POSIX mode changes via other protocols (eg NFS) or local filesystem access, add the following tweaks: o validate ACL blob: if POSIX mode is not 0777/0666 discard the ACL blob from the xattr and synthesize a default ACL based on the POSIX mode o when setting an ACL, check and reset POSIX mode to 0777/0666 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 118 ++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 6 deletions(-) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 2515d0c7987..9c0c87f6331 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -29,6 +29,7 @@ #include "includes.h" #include "system/filesys.h" #include "smbd/smbd.h" +#include "libcli/security/security_token.h" #include "nfs4_acls.h" #include "librpc/gen_ndr/ndr_nfs4acl.h" #include "nfs4acl_xattr.h" @@ -42,6 +43,55 @@ static const struct enum_list nfs4acl_encoding[] = { {NFS4ACL_ENCODING_XDR, "xdr"}, }; +/* + * Check if someone changed the POSIX mode, for files we expect 0666, for + * directories 0777. Discard the ACL blob if the mode is different. + */ +static bool nfs4acl_validate_blob(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) +{ + struct nfs4acl_config *config = NULL; + mode_t expected_mode; + int saved_errno = 0; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return false); + + if (!VALID_STAT(smb_fname->st)) { + /* might be a create */ + return true; + } + + if (S_ISDIR(smb_fname->st.st_ex_mode)) { + expected_mode = 0777; + } else { + expected_mode = 0666; + } + if ((smb_fname->st.st_ex_mode & expected_mode) == expected_mode) { + return true; + } + + become_root(); + ret = SMB_VFS_NEXT_REMOVEXATTR(handle, + smb_fname, + config->xattr_name); + if (ret != 0) { + saved_errno = errno; + } + unbecome_root(); + if (saved_errno != 0) { + errno = saved_errno; + } + if (ret != 0 && errno != ENOATTR) { + DBG_ERR("Removing NFS4 xattr failed: %s\n", strerror(errno)); + return false; + } + + return true; +} + static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle, files_struct *fsp, const struct smb_filename *smb_fname_in, @@ -71,6 +121,11 @@ static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle, return NT_STATUS_INTERNAL_ERROR; } + ok = nfs4acl_validate_blob(handle, smb_fname); + if (!ok) { + return NT_STATUS_INTERNAL_ERROR; + } + do { int saved_errno = 0; @@ -304,17 +359,68 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle, const struct security_descriptor *psd) { struct nfs4acl_config *config = NULL; + mode_t existing_mode; + mode_t expected_mode; + mode_t restored_mode; + NTSTATUS status; + int ret; SMB_VFS_HANDLE_GET_DATA(handle, config, struct nfs4acl_config, return NT_STATUS_INTERNAL_ERROR); - return smb_set_nt_acl_nfs4(handle, - fsp, - &config->nfs4_params, - security_info_sent, - psd, - nfs4acl_smb4acl_set_fn); + if (!VALID_STAT(fsp->fsp_name->st)) { + DBG_ERR("Invalid stat info on [%s]\n", fsp_str_dbg(fsp)); + return NT_STATUS_INTERNAL_ERROR; + } + + existing_mode = fsp->fsp_name->st.st_ex_mode; + if (S_ISDIR(existing_mode)) { + expected_mode = 0777; + } else { + expected_mode = 0666; + } + if ((existing_mode & expected_mode) != expected_mode) { + int saved_errno = 0; + + restored_mode = existing_mode | expected_mode; + + become_root(); + if (fsp->fh->fd != -1) { + ret = SMB_VFS_NEXT_FCHMOD(handle, + fsp, + restored_mode); + } else { + ret = SMB_VFS_NEXT_CHMOD(handle, + fsp->fsp_name, + restored_mode); + } + if (ret != 0) { + saved_errno = errno; + } + unbecome_root(); + if (saved_errno != 0) { + errno = saved_errno; + } + if (ret != 0) { + DBG_ERR("Resetting POSIX mode on [%s] from [0%o]: %s\n", + fsp_str_dbg(fsp), existing_mode, + strerror(errno)); + return map_nt_error_from_unix(errno); + } + } + + status = smb_set_nt_acl_nfs4(handle, + fsp, + &config->nfs4_params, + security_info_sent, + psd, + nfs4acl_smb4acl_set_fn); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; } static int nfs4acl_connect(struct vfs_handle_struct *handle, From 8b1b1cd8cc561378058b915e03996ff567355d81 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 12:46:07 +0200 Subject: [PATCH 24/92] vfs_nfs4acl_xattr: implement take-ownership as in vfs_acl_common This allows take-ownership to work if the user has SEC_STD_WRITE_OWNER. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/vfs_nfs4acl_xattr.c | 55 +++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index 9c0c87f6331..d4f4d47635e 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -359,9 +359,11 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle, const struct security_descriptor *psd) { struct nfs4acl_config *config = NULL; + const struct security_token *token = NULL; mode_t existing_mode; mode_t expected_mode; mode_t restored_mode; + bool chown_needed = false; NTSTATUS status; int ret; @@ -416,11 +418,58 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle, security_info_sent, psd, nfs4acl_smb4acl_set_fn); - if (!NT_STATUS_IS_OK(status)) { - return status; + if (NT_STATUS_IS_OK(status)) { + return NT_STATUS_OK; } - return NT_STATUS_OK; + /* + * We got access denied. If we're already root, or we didn't + * need to do a chown, or the fsp isn't open with WRITE_OWNER + * access, just return. + */ + + if ((security_info_sent & SECINFO_OWNER) && + (psd->owner_sid != NULL)) + { + chown_needed = true; + } + if ((security_info_sent & SECINFO_GROUP) && + (psd->group_sid != NULL)) + { + chown_needed = true; + } + + if (get_current_uid(handle->conn) == 0 || + chown_needed == false || + !(fsp->access_mask & SEC_STD_WRITE_OWNER)) + { + return NT_STATUS_ACCESS_DENIED; + } + + /* + * Only allow take-ownership, not give-ownership. That's the way Windows + * implements SEC_STD_WRITE_OWNER. MS-FSA 2.1.5.16 just states: If + * InputBuffer.OwnerSid is not a valid owner SID for a file in the + * objectstore, as determined in an implementation specific manner, the + * object store MUST return STATUS_INVALID_OWNER. + */ + token = get_current_nttok(fsp->conn); + if (!security_token_is_sid(token, psd->owner_sid)) { + return NT_STATUS_INVALID_OWNER; + } + + DBG_DEBUG("overriding chown on file %s for sid %s\n", + fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid)); + + become_root(); + status = smb_set_nt_acl_nfs4(handle, + fsp, + &config->nfs4_params, + security_info_sent, + psd, + nfs4acl_smb4acl_set_fn); + unbecome_root(); + return status; } static int nfs4acl_connect(struct vfs_handle_struct *handle, From a1671558af014bd9303f62120e7fc3a9978be6fe Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 18 Oct 2017 20:48:37 +0200 Subject: [PATCH 25/92] vfs_nfs4acl_xattr: add XDR backend Add a NFS4 ACL backend that stores the ACL blob in an XDR encoded xattr, by default in "security.nfs4acl_xdr". This backend is enabled by setting "nfs4acl_xattr:encoding = xdr" in a share definition. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/modules/nfs41acl.x | 94 ++++++++ source3/modules/nfs4acl_xattr_xdr.c | 421 ++++++++++++++++++++++++++++++++++++ source3/modules/nfs4acl_xattr_xdr.h | 35 +++ source3/modules/vfs_nfs4acl_xattr.c | 11 + source3/modules/wscript_build | 23 +- source3/wscript | 2 + 6 files changed, 585 insertions(+), 1 deletion(-) create mode 100644 source3/modules/nfs41acl.x create mode 100644 source3/modules/nfs4acl_xattr_xdr.c create mode 100644 source3/modules/nfs4acl_xattr_xdr.h diff --git a/source3/modules/nfs41acl.x b/source3/modules/nfs41acl.x new file mode 100644 index 00000000000..9cfbd9f3074 --- /dev/null +++ b/source3/modules/nfs41acl.x @@ -0,0 +1,94 @@ +typedef opaque utf8string<>; +typedef utf8string utf8str_mixed; + +const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; +const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; +const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; +const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; + +typedef u_int acetype4; + +const ACE4_FILE_INHERIT_ACE = 0x00000001; +const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; +const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; +const ACE4_INHERIT_ONLY_ACE = 0x00000008; +const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; +const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; +const ACE4_IDENTIFIER_GROUP = 0x00000040; +const ACE4_INHERITED_ACE = 0x00000080; + +typedef u_int aceflag4; + +/* + * The following aceiflag4 is extensions for RFC 5661 that deals with storing + * identifiers as numerical ids instead UTF8 strings in order to avoid wasting + * CPU cycles for the costly conversion. + * + * Placed in a seperate field to avoid ever running into conflicts with newly + * defined NFSv4 flags. + */ + +const ACEI4_SPECIAL_WHO = 0x00000001; + +typedef u_int aceiflag4; + +/* + * Numerical representation of special identifiers from 6.2.1.5. + * ACEI4_SPECIAL_WHO MUST be set in nfsace4.aceiflag4. + */ +const ACE4_SPECIAL_OWNER = 1; +const ACE4_SPECIAL_GROUP = 2; +const ACE4_SPECIAL_EVERYONE = 3; +const ACE4_SPECIAL_INTERACTIVE = 4; +const ACE4_SPECIAL_NETWORK = 5; +const ACE4_SPECIAL_DIALUP = 6; +const ACE4_SPECIAL_BATCH = 7; +const ACE4_SPECIAL_ANONYMOUS = 8; +const ACE4_SPECIAL_AUTHENTICATED = 9; +const ACE4_SPECIAL_SERVICE = 10; + +const ACE4_READ_DATA = 0x00000001; +const ACE4_LIST_DIRECTORY = 0x00000001; +const ACE4_WRITE_DATA = 0x00000002; +const ACE4_ADD_FILE = 0x00000002; +const ACE4_APPEND_DATA = 0x00000004; +const ACE4_ADD_SUBDIRECTORY = 0x00000004; +const ACE4_READ_NAMED_ATTRS = 0x00000008; +const ACE4_WRITE_NAMED_ATTRS = 0x00000010; +const ACE4_EXECUTE = 0x00000020; +const ACE4_DELETE_CHILD = 0x00000040; +const ACE4_READ_ATTRIBUTES = 0x00000080; +const ACE4_WRITE_ATTRIBUTES = 0x00000100; +const ACE4_WRITE_RETENTION = 0x00000200; +const ACE4_WRITE_RETENTION_HOLD = 0x00000400; + +const ACE4_DELETE = 0x00010000; +const ACE4_READ_ACL = 0x00020000; +const ACE4_WRITE_ACL = 0x00040000; +const ACE4_WRITE_OWNER = 0x00080000; +const ACE4_SYNCHRONIZE = 0x00100000; + +typedef u_int acemask4; + +struct nfsace4 { + acetype4 type; + aceflag4 flag; + aceiflag4 iflag; + acemask4 access_mask; + u_int who; +}; + +const ACL4_XATTR_VERSION_40 = 0; +const ACL4_XATTR_VERSION_41 = 1; +const ACL4_XATTR_VERSION_DEFAULT = ACL4_XATTR_VERSION_40; + +const ACL4_AUTO_INHERIT = 0x00000001; +const ACL4_PROTECTED = 0x00000002; +const ACL4_DEFAULTED = 0x00000004; + +typedef u_int aclflag4; + +struct nfsacl41 { + aclflag4 na41_flag; + nfsace4 na41_aces<>; +}; diff --git a/source3/modules/nfs4acl_xattr_xdr.c b/source3/modules/nfs4acl_xattr_xdr.c new file mode 100644 index 00000000000..67684dceb17 --- /dev/null +++ b/source3/modules/nfs4acl_xattr_xdr.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) Ralph Boehme 2017 + * + * 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 "smbd/proto.h" +#include "libcli/security/security_descriptor.h" +#include "libcli/security/security_token.h" +#include "nfs4_acls.h" +#include "nfs4acl_xattr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +#ifdef HAVE_RPC_XDR_H +#include +#include "nfs41acl.h" +#include "nfs4acl_xattr_xdr.h" + +static unsigned nfs4acl_get_naces(nfsacl41 *nacl) +{ + return nacl->na41_aces.na41_aces_len; +} + +static void nfs4acl_set_naces(nfsacl41 *nacl, unsigned naces) +{ + nacl->na41_aces.na41_aces_len = naces; +} + +static unsigned nfs4acl_get_flags(nfsacl41 *nacl) +{ + return nacl->na41_flag; +} + +static void nfs4acl_set_flags(nfsacl41 *nacl, unsigned flags) +{ + nacl->na41_flag = flags; +} + +static size_t nfs4acl_get_xdrblob_size(nfsacl41 *nacl) +{ + size_t acl_size; + size_t aces_size; + unsigned naces = nfs4acl_get_naces(nacl); + + acl_size = sizeof(aclflag4) + sizeof(unsigned); + + if (naces > NFS4ACL_XDR_MAX_ACES) { + DBG_ERR("Too many ACEs: %u", naces); + return 0; + } + + aces_size = naces * sizeof(struct nfsace4); + if (acl_size + aces_size < acl_size) { + return 0; + } + acl_size += aces_size; + + return acl_size; +} + +static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize) +{ + size_t blobsize = _blobsize; + + blobsize -= sizeof(aclflag4); + blobsize -= sizeof(unsigned); + if (blobsize > _blobsize) { + return 0; + } + return (blobsize / sizeof(struct nfsace4)); +} + +static nfsacl41 *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces) +{ + size_t acl_size = sizeof(nfsacl41) + (naces * sizeof(struct nfsace4)); + nfsacl41 *nacl = NULL; + + if (naces > NFS4ACL_XDR_MAX_ACES) { + DBG_ERR("Too many ACEs: %d\n", naces); + return NULL; + } + + nacl = talloc_zero_size(mem_ctx, acl_size); + if (nacl == NULL) { + DBG_ERR("talloc_zero_size failed\n"); + return NULL; + } + + nfs4acl_set_naces(nacl, naces); + nacl->na41_aces.na41_aces_val = + (nfsace4 *)((char *)nacl + sizeof(nfsacl41)); + + return nacl; +} + +static nfsace4 *nfs4acl_get_ace(nfsacl41 *nacl, size_t n) +{ + return &nacl->na41_aces.na41_aces_val[n]; +} + +static unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags) +{ + unsigned nfs4acl_flags = 0; + + if (smb4acl_flags & SEC_DESC_DACL_AUTO_INHERITED) { + nfs4acl_flags |= ACL4_AUTO_INHERIT; + } + if (smb4acl_flags & SEC_DESC_DACL_PROTECTED) { + nfs4acl_flags |= ACL4_PROTECTED; + } + if (smb4acl_flags & SEC_DESC_DACL_DEFAULTED) { + nfs4acl_flags |= ACL4_DEFAULTED; + } + + return nfs4acl_flags; +} + +static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smb4acl, + nfsacl41 **_nacl) +{ + struct nfs4acl_config *config = NULL; + struct SMB4ACE_T *smb4ace = NULL; + size_t smb4naces = 0; + nfsacl41 *nacl = NULL; + uint16_t smb4acl_flags = 0; + unsigned nacl_flags = 0; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return false); + + smb4naces = smb_get_naces(smb4acl); + nacl = nfs4acl_alloc(mem_ctx, smb4naces); + nfs4acl_set_naces(nacl, 0); + + if (config->nfs_version > ACL4_XATTR_VERSION_40) { + smb4acl_flags = smbacl4_get_controlflags(smb4acl); + nacl_flags = smb4acl_to_nfs4acl_flags(smb4acl_flags); + nfs4acl_set_flags(nacl, nacl_flags); + } + + smb4ace = smb_first_ace4(smb4acl); + while (smb4ace != NULL) { + SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace); + size_t nace_count = nfs4acl_get_naces(nacl); + nfsace4 *nace = nfs4acl_get_ace(nacl, nace_count); + + nace->type = ace4prop->aceType; + nace->flag = ace4prop->aceFlags; + nace->access_mask = ace4prop->aceMask; + + if (ace4prop->flags & SMB_ACE4_ID_SPECIAL) { + nace->iflag |= ACEI4_SPECIAL_WHO; + + switch (ace4prop->who.special_id) { + case SMB_ACE4_WHO_OWNER: + nace->who = ACE4_SPECIAL_OWNER; + break; + + case SMB_ACE4_WHO_GROUP: + nace->who = ACE4_SPECIAL_GROUP; + break; + + case SMB_ACE4_WHO_EVERYONE: + nace->who = ACE4_SPECIAL_EVERYONE; + break; + + default: + DBG_ERR("Unsupported special id [%d]\n", + ace4prop->who.special_id); + continue; + } + } else { + if (ace4prop->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { + nace->flag |= ACE4_IDENTIFIER_GROUP; + nace->who = ace4prop->who.gid; + } else { + nace->who = ace4prop->who.uid; + } + } + + nace_count++; + nfs4acl_set_naces(nacl, nace_count); + smb4ace = smb_next_ace4(smb4ace); + } + + *_nacl = nacl; + return true; +} + +NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smb4acl, + DATA_BLOB *_blob) +{ + nfsacl41 *nacl = NULL; + XDR xdr = {0}; + size_t aclblobsize; + DATA_BLOB blob; + bool ok; + + ok = smb4acl_to_nfs4acl(handle, talloc_tos(), smb4acl, &nacl); + if (!ok) { + DBG_ERR("smb4acl_to_nfs4acl failed\n"); + return NT_STATUS_INTERNAL_ERROR; + } + + aclblobsize = nfs4acl_get_xdrblob_size(nacl); + if (aclblobsize == 0) { + return NT_STATUS_INTERNAL_ERROR; + } + + blob = data_blob_talloc(mem_ctx, NULL, aclblobsize); + if (blob.data == NULL) { + TALLOC_FREE(nacl); + return NT_STATUS_NO_MEMORY; + } + + xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE); + + ok = xdr_nfsacl41(&xdr, nacl); + TALLOC_FREE(nacl); + if (!ok) { + DBG_ERR("xdr_nfs4acl41 failed\n"); + return NT_STATUS_NO_MEMORY; + } + + *_blob = blob; + return NT_STATUS_OK; +} + +static uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags) +{ + uint16_t smb4acl_flags = SEC_DESC_SELF_RELATIVE; + + if (nfsacl41_flags & ACL4_AUTO_INHERIT) { + smb4acl_flags |= SEC_DESC_DACL_AUTO_INHERITED; + } + if (nfsacl41_flags & ACL4_PROTECTED) { + smb4acl_flags |= SEC_DESC_DACL_PROTECTED; + } + if (nfsacl41_flags & ACL4_DEFAULTED) { + smb4acl_flags |= SEC_DESC_DACL_DEFAULTED; + } + + return smb4acl_flags; +} + +static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + nfsacl41 **_nacl) +{ + struct nfs4acl_config *config = NULL; + nfsacl41 *nacl = NULL; + size_t naces; + XDR xdr = {0}; + bool ok; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + naces = nfs4acl_get_xdrblob_naces(blob->length); + nacl = nfs4acl_alloc(mem_ctx, naces); + + xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE); + + ok = xdr_nfsacl41(&xdr, nacl); + if (!ok) { + DBG_ERR("xdr_nfs4acl41 failed\n"); + return NT_STATUS_INTERNAL_ERROR; + } + + if (config->nfs_version == ACL4_XATTR_VERSION_40) { + nacl->na41_flag = 0; + } + + *_nacl = nacl; + return NT_STATUS_OK; +} + +static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + nfsacl41 *nacl, + struct SMB4ACL_T **_smb4acl) +{ + struct nfs4acl_config *config = NULL; + struct SMB4ACL_T *smb4acl = NULL; + unsigned nfsacl41_flag = 0; + uint16_t smb4acl_flags = 0; + unsigned naces = nfs4acl_get_naces(nacl); + int i; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + smb4acl = smb_create_smb4acl(mem_ctx); + if (smb4acl == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + + if (config->nfs_version > ACL4_XATTR_VERSION_40) { + nfsacl41_flag = nfs4acl_get_flags(nacl); + smb4acl_flags = nfs4acl_to_smb4acl_flags(nfsacl41_flag); + smbacl4_set_controlflags(smb4acl, smb4acl_flags); + } + + DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces); + + for (i = 0; i < naces; i++) { + nfsace4 *nace = nfs4acl_get_ace(nacl, i); + SMB_ACE4PROP_T smbace = { 0 }; + + DBG_DEBUG("type [%d] iflag [%x] flag [%x] mask [%x] who [%d]\n", + nace->type, nace->iflag, nace->flag, + nace->access_mask, nace->who); + + smbace.aceType = nace->type; + smbace.aceFlags = nace->flag; + smbace.aceMask = nace->access_mask; + + if (nace->iflag & ACEI4_SPECIAL_WHO) { + smbace.flags |= SMB_ACE4_ID_SPECIAL; + + switch (nace->who) { + case ACE4_SPECIAL_OWNER: + smbace.who.special_id = SMB_ACE4_WHO_OWNER; + break; + + case ACE4_SPECIAL_GROUP: + smbace.who.special_id = SMB_ACE4_WHO_GROUP; + break; + + case ACE4_SPECIAL_EVERYONE: + smbace.who.special_id = SMB_ACE4_WHO_EVERYONE; + break; + + default: + DBG_ERR("Unknown special id [%d]\n", nace->who); + continue; + } + } else { + if (nace->flag & ACE4_IDENTIFIER_GROUP) { + smbace.who.gid = nace->who; + } else { + smbace.who.uid = nace->who; + } + } + + smb_add_ace4(smb4acl, &smbace); + } + + *_smb4acl = smb4acl; + return NT_STATUS_OK; +} + +NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + struct SMB4ACL_T **_smb4acl) +{ + struct nfs4acl_config *config = NULL; + nfsacl41 *nacl = NULL; + struct SMB4ACL_T *smb4acl = NULL; + NTSTATUS status; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct nfs4acl_config, + return NT_STATUS_INTERNAL_ERROR); + + status = nfs4acl_xdr_blob_to_nfs4acl(handle, talloc_tos(), blob, &nacl); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = nfs4acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl); + TALLOC_FREE(nacl); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *_smb4acl = smb4acl; + return NT_STATUS_OK; +} + +#else /* !HAVE_RPC_XDR_H */ +NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + struct SMB4ACL_T **_smb4acl) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smbacl, + DATA_BLOB *blob) +{ + return NT_STATUS_NOT_SUPPORTED; +} +#endif /* HAVE_RPC_XDR_H */ diff --git a/source3/modules/nfs4acl_xattr_xdr.h b/source3/modules/nfs4acl_xattr_xdr.h new file mode 100644 index 00000000000..8a544349cc8 --- /dev/null +++ b/source3/modules/nfs4acl_xattr_xdr.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Ralph Boehme 2017 + * + * 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 . + * + */ + +#ifndef __NFS4ACL_XATTR_XDR_H__ +#define __NFS4ACL_XATTR_XDR_H__ + +#define NFS4ACL_XDR_XATTR_NAME "security.nfs4acl_xdr" +#define NFS4ACL_XDR_MAX_ACES 8192 + +NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, + struct SMB4ACL_T **_smb4acl); + +NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct SMB4ACL_T *smbacl, + DATA_BLOB *blob); + +#endif /* __NFS4ACL_XATTR_XDR_H__ */ diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c index d4f4d47635e..d301f25ed31 100644 --- a/source3/modules/vfs_nfs4acl_xattr.c +++ b/source3/modules/vfs_nfs4acl_xattr.c @@ -34,6 +34,7 @@ #include "librpc/gen_ndr/ndr_nfs4acl.h" #include "nfs4acl_xattr.h" #include "nfs4acl_xattr_ndr.h" +#include "nfs4acl_xattr_xdr.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -224,6 +225,9 @@ static NTSTATUS nfs4acl_blob_to_smb4(struct vfs_handle_struct *handle, case NFS4ACL_ENCODING_NDR: status = nfs4acl_ndr_blob_to_smb4(handle, mem_ctx, blob, smb4acl); break; + case NFS4ACL_ENCODING_XDR: + status = nfs4acl_xdr_blob_to_smb4(handle, mem_ctx, blob, smb4acl); + break; default: status = NT_STATUS_INTERNAL_ERROR; break; @@ -320,6 +324,10 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle, status = nfs4acl_smb4acl_to_ndr_blob(handle, talloc_tos(), smb4acl, &blob); break; + case NFS4ACL_ENCODING_XDR: + status = nfs4acl_smb4acl_to_xdr_blob(handle, talloc_tos(), + smb4acl, &blob); + break; default: status = NT_STATUS_INTERNAL_ERROR; break; @@ -515,6 +523,9 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle, config->encoding = (enum nfs4acl_encoding)enumval; switch (config->encoding) { + case NFS4ACL_ENCODING_XDR: + default_xattr_name = NFS4ACL_XDR_XATTR_NAME; + break; case NFS4ACL_ENCODING_NDR: default: default_xattr_name = NFS4ACL_NDR_XATTR_NAME; diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index 6943d474826..ab9be384189 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -217,9 +217,30 @@ bld.SAMBA3_MODULE('vfs_zfsacl', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_zfsacl'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_zfsacl')) +xdr_buf_hack = 'sed -e "s@^\([ \t]*register int32_t \*buf\);@\\1 = buf;@"' + +bld.SAMBA_GENERATOR('nfs41acl-xdr-c', + source='nfs41acl.x', + target='nfs41acl_xdr.c', + rule='rpcgen -c ${SRC} | ' + xdr_buf_hack + ' > ${TGT}') + +bld.SAMBA_GENERATOR('nfs41acl-h', + source='nfs41acl.x', + target='nfs41acl.h', + rule='rpcgen -h ${SRC} > ${TGT}') + +vfs_nfs4acl_xattr_source = ''' + vfs_nfs4acl_xattr.c + nfs4acl_xattr_ndr.c + nfs4acl_xattr_xdr.c + ''' + +if bld.CONFIG_SET("HAVE_RPC_XDR_H"): + vfs_nfs4acl_xattr_source += ' nfs41acl_xdr.c' + bld.SAMBA3_MODULE('vfs_nfs4acl_xattr', subsystem='vfs', - source='vfs_nfs4acl_xattr.c nfs4acl_xattr_ndr.c', + source=vfs_nfs4acl_xattr_source, deps='NFS4_ACLS sunacl NDR_NFS4ACL', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_nfs4acl_xattr'), diff --git a/source3/wscript b/source3/wscript index 3638abab202..814433488e4 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1664,6 +1664,8 @@ main() { Logs.info("building with Spotlight support") default_static_modules.extend(TO_LIST('rpc_mdssvc_module')) + conf.CHECK_HEADERS('rpc/xdr.h') + forced_static_modules.extend(TO_LIST('auth_builtin auth_sam auth_winbind')) default_static_modules.extend(TO_LIST('''pdb_smbpasswd pdb_tdbsam auth_unix From e981b41a37c78de1d7ad114921f65502a365dd66 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 7 Sep 2017 17:29:03 +0200 Subject: [PATCH 26/92] selftest: run raw.acls tests against a share with XDR NFS4 ACLs Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 6 ++++++ selftest/target/Samba3.pm | 8 ++++++++ source3/selftest/tests.py | 1 + 3 files changed, 15 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index 36c1697f9a4..1791614fc90 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -34,6 +34,12 @@ ^samba3.raw.acls nfs4acl_xattr-special-40.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special-40.inherit_creator_owner\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-special-40.inherit_creator_group\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-40.INHERITFLAGS\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-40.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-40.create_owner_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-40.nulldacl\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-40.inherit_creator_owner\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-40.inherit_creator_group\(nt4_dc\) ^samba3.base.delete.deltest16a ^samba3.base.delete.deltest17a ^samba3.unix.whoami anonymous connection.whoami\(ad_dc\) # We need to resolve if we should be including SID_NT_WORLD and SID_NT_NETWORK in this token diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 57db4fa1c60..248075ddffa 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1882,6 +1882,14 @@ sub provision($$$$$$$$$) nfs4:mode = simple vfs objects = nfs4acl_xattr xattr_tdb +[nfs4acl_xdr_40] + path = $shrdir + comment = smb username is [%U] + vfs objects = nfs4acl_xattr xattr_tdb + nfs4:mode = simple + nfs4acl_xattr:encoding = xdr + nfs4acl_xattr:version = 40 + [xcopy_share] path = $shrdir comment = smb username is [%U] diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 4dc7f753fb5..e2a8b7a4db5 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -464,6 +464,7 @@ def plansmbtorture4testsuite(name, env, options, description=''): plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-40') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_special_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-special-40') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-41') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_xdr_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-xdr-40') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD') elif t == "smb2.ioctl": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/fs_specific -U$USERNAME%$PASSWORD', 'fs_specific') From d1476988408a676176cddbe6ffb1c42a66dd756f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 19 Oct 2017 14:24:03 +0200 Subject: [PATCH 27/92] selftest: run raw.acls test with XDR NFS41 ACLs Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail | 3 +++ selftest/target/Samba3.pm | 8 ++++++++ source3/selftest/tests.py | 1 + 3 files changed, 12 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index 1791614fc90..3c910fb3d6f 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -40,6 +40,9 @@ ^samba3.raw.acls nfs4acl_xattr-xdr-40.nulldacl\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-xdr-40.inherit_creator_owner\(nt4_dc\) ^samba3.raw.acls nfs4acl_xattr-xdr-40.inherit_creator_group\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-41.create_owner_file\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-41.create_owner_dir\(nt4_dc\) +^samba3.raw.acls nfs4acl_xattr-xdr-41.nulldacl\(nt4_dc\) ^samba3.base.delete.deltest16a ^samba3.base.delete.deltest17a ^samba3.unix.whoami anonymous connection.whoami\(ad_dc\) # We need to resolve if we should be including SID_NT_WORLD and SID_NT_NETWORK in this token diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 248075ddffa..688045522af 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1890,6 +1890,14 @@ sub provision($$$$$$$$$) nfs4acl_xattr:encoding = xdr nfs4acl_xattr:version = 40 +[nfs4acl_xdr_41] + path = $shrdir + comment = smb username is [%U] + vfs objects = nfs4acl_xattr xattr_tdb + nfs4:mode = simple + nfs4acl_xattr:encoding = xdr + nfs4acl_xattr:version = 41 + [xcopy_share] path = $shrdir comment = smb username is [%U] diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index e2a8b7a4db5..186b2235875 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -465,6 +465,7 @@ def plansmbtorture4testsuite(name, env, options, description=''): plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_special_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-special-40') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-41') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_xdr_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-xdr-40') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_xdr_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-xdr-41') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD') elif t == "smb2.ioctl": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/fs_specific -U$USERNAME%$PASSWORD', 'fs_specific') From d12ba2d342c4efa26057122025f5692b075af73b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 23 Oct 2017 18:56:37 +0200 Subject: [PATCH 28/92] manpages: add vfs_nfs4acl_xattr.8 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Nov 8 04:27:28 CET 2017 on sn-devel-144 --- docs-xml/manpages/vfs_nfs4acl_xattr.8.xml | 134 ++++++++++++++++++++++++++++++ docs-xml/wscript_build | 1 + 2 files changed, 135 insertions(+) create mode 100644 docs-xml/manpages/vfs_nfs4acl_xattr.8.xml diff --git a/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml b/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml new file mode 100644 index 00000000000..16737349b71 --- /dev/null +++ b/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml @@ -0,0 +1,134 @@ + + + + + + vfs_nfs4acl_xattr + 8 + Samba + System Administration tools + 4.7 + + + + + vfs_nfs4acl_xattr + Save NTFS-ACLs as NFS4 encoded blobs in extended + attributes + + + + + vfs objects = nfs4acl_xattr + + + + + DESCRIPTION + + This VFS module is part of the + samba + 7 suite. + + The vfs_acl_xattr VFS module stores NTFS Access + Control Lists (ACLs) in Extended Attributes (EAs/xattrs). This enables the + full mapping of Windows ACLs on Samba servers. + + + This module is stackable. + + + + + OPTIONS + + + + + nfs4acl_xattr:encoding = [ndr|xdr] + + This parameter configures the marshaling format used in the ACL + blob and the default extended attribute name used to store the blob. + + + When set to ndr (default) - store the NT + ACL with POSIX draft NFSv4 compatible NDR encoding. By default this + uses the extended attribute "security.nfs4acl_ndr". + + When set to xdr - store the NT ACL in a + format similar to NFS 4.1 RFC 5661 in XDR encoding. The main + differences to RFC 5661 are the use of ids instead of strings as users + and group identifiers and an additional attribute per nfsace4. By + default this encoding stores the blob in the extended attribute + "security.nfs4acl_xdr". + + + + + nfs4acl_xattr:version = [40|41] + + This parameter configures the NFS4 ACL level. Only + 41 fully supports mapping NT ACLs and should be + used. The default is 41. + + + + + nfs4acl_xattr:default acl style = [posix|windows|everyone] + + This parameter determines the type of ACL that is synthesized in + case a file or directory lacks an ACL extended attribute. + + When set to posix, an ACL will be + synthesized based on the POSIX mode permissions for user, group and + others, with an additional ACE for NT + Authority\SYSTEM will full rights. + + When set to windows, an ACL is synthesized + the same way Windows does it, only including permissions for the owner + and NT Authority\SYSTEM. + + When set to everyone, an ACL is synthesized + giving full permissions to everyone (S-1-1-0). + + The default for this option is + everyone. + + + + + nfs4acl_xattr:xattr_name = STRING + + This parameter configures the extended attribute name used to + store the marshaled ACL. + The default depends on the setting for + nfs4acl_xattr:encoding. + + + + + + + + EXAMPLES + + A directory can be exported via Samba using this module as + follows: + + + + nfs4acl_xattr + /foo/bar + + + + + 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. + + + diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build index 5670572167f..afba0b9e841 100644 --- a/docs-xml/wscript_build +++ b/docs-xml/wscript_build @@ -74,6 +74,7 @@ manpages=''' manpages/vfs_linux_xfs_sgid.8 manpages/vfs_media_harmony.8 manpages/vfs_netatalk.8 + manpages/vfs_nfs4acl_xattr.8 manpages/vfs_offline.8 manpages/vfs_prealloc.8 manpages/vfs_preopen.8 From aed7faeab4b1c701768bb3c56b3f3bbfd2801938 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Wed, 8 Nov 2017 09:22:29 +1100 Subject: [PATCH 29/92] ctdb-tests: Fix some harmless CIDs CID 1420632: Resource leaks (RESOURCE LEAK) CID 1420631: Security best practices violations (TOCTOU) CID 1417432: Resource leaks (RESOURCE LEAK) CID 1417429: Security best practices violations (TOCTOU) CID 1417427: Resource leaks (RESOURCE LEAK) These are all in test code and constrained to the test environment, so can't result in privilege escape. No backport necessary. However, we might as well get them off the list. Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Wed Nov 8 11:28:40 CET 2017 on sn-devel-144 --- ctdb/tests/src/sock_daemon_test.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c index bba0df26a0a..95045d175ff 100644 --- a/ctdb/tests/src/sock_daemon_test.c +++ b/ctdb/tests/src/sock_daemon_test.c @@ -216,16 +216,16 @@ static void test2(TALLOC_CTX *mem_ctx, const char *pidfile, assert(n == sizeof(ret)); assert(ret == 1); - ret = stat(pidfile, &st); - assert(ret == 0); - assert(S_ISREG(st.st_mode)); - pidfile_fd = open(pidfile, O_RDONLY, 0644); assert(pidfile_fd != -1); + ret = fstat(pidfile_fd, &st); + assert(ret == 0); + assert(S_ISREG(st.st_mode)); n = read(pidfile_fd, pidstr, sizeof(pidstr)-1); assert(n != -1); pid2 = (pid_t)atoi(pidstr); assert(pid == pid2); + close(pidfile_fd); ret = kill(pid, SIGHUP); assert(ret == 0); @@ -1315,6 +1315,7 @@ static void test9(TALLOC_CTX *mem_ctx, const char *pidfile, assert(n != -1); pid2 = (pid_t)atoi(pidstr); assert(pid != pid2); + close(pidfile_fd); ret = kill(pid2, SIGTERM); assert(ret == 0); @@ -1431,16 +1432,13 @@ static void test10(TALLOC_CTX *mem_ctx, const char *pidfile, assert(n == sizeof(ret)); assert(ret == 1); - ret = stat(pidfile, &st); - assert(ret == 0); - assert(S_ISREG(st.st_mode)); - pidfile_fd = open(pidfile, O_RDONLY, 0644); assert(pidfile_fd != -1); n = read(pidfile_fd, pidstr, sizeof(pidstr)-1); assert(n != -1); pid2 = (pid_t)atoi(pidstr); assert(pid == pid2); + close(pidfile_fd); ret = kill(pid, SIGTERM); assert(ret == 0); From e00ba05d33af9d922fcad7f24bc5814d9145d71a Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 24 Oct 2017 09:00:11 +0200 Subject: [PATCH 30/92] python: Port ntvfs posix bindings to Python 3 compatible form Signed-off-by: Lumir Balhar Reviewed-by: Andrew Bartlet Reviewed-by: Andreas Schneider --- selftest/tests.py | 2 +- source4/ntvfs/posix/python/pyposix_eadb.c | 23 ++++++++++++++++------- source4/ntvfs/posix/python/pyxattr_native.c | 23 +++++++++++++++-------- source4/ntvfs/posix/python/pyxattr_tdb.c | 23 ++++++++++++++++------- source4/ntvfs/posix/wscript_build | 24 +++++++++++++----------- 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/selftest/tests.py b/selftest/tests.py index 704dbad3b73..181313ebc95 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -126,7 +126,7 @@ os.path.join(bbdir, "dbcheck-links.sh"), '$PREFIX_ABS/provision', 'release-4-5-0-pre1', configuration]) planpythontestsuite("none", "samba.tests.upgradeprovision") -planpythontestsuite("none", "samba.tests.xattr") +planpythontestsuite("none", "samba.tests.xattr", py3_compatible=True) planpythontestsuite("none", "samba.tests.ntacls") planpythontestsuite("none", "samba.tests.policy") planpythontestsuite("none", "samba.tests.kcc.graph") diff --git a/source4/ntvfs/posix/python/pyposix_eadb.c b/source4/ntvfs/posix/python/pyposix_eadb.c index a94440be3f0..d43c7c47bb7 100644 --- a/source4/ntvfs/posix/python/pyposix_eadb.c +++ b/source4/ntvfs/posix/python/pyposix_eadb.c @@ -19,6 +19,7 @@ */ #include +#include "python/py3compat.h" #include "includes.h" #include "system/filesys.h" #include @@ -28,8 +29,6 @@ #include "libcli/util/pyerrors.h" #include "param/pyparam.h" -void initposix_eadb(void); - static PyObject *py_is_xattr_supported(PyObject *self) { return Py_True; @@ -102,7 +101,7 @@ static PyObject *py_wrap_getxattr(PyObject *self, PyObject *args) talloc_free(mem_ctx); return NULL; } - ret = PyString_FromStringAndSize((char *)blob.data, blob.length); + ret = PyStr_FromStringAndSize((char *)blob.data, blob.length); talloc_free(mem_ctx); return ret; } @@ -119,12 +118,22 @@ static PyMethodDef py_posix_eadb_methods[] = { { NULL } }; -void initposix_eadb(void) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "posix_eadb", + .m_doc = "Python bindings for xattr manipulation.", + .m_size = -1, + .m_methods = py_posix_eadb_methods, +}; + +MODULE_INIT_FUNC(posix_eadb) { PyObject *m; - m = Py_InitModule3("posix_eadb", py_posix_eadb_methods, - "Python bindings for xattr manipulation."); + m = PyModule_Create(&moduledef); + if (m == NULL) - return; + return NULL; + + return m; } diff --git a/source4/ntvfs/posix/python/pyxattr_native.c b/source4/ntvfs/posix/python/pyxattr_native.c index 6758996da6d..c5e740fe577 100644 --- a/source4/ntvfs/posix/python/pyxattr_native.c +++ b/source4/ntvfs/posix/python/pyxattr_native.c @@ -19,13 +19,12 @@ */ #include +#include "python/py3compat.h" #include "includes.h" #include "librpc/ndr/libndr.h" #include "system/filesys.h" #include "lib/util/base64.h" -void initxattr_native(void); - static PyObject *py_is_xattr_supported(PyObject *self) { #if !defined(HAVE_XATTR_SUPPORT) @@ -91,7 +90,7 @@ static PyObject *py_wrap_getxattr(PyObject *self, PyObject *args) talloc_free(mem_ctx); return NULL; } - ret = PyString_FromStringAndSize(buf, len); + ret = PyStr_FromStringAndSize(buf, len); talloc_free(mem_ctx); return ret; } @@ -108,14 +107,22 @@ static PyMethodDef py_xattr_methods[] = { { NULL } }; -void initxattr_native(void) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "xattr_native", + .m_doc = "Python bindings for xattr manipulation.", + .m_size = -1, + .m_methods = py_xattr_methods, +}; + +MODULE_INIT_FUNC(xattr_native) { PyObject *m; - m = Py_InitModule3("xattr_native", py_xattr_methods, - "Python bindings for xattr manipulation."); + m = PyModule_Create(&moduledef); if (m == NULL) - return; -} + return NULL; + return m; +} diff --git a/source4/ntvfs/posix/python/pyxattr_tdb.c b/source4/ntvfs/posix/python/pyxattr_tdb.c index 56beedb1e50..05303b6aa00 100644 --- a/source4/ntvfs/posix/python/pyxattr_tdb.c +++ b/source4/ntvfs/posix/python/pyxattr_tdb.c @@ -19,6 +19,7 @@ */ #include +#include "python/py3compat.h" #include "includes.h" #include "system/filesys.h" #include @@ -32,8 +33,6 @@ #include "lib/dbwrap/dbwrap_tdb.h" #include "source3/lib/xattr_tdb.h" -void initxattr_tdb(void); - static PyObject *py_is_xattr_supported(PyObject *self) { return Py_True; @@ -138,7 +137,7 @@ static PyObject *py_wrap_getxattr(PyObject *self, PyObject *args) talloc_free(mem_ctx); return NULL; } - ret_obj = PyString_FromStringAndSize((char *)blob.data, xattr_size); + ret_obj = PyStr_FromStringAndSize((char *)blob.data, xattr_size); talloc_free(mem_ctx); return ret_obj; } @@ -155,13 +154,23 @@ static PyMethodDef py_xattr_methods[] = { { NULL } }; -void initxattr_tdb(void) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "xattr_tdb", + .m_doc = "Python bindings for xattr manipulation.", + .m_size = -1, + .m_methods = py_xattr_methods, +}; + +MODULE_INIT_FUNC(xattr_tdb) { PyObject *m; - m = Py_InitModule3("xattr_tdb", py_xattr_methods, - "Python bindings for xattr manipulation."); + m = PyModule_Create(&moduledef); + if (m == NULL) - return; + return NULL; + + return m; } diff --git a/source4/ntvfs/posix/wscript_build b/source4/ntvfs/posix/wscript_build index a07da33484b..eac2dfc68e4 100644 --- a/source4/ntvfs/posix/wscript_build +++ b/source4/ntvfs/posix/wscript_build @@ -41,27 +41,29 @@ if bld.CONFIG_SET('WITH_NTVFS_FILESERVER'): ) -bld.SAMBA_PYTHON('python_xattr_native', - source='python/pyxattr_native.c', - deps='ndr ldb samdb samba-credentials pyparam_util attr', - realname='samba/xattr_native.so' - ) - bld.SAMBA_LIBRARY('posix_eadb', source='posix_eadb.c', deps='tdb tdb-wrap samba-util', autoproto='posix_eadb_proto.h', private_library=True) -bld.SAMBA_PYTHON('python_posix_eadb', +for env in bld.gen_python_environments(): + pyparam_util = bld.pyembed_libname('pyparam_util') + + bld.SAMBA_PYTHON('python_xattr_native', + source='python/pyxattr_native.c', + deps='ndr ldb samdb samba-credentials %s attr' % pyparam_util, + realname='samba/xattr_native.so' + ) + + bld.SAMBA_PYTHON('python_posix_eadb', source='python/pyposix_eadb.c', - deps='pyparam_util posix_eadb tdb', + deps='%s posix_eadb tdb' % pyparam_util, realname='samba/posix_eadb.so' ) -bld.SAMBA_PYTHON('python_xattr_tdb', + bld.SAMBA_PYTHON('python_xattr_tdb', source='python/pyxattr_tdb.c', - deps='pyparam_util xattr_tdb', + deps='%s xattr_tdb' % pyparam_util, realname='samba/xattr_tdb.so' ) - From de5e23c236013d35625d296ea00c6206d55330aa Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 24 Oct 2017 09:01:16 +0200 Subject: [PATCH 31/92] python: tests: Add tests for samba.posix_eadb module Signed-off-by: Lumir Balhar Reviewed-by: Andrew Bartlet Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Wed Nov 8 21:54:59 CET 2017 on sn-devel-144 --- python/samba/tests/xattr.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/xattr.py b/python/samba/tests/xattr.py index 63874523f00..b024175a8d6 100644 --- a/python/samba/tests/xattr.py +++ b/python/samba/tests/xattr.py @@ -17,7 +17,7 @@ """Tests for samba.xattr_native and samba.xattr_tdb.""" -import samba.xattr_native, samba.xattr_tdb +import samba.xattr_native, samba.xattr_tdb, samba.posix_eadb from samba.xattr import copytree_with_xattrs from samba.dcerpc import xattr from samba.ndr import ndr_pack @@ -108,6 +108,34 @@ def test_set_and_get_tdb(self): os.unlink(tempf) os.unlink(eadb_path) + def test_set_posix_eadb(self): + tempf = self._tmpfilename() + eadb_path = self._eadbpath() + ntacl = xattr.NTACL() + ntacl.version = 1 + open(tempf, 'w').write("empty") + try: + samba.posix_eadb.wrap_setxattr(eadb_path, + tempf, "user.unittests", ndr_pack(ntacl)) + finally: + os.unlink(tempf) + os.unlink(eadb_path) + + def test_set_and_get_posix_eadb(self): + tempf = self._tmpfilename() + eadb_path = self._eadbpath() + reftxt = "this is a test" + open(tempf, 'w').write("empty") + try: + samba.posix_eadb.wrap_setxattr(eadb_path, tempf, "user.unittests", + reftxt) + text = samba.posix_eadb.wrap_getxattr(eadb_path, tempf, + "user.unittests") + self.assertEquals(text, reftxt) + finally: + os.unlink(tempf) + os.unlink(eadb_path) + class TestCopyTreeWithXattrs(TestCaseInTempDir): From 7470b9b18af282a742929d3fc90f4be5520428a1 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Thu, 2 Nov 2017 08:25:11 -0600 Subject: [PATCH 32/92] smbc_opendir should not return EEXIST with invalid login credentials Signed-off-by: David Mulder Reviewed-by: Andreas Schneider Reviewed-by: Jim McDonough Autobuild-User(master): Jim McDonough Autobuild-Date(master): Thu Nov 9 01:49:06 CET 2017 on sn-devel-144 --- source3/libsmb/libsmb_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index b0e5926fa65..93b9e800910 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -351,8 +351,8 @@ SMBC_server_internal(TALLOC_CTX *ctx, "?????", *pp_password); if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); cli_shutdown(srv->cli); + errno = map_errno_from_nt_status(status); srv->cli = NULL; smbc_getFunctionRemoveCachedServer(context)(context, srv); @@ -562,8 +562,8 @@ SMBC_server_internal(TALLOC_CTX *ctx, status = cli_tree_connect_creds(c, share, "?????", creds); if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); cli_shutdown(c); + errno = map_errno_from_nt_status(status); return NULL; } From 732ba3c84a2d40040550ea36b0478dd6af9a173a Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Tue, 31 Oct 2017 15:52:49 +0100 Subject: [PATCH 33/92] vfs_glusterfs: include glusterfs/api/glfs.h without relying on -I options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=13125 The glfs.h header file has always resided under glusterfs/api/ in the standard include directory. The glusterfs-api.pc file adds the unneeded -I${includedir}/glusterfs compiler option. This option will be removed from future versions of the pkg-config file. This change can safely be backported to older versions if there is a need to have them build against glusterfs-3.13 or newer. URL: https://review.gluster.org/18576 CC: Andrea Bolognani Signed-off-by: Niels de Vos Reviewed-by: Andreas Schneider Reviewed-by: Guenther Deschner Autobuild-User(master): Günther Deschner Autobuild-Date(master): Thu Nov 9 22:37:30 CET 2017 on sn-devel-144 --- source3/modules/vfs_glusterfs.c | 2 +- source3/wscript | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 3534ed7027e..8c245573b55 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -38,7 +38,7 @@ #include "includes.h" #include "smbd/smbd.h" #include -#include "api/glfs.h" +#include #include "lib/util/dlinklist.h" #include "lib/util/tevent_unix.h" #include "smbd/globals.h" diff --git a/source3/wscript b/source3/wscript index 814433488e4..e311f5f6efe 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1580,10 +1580,10 @@ main() { if Options.options.with_glusterfs: conf.CHECK_CFG(package='glusterfs-api', args='"glusterfs-api >= 4" --cflags --libs', msg='Checking for glusterfs-api >= 4', uselib_store="GFAPI") - conf.CHECK_HEADERS('api/glfs.h', lib='gfapi') + conf.CHECK_HEADERS('glusterfs/api/glfs.h', lib='gfapi') conf.CHECK_LIB('gfapi', shlib=True) - if conf.CONFIG_SET('HAVE_API_GLFS_H'): + if conf.CONFIG_SET('HAVE_GLUSTERFS_API_GLFS_H'): if Options.options.with_acl_support: conf.DEFINE('HAVE_GLUSTERFS', '1') else: From 62a556d5c8ce0650e3a2095ee62bea16c8eab1d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Nov 2017 21:47:01 +0000 Subject: [PATCH 34/92] Revert "s3/smbd: fix deferred open with streams and kernel oplocks" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b35a296a27a0807c780f2a9e7af2f2e93feefaa8. This was the cause of BUG: https://bugzilla.samba.org/show_bug.cgi?id=13058 1. client of smbd-1 opens the file and sets the oplock. 2. client of smbd-2 tries to open the file. open() fails(EAGAIN) and open is deferred. 3. client of smbd-1 sends oplock break request to the client. 4. client of smbd-1 closes the file. 5. client of smbd-1 opens the file and sets the oplock. 6. client of smbd-2 calls defer_open_done(), sees that the file lease was not changed and does not reschedule open. and is no longer needed now vfs_streams_xattr.c no longer opens the base file internally. Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme --- source3/smbd/open.c | 115 +++++----------------------------------------------- 1 file changed, 11 insertions(+), 104 deletions(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7781a6f86a7..89a267b0634 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1896,23 +1896,6 @@ static bool delay_for_oplock(files_struct *fsp, return delay; } -/** - * Return lease or oplock state from a share mode - **/ -static uint32_t get_lease_type_from_share_mode(const struct share_mode_data *d) -{ - uint32_t e_lease_type = 0; - uint32_t i; - - for (i=0; i < d->num_share_modes; i++) { - struct share_mode_entry *e = &d->share_modes[i]; - - e_lease_type |= get_lease_type(d, e); - } - - return e_lease_type; -} - static bool file_has_brlocks(files_struct *fsp) { struct byte_range_lock *br_lck; @@ -2325,11 +2308,6 @@ static struct deferred_open_record *deferred_open_record_create( struct defer_open_state { struct smbXsrv_connection *xconn; uint64_t mid; - struct file_id file_id; - struct timeval request_time; - struct timeval timeout; - bool kernel_oplock; - uint32_t lease_type; }; static void defer_open_done(struct tevent_req *req); @@ -2348,7 +2326,6 @@ static void defer_open(struct share_mode_lock *lck, struct timeval timeout, struct smb_request *req, bool delayed_for_oplocks, - bool kernel_oplock, struct file_id id) { struct deferred_open_record *open_rec = NULL; @@ -2360,12 +2337,11 @@ static void defer_open(struct share_mode_lock *lck, abs_timeout = timeval_sum(&request_time, &timeout); DBG_DEBUG("request time [%s] timeout [%s] mid [%" PRIu64 "] " - "delayed_for_oplocks [%s] kernel_oplock [%s] file_id [%s]\n", + "delayed_for_oplocks [%s] file_id [%s]\n", timeval_string(talloc_tos(), &request_time, false), timeval_string(talloc_tos(), &abs_timeout, false), req->mid, delayed_for_oplocks ? "yes" : "no", - kernel_oplock ? "yes" : "no", file_id_string_tos(&id)); open_rec = deferred_open_record_create(delayed_for_oplocks, @@ -2382,11 +2358,6 @@ static void defer_open(struct share_mode_lock *lck, } watch_state->xconn = req->xconn; watch_state->mid = req->mid; - watch_state->file_id = lck->data->id; - watch_state->request_time = request_time; - watch_state->timeout = timeout; - watch_state->kernel_oplock = kernel_oplock; - watch_state->lease_type = get_lease_type_from_share_mode(lck->data); DBG_DEBUG("defering mid %" PRIu64 "\n", req->mid); @@ -2416,12 +2387,8 @@ static void defer_open_done(struct tevent_req *req) { struct defer_open_state *state = tevent_req_callback_data( req, struct defer_open_state); - struct tevent_req *watch_req = NULL; - struct share_mode_lock *lck = NULL; - bool schedule_req = true; - struct timeval timeout; NTSTATUS status; - bool ok; + bool ret; status = dbwrap_watched_watch_recv(req, talloc_tos(), NULL, NULL, NULL); @@ -2433,72 +2400,13 @@ static void defer_open_done(struct tevent_req *req) * Even if it failed, retry anyway. TODO: We need a way to * tell a re-scheduled open about that error. */ - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && - state->kernel_oplock) - { - /* - * If we reschedule but the kernel oplock is still hold - * we would block in the second open as that will be a - * blocking open attempt. - */ - exit_server("Kernel oplock holder didn't " - "respond to break message"); - } - } - - if (state->kernel_oplock) { - lck = get_existing_share_mode_lock(talloc_tos(), state->file_id); - if (lck != NULL) { - uint32_t lease_type; - - lease_type = get_lease_type_from_share_mode(lck->data); - - if ((lease_type != 0) && - (lease_type == state->lease_type)) - { - DBG_DEBUG("Unchanged lease: %" PRIu32 "\n", - lease_type); - schedule_req = false; - } - } - } - - if (schedule_req) { - DBG_DEBUG("scheduling mid %" PRIu64 "\n", state->mid); - - ok = schedule_deferred_open_message_smb(state->xconn, - state->mid); - if (!ok) { - exit_server("schedule_deferred_open_message_smb failed"); - } - TALLOC_FREE(lck); - TALLOC_FREE(state); - return; - } - - DBG_DEBUG("Keep waiting for oplock release for [%s/%s%s] " - "mid: %" PRIu64 "\n", - lck->data->servicepath, - lck->data->base_name, - lck->data->stream_name ? lck->data->stream_name : "", - state->mid); - - watch_req = dbwrap_watched_watch_send(state, - state->xconn->ev_ctx, - lck->data->record, - (struct server_id){0}); - if (watch_req == NULL) { - exit_server("Could not watch share mode record"); } - tevent_req_set_callback(watch_req, defer_open_done, state); - timeout = timeval_sum(&state->request_time, &state->timeout); - ok = tevent_req_set_endtime(watch_req, state->xconn->ev_ctx, timeout); - if (!ok) { - exit_server("tevent_req_set_endtime failed"); - } + DEBUG(10, ("scheduling mid %llu\n", (unsigned long long)state->mid)); - TALLOC_FREE(lck); + ret = schedule_deferred_open_message_smb(state->xconn, state->mid); + SMB_ASSERT(ret); + TALLOC_FREE(state); } /** @@ -2649,8 +2557,7 @@ static NTSTATUS fcb_or_dos_open(struct smb_request *req, static void schedule_defer_open(struct share_mode_lock *lck, struct file_id id, struct timeval request_time, - struct smb_request *req, - bool kernel_oplock) + struct smb_request *req) { /* This is a relative time, added to the absolute request_time value to get the absolute timeout time. @@ -2674,7 +2581,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, return; } - defer_open(lck, request_time, timeout, req, true, kernel_oplock, id); + defer_open(lck, request_time, timeout, req, true, id); } /**************************************************************************** @@ -3360,7 +3267,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, first_open_attempt); if (delay) { schedule_defer_open(lck, fsp->file_id, request_time, - req, true); + req); TALLOC_FREE(lck); DEBUG(10, ("Sent oplock break request to kernel " "oplock holder\n")); @@ -3493,7 +3400,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, first_open_attempt); if (delay) { schedule_defer_open(lck, fsp->file_id, - request_time, req, false); + request_time, req); TALLOC_FREE(lck); fd_close(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -3597,7 +3504,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (!request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, req, - false, false, id); + false, id); } } From 15597a95ecd2d1c2b7edce4942d489c95796951f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Nov 2017 12:02:17 -0700 Subject: [PATCH 35/92] s4: torture: kernel_oplocks. Create a regression test case for bug #13058. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It implements the following test case: 1. client of smbd-1 opens the file and sets the oplock. 2. client of smbd-2 tries to open the file. open() fails(EAGAIN) and open is deferred. 3. client of smbd-1 sends oplock break request to the client. 4. client of smbd-1 closes the file. 5. client of smbd-1 opens the file and sets the oplock. 6. client of smbd-2 calls defer_open_done(), sees that the file lease was not changed and does not reschedule open. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13058 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Böhme --- source4/torture/smb2/oplock.c | 117 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c index e0db5ecb50d..3290ed42d8c 100644 --- a/source4/torture/smb2/oplock.c +++ b/source4/torture/smb2/oplock.c @@ -4674,6 +4674,122 @@ static bool test_smb2_kernel_oplocks6(struct torture_context *tctx, return ret; } +/** + * Recreate regression test from bug: + * + * https://bugzilla.samba.org/show_bug.cgi?id=13058 + * + * 1. smbd-1 opens the file and sets the oplock + * 2. smbd-2 tries to open the file. open() fails(EAGAIN) and open is deferred. + * 3. smbd-1 sends oplock break request to the client. + * 4. smbd-1 closes the file. + * 5. smbd-1 opens the file and sets the oplock. + * 6. smbd-2 calls defer_open_done(), and should re-break the oplock. + **/ + +static bool test_smb2_kernel_oplocks7(struct torture_context *tctx, + struct smb2_tree *tree, + struct smb2_tree *tree2) +{ + const char *fname = "test_kernel_oplock7.dat"; + NTSTATUS status; + bool ret = true; + struct smb2_create create; + struct smb2_handle h1 = {{0}}, h2 = {{0}}; + struct smb2_create create_2; + struct smb2_create io; + struct smb2_request *req; + + smb2_util_unlink(tree, fname); + status = torture_smb2_testfile(tree, fname, &h1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error creating testfile\n"); + smb2_util_close(tree, h1); + ZERO_STRUCT(h1); + + /* Close the open file on break. */ + tree->session->transport->oplock.handler = torture_oplock_handler_close; + tree->session->transport->oplock.private_data = tree; + ZERO_STRUCT(break_info); + + /* 1 - open file with oplock */ + ZERO_STRUCT(create); + create.in.desired_access = SEC_RIGHTS_FILE_ALL; + create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; + create.in.create_disposition = NTCREATEX_DISP_OPEN; + create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + create.in.fname = fname; + create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error opening the file\n"); + CHECK_VAL(create.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE); + + /* 2 - open file to break oplock */ + ZERO_STRUCT(create_2); + create_2.in.desired_access = SEC_RIGHTS_FILE_ALL; + create_2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + create_2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; + create_2.in.create_disposition = NTCREATEX_DISP_OPEN; + create_2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + create_2.in.fname = fname; + create_2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE; + + /* Open on tree2 - should cause a break on tree */ + req = smb2_create_send(tree2, &create_2); + torture_assert(tctx, req != NULL, "smb2_create_send"); + + /* The oplock break handler should close the file. */ + /* Steps 3 & 4. */ + torture_wait_for_oplock_break(tctx); + + tree->session->transport->oplock.handler = torture_oplock_handler; + + /* + * 5 - re-open on tree. NB. There is a race here + * depending on which smbd goes first. We either get + * an oplock level of SMB2_OPLOCK_LEVEL_EXCLUSIVE if + * the close and re-open on tree is processed first, or + * SMB2_OPLOCK_LEVEL_NONE if the pending create on + * tree2 is processed first. + */ + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error opening the file\n"); + + h1 = create.out.file.handle; + if (create.out.oplock_level != SMB2_OPLOCK_LEVEL_EXCLUSIVE && + create.out.oplock_level != SMB2_OPLOCK_LEVEL_NONE) { + torture_result(tctx, + TORTURE_FAIL, + "(%s): wrong value for oplock got 0x%x\n", + __location__, + (unsigned int)create.out.oplock_level); + ret = false; + goto done; + + } + + /* 6 - retrieve the second open. */ + status = smb2_create_recv(req, tctx, &io); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error opening the file\n"); + h2 = io.out.file.handle; + CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); + +done: + if (!smb2_util_handle_empty(h1)) { + smb2_util_close(tree, h1); + } + if (!smb2_util_handle_empty(h2)) { + smb2_util_close(tree2, h2); + } + smb2_util_unlink(tree, fname); + return ret; +} + struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -4685,6 +4801,7 @@ struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4); torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5); torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6); + torture_suite_add_2smb2_test(suite, "kernel_oplocks7", test_smb2_kernel_oplocks7); suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests"); From 71720e2e9c414f8ae823a5c6cfa624a4d8683926 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Oct 2017 13:46:04 +0100 Subject: [PATCH 36/92] libcli: Fix a typo Signed-off-by: Volker Lendecke Reviewed-by: Richard Sharpe --- libcli/smb/smbXcli_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 7322380d501..6335ce0c121 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -878,7 +878,7 @@ static NTSTATUS smbXcli_req_cancel_write_req(struct tevent_req *req) /* * Check if it's possible to cancel the request. - * If the result is true it's not to late. + * If the result is true it's not too late. * See writev_cancel(). */ ok = tevent_req_cancel(state->write_req); From 20cfcb7dbc5dd099384b76a76e3d35cf627100b6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Nov 2017 21:22:26 +0100 Subject: [PATCH 37/92] tevent: Fix a race condition We can't rely on tctx to exist after we unlocked the mutex. It took a while, but this does lead to data corruption. If *tctx is replaced with something where tctx->wakeup_fd points to a real, existing file descriptor, we're screwed. And by screwed, this means file corruption on disk. Again. I am not tall enough for this business. http://bholley.net/blog/2015/must-be-this-tall-to-write-multi-threaded-code.html BUG: https://bugzilla.samba.org/show_bug.cgi?id=13130 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Sat Nov 11 03:20:09 CET 2017 on sn-devel-144 --- lib/tevent/tevent_threads.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index 4d1a8805181..2e83f1b66c2 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -451,7 +451,7 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, { #ifdef HAVE_PTHREAD struct tevent_context *ev; - int ret; + int ret, wakeup_fd; ret = pthread_mutex_lock(&tctx->event_ctx_mutex); if (ret != 0) { @@ -495,6 +495,8 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, abort(); } + wakeup_fd = tctx->wakeup_fd; + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); @@ -510,7 +512,7 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, * than a noncontended one. So I'd opt for the lower footprint * initially. Maybe we have to change that later. */ - tevent_common_wakeup_fd(tctx->wakeup_fd); + tevent_common_wakeup_fd(wakeup_fd); #else /* * tevent_threaded_context_create() returned NULL with ENOSYS... From 6381044c0270a647c20935d22fd23f235d19b328 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Nov 2017 12:09:36 +0100 Subject: [PATCH 38/92] vfs: Remove aio_linux Triggered by https://bugzilla.samba.org/show_bug.cgi?id=13128 I think this module should go. Once Linux aio will do what Samba needs, this might be worth another look. What we should instead do soon is support Linux preadv2 and the RWF_NOWAIT flag to avoid the thread context switch whenever possible. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- WHATSNEW.txt | 9 + docs-xml/manpages/vfs_aio_linux.8.xml | 115 ----------- docs-xml/wscript_build | 1 - source3/modules/vfs_aio_linux.c | 346 ---------------------------------- source3/modules/wscript_build | 8 - source3/wscript | 26 --- 6 files changed, 9 insertions(+), 496 deletions(-) delete mode 100644 docs-xml/manpages/vfs_aio_linux.8.xml delete mode 100644 source3/modules/vfs_aio_linux.c diff --git a/WHATSNEW.txt b/WHATSNEW.txt index cc03f2016c8..475ebcbdc84 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -65,6 +65,15 @@ commands have been removed from rpcclient. "net rpc vampire keytab" from Active Directory domains continues to be supported. +vfs_aio_linux module removed +============================ + +The current Linux kernel aio does not match what Samba would +do. Shipping code that uses it leads people to false +assumptions. Samba implements async I/O based on threads by default, +there is no special module required to see benefits of read and write +request being sent do the disk in parallel. + KNOWN ISSUES ============ diff --git a/docs-xml/manpages/vfs_aio_linux.8.xml b/docs-xml/manpages/vfs_aio_linux.8.xml deleted file mode 100644 index 3a009501820..00000000000 --- a/docs-xml/manpages/vfs_aio_linux.8.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - vfs_aio_linux - 8 - Samba - System Administration tools - 4.7 - - - - - vfs_aio_linux - implement async I/O in Samba vfs using Linux kernel aio calls - - - - - vfs objects = aio_linux - - - - - DESCRIPTION - - This VFS module is part of the - samba - 7 suite. - - The aio_linux VFS module enables asynchronous - I/O for Samba on Linux kernels that have the kernel AIO calls available - without using the Posix AIO interface. Posix AIO can suffer from severe - limitations. For example, on some Linux versions the - real-time signals that it uses are broken under heavy load. - Other systems only allow AIO when special kernel modules are - loaded or only allow a certain system-wide amount of async - requests being scheduled. Systems based on glibc (most Linux - systems) only allow a single outstanding request per file - descriptor which essentially makes Posix AIO useless on systems - using the glibc implementation. - - To work around all these limitations, the aio_linux module - was written. It uses the Linux kernel AIO interface instead of the - internal Posix AIO interface to allow read and write calls - to be processed asynchronously. A queue size of 128 events - is used by default. To change this limit set the "aio num events" - parameter below. - - - - Note that the smb.conf parameters aio read size - and aio write size must also be set appropriately - for this module to be active. - - - This module MUST be listed last in any module stack as - the Samba VFS pread/pwrite interface is not thread-safe. This - module makes direct pread and pwrite system calls and does - NOT call the Samba VFS pread and pwrite interfaces. - - - - - - EXAMPLES - - Straight forward use: - - - - /data/ice - 1024 - 1024 - aio_linux - - - - - - OPTIONS - - - - - aio_linux:aio num events = INTEGER - - Set the maximum size of the event queue - that is used to limit outstanding IO requests. - - By default this is set to 128. - - - - - - - VERSION - - This man page is correct for version 4.0 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. - - - - diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build index afba0b9e841..0bd08d11cdb 100644 --- a/docs-xml/wscript_build +++ b/docs-xml/wscript_build @@ -52,7 +52,6 @@ manpages=''' manpages/vfs_acl_tdb.8 manpages/vfs_acl_xattr.8 manpages/vfs_aio_fork.8 - manpages/vfs_aio_linux.8 manpages/vfs_aio_pthread.8 manpages/vfs_audit.8 manpages/vfs_btrfs.8 diff --git a/source3/modules/vfs_aio_linux.c b/source3/modules/vfs_aio_linux.c deleted file mode 100644 index e89c2905bad..00000000000 --- a/source3/modules/vfs_aio_linux.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Simulate Posix AIO using Linux kernel AIO. - * - * Copyright (C) Jeremy Allison 2012 - * Copyright (C) Volker Lendecke 2012 - * - * 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" -#include "system/filesys.h" -#include "smbd/smbd.h" -#include "smbd/globals.h" -#include "lib/util/tevent_unix.h" -#include "lib/util/sys_rw.h" -#include -#include -#include "smbprofile.h" - -static int event_fd = -1; -static io_context_t io_ctx; -static struct tevent_fd *aio_read_event; -static bool used; -static unsigned num_busy; - -static void aio_linux_done(struct tevent_context *event_ctx, - struct tevent_fd *event, - uint16_t flags, void *private_data); - -/************************************************************************ - Housekeeping. Cleanup if no activity for 30 seconds. -***********************************************************************/ - -static void aio_linux_housekeeping(struct tevent_context *event_ctx, - struct tevent_timer *te, - struct timeval now, - void *private_data) -{ - /* Remove this timed event handler. */ - TALLOC_FREE(te); - - if ((num_busy != 0) || used) { - used = false; - - /* Still busy. Look again in 30 seconds. */ - (void)tevent_add_timer(event_ctx, - NULL, - timeval_current_ofs(30, 0), - aio_linux_housekeeping, - NULL); - return; - } - - /* No activity for 30 seconds. Close out kernel resources. */ - io_queue_release(io_ctx); - memset(&io_ctx, '\0', sizeof(io_ctx)); - - if (event_fd != -1) { - close(event_fd); - event_fd = -1; - } - - TALLOC_FREE(aio_read_event); -} - -/************************************************************************ - Ensure event fd and aio context are initialized. -***********************************************************************/ - -static bool init_aio_linux(struct vfs_handle_struct *handle) -{ - struct tevent_timer *te = NULL; - - if (event_fd != -1) { - /* Already initialized. */ - return true; - } - - /* Schedule a shutdown event for 30 seconds from now. */ - te = tevent_add_timer(handle->conn->sconn->ev_ctx, - NULL, - timeval_current_ofs(30, 0), - aio_linux_housekeeping, - NULL); - - if (te == NULL) { - goto fail; - } - - event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - if (event_fd == -1) { - goto fail; - } - - aio_read_event = tevent_add_fd(server_event_context(), - NULL, - event_fd, - TEVENT_FD_READ, - aio_linux_done, - NULL); - if (aio_read_event == NULL) { - goto fail; - } - - if (io_queue_init(lp_aio_max_threads(), &io_ctx)) { - goto fail; - } - - DEBUG(10,("init_aio_linux: initialized with up to %d events\n", - (int)lp_aio_max_threads())); - - return true; - - fail: - - DEBUG(10,("init_aio_linux: initialization failed\n")); - - TALLOC_FREE(te); - TALLOC_FREE(aio_read_event); - if (event_fd != -1) { - close(event_fd); - event_fd = -1; - } - memset(&io_ctx, '\0', sizeof(io_ctx)); - return false; -} - -struct aio_linux_state { - struct iocb event_iocb; - ssize_t ret; - struct vfs_aio_state vfs_aio_state; - struct timespec start; -}; - -static struct tevent_req *aio_linux_pread_send( - struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, - struct tevent_context *ev, struct files_struct *fsp, - void *data, size_t n, off_t offset) -{ - struct tevent_req *req; - struct aio_linux_state *state; - struct iocb *piocb; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct aio_linux_state); - if (req == NULL) { - return NULL; - } - if (!init_aio_linux(handle)) { - tevent_req_error(req, EIO); - return tevent_req_post(req, ev); - } - - io_prep_pread(&state->event_iocb, fsp->fh->fd, data, n, offset); - io_set_eventfd(&state->event_iocb, event_fd); - state->event_iocb.data = req; - - piocb = &state->event_iocb; - - PROFILE_TIMESTAMP(&state->start); - ret = io_submit(io_ctx, 1, &piocb); - if (ret < 0) { - tevent_req_error(req, -ret); - return tevent_req_post(req, ev); - } - num_busy += 1; - used = true; - return req; -} - -static struct tevent_req *aio_linux_pwrite_send( - struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, - struct tevent_context *ev, struct files_struct *fsp, - const void *data, size_t n, off_t offset) -{ - struct tevent_req *req; - struct aio_linux_state *state; - struct iocb *piocb; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct aio_linux_state); - if (req == NULL) { - return NULL; - } - if (!init_aio_linux(handle)) { - tevent_req_error(req, EIO); - return tevent_req_post(req, ev); - } - - io_prep_pwrite(&state->event_iocb, fsp->fh->fd, discard_const(data), - n, offset); - io_set_eventfd(&state->event_iocb, event_fd); - state->event_iocb.data = req; - - piocb = &state->event_iocb; - - PROFILE_TIMESTAMP(&state->start); - ret = io_submit(io_ctx, 1, &piocb); - if (ret < 0) { - tevent_req_error(req, -ret); - return tevent_req_post(req, ev); - } - num_busy += 1; - used = true; - return req; -} - -static struct tevent_req *aio_linux_fsync_send( - struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, - struct tevent_context *ev, struct files_struct *fsp) -{ - struct tevent_req *req; - struct aio_linux_state *state; - struct iocb *piocb; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct aio_linux_state); - if (req == NULL) { - return NULL; - } - if (!init_aio_linux(handle)) { - tevent_req_error(req, EIO); - return tevent_req_post(req, ev); - } - - io_prep_fsync(&state->event_iocb, fsp->fh->fd); - io_set_eventfd(&state->event_iocb, event_fd); - state->event_iocb.data = req; - - piocb = &state->event_iocb; - - PROFILE_TIMESTAMP(&state->start); - ret = io_submit(io_ctx, 1, &piocb); - if (ret < 0) { - tevent_req_error(req, -ret); - return tevent_req_post(req, ev); - } - num_busy += 1; - used = true; - return req; -} - -static void aio_linux_done(struct tevent_context *event_ctx, - struct tevent_fd *event, - uint16_t flags, void *private_data) -{ - uint64_t num_events = 0; - struct timespec end; - - DEBUG(10, ("aio_linux_done called with flags=%d\n", - (int)flags)); - - PROFILE_TIMESTAMP(&end); - - /* Read the number of events available. */ - if (sys_read(event_fd, &num_events, sizeof(num_events)) != - sizeof(num_events)) { - smb_panic("aio_linux_handle_completion: invalid read"); - } - - while (num_events > 0) { - struct timespec ts = { 0, }; - struct io_event finished; - struct tevent_req *req; - struct aio_linux_state *state; - int ret; - - ret = io_getevents(io_ctx, 1, 1, &finished, &ts); - if (ret < 0) { - DEBUG(1, ("aio_linux_done: io_getevents returned %s\n", - strerror(-ret))); - return; - } - if (ret == 0) { - DEBUG(10, ("aio_linux_done: io_getvents returned " - "0\n")); - continue; - } - - num_busy -= 1; - - req = talloc_get_type_abort(finished.data, - struct tevent_req); - state = tevent_req_data(req, struct aio_linux_state); - - if (finished.res < 0) { - state->ret = -1; - state->vfs_aio_state.error = -finished.res; - } else { - state->ret = finished.res; - } - state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start); - tevent_req_done(req); - num_events -= 1; - } -} - -static ssize_t aio_linux_recv(struct tevent_req *req, - struct vfs_aio_state *vfs_aio_state) -{ - struct aio_linux_state *state = tevent_req_data( - req, struct aio_linux_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 aio_linux_int_recv(struct tevent_req *req, - struct vfs_aio_state *vfs_aio_state) -{ - /* - * Use implicit conversion ssize_t->int - */ - return aio_linux_recv(req, vfs_aio_state); -} - -static struct vfs_fn_pointers vfs_aio_linux_fns = { - .pread_send_fn = aio_linux_pread_send, - .pread_recv_fn = aio_linux_recv, - .pwrite_send_fn = aio_linux_pwrite_send, - .pwrite_recv_fn = aio_linux_recv, - .fsync_send_fn = aio_linux_fsync_send, - .fsync_recv_fn = aio_linux_int_recv, -}; - -static_decl_vfs; -NTSTATUS vfs_aio_linux_init(TALLOC_CTX *ctx) -{ - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, - "aio_linux", &vfs_aio_linux_fns); -} diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index ab9be384189..4e4fdb98a1d 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -357,14 +357,6 @@ bld.SAMBA3_MODULE('vfs_aio_pthread', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_aio_pthread'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_aio_pthread')) -bld.SAMBA3_MODULE('vfs_aio_linux', - subsystem='vfs', - source='vfs_aio_linux.c', - deps='samba-util aio', - init_function='', - internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_aio_linux'), - enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_aio_linux')) - bld.SAMBA3_MODULE('vfs_preopen', subsystem='vfs', source='vfs_preopen.c', diff --git a/source3/wscript b/source3/wscript index e311f5f6efe..d45a7d9ec60 100644 --- a/source3/wscript +++ b/source3/wscript @@ -551,29 +551,6 @@ return acl_get_perm_np(permset_d, perm); msg='Checking for openat', headers='fcntl.h') - if host_os.rfind('linux') > -1: - conf.CHECK_FUNCS_IN('io_submit', 'aio') - conf.CHECK_CODE(''' -struct io_event ioev; -struct iocb *ioc; -io_context_t ctx; -struct timespec ts; -int fd; -char *buf; -fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); -io_queue_init(128,&ctx); -io_prep_pwrite(ioc, 1, buf, 1, 0); -io_prep_pread(ioc, 1, buf, 1, 0); -io_set_eventfd(ioc, fd); -io_set_callback(ioc, (io_callback_t)(0)); -io_submit(ctx, 1, &ioc); -io_getevents(ctx, 1, 1, &ioev, &ts); -''', - 'HAVE_LINUX_KERNEL_AIO', - msg='Checking for linux kernel asynchronous io support', - headers='unistd.h stdlib.h sys/types.h fcntl.h sys/eventfd.h libaio.h', - lib='aio') - conf.CHECK_CODE(''' struct msghdr msg; union { @@ -1717,9 +1694,6 @@ main() { if Options.options.with_pthreadpool: default_shared_modules.extend(TO_LIST('vfs_aio_pthread')) - if conf.CONFIG_SET('HAVE_LINUX_KERNEL_AIO'): - default_shared_modules.extend(TO_LIST('vfs_aio_linux')) - if conf.CONFIG_SET('HAVE_LDAP'): default_static_modules.extend(TO_LIST('pdb_ldapsam idmap_ldap')) From f53ee1284f785e85fea33506263f76757335ee20 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:32:49 +0200 Subject: [PATCH 39/92] smbd: remove calls to dptr_init_search_op() dptr_init_search_op() invokes a VFS operation which is a no-op in all in-tree VFS modules. Furthermore, dptr_init_search_op() is not being called from SMB2 search code, which hints that no out-of-tree VFS module needs it. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/smbd/reply.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7b07078249b..9c82ebff03f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1896,9 +1896,6 @@ void reply_search(struct smb_request *req) DEBUG(4,("dptr_num is %d\n",dptr_num)); - /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */ - dptr_init_search_op(dirptr); - if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) { char buf[DIR_STRUCT_SIZE]; memcpy(buf,status,21); From b8aa599f060ea6de7277b0af42659a09f4469165 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:35:54 +0200 Subject: [PATCH 40/92] smbd: remove calls to dptr_init_search_op() from TRANS2 search code dptr_init_search_op() invokes VFS operations which are no-op in all in-tree VFS modules. Furthermore, it's not being called by the SMB2 search code, so probably it's not being used by any out-of-tree VFS module either. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/smbd/trans2.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index de6073a973f..dbad71be3b7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2867,9 +2867,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd dptr_num = dptr_dnum(dirptr); DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype)); - /* Initialize per TRANS2_FIND_FIRST operation data */ - dptr_init_search_op(dirptr); - /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ @@ -3237,9 +3234,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd dptr_TellDir(dirptr), (int)backup_priv)); - /* Initialize per TRANS2_FIND_NEXT operation data */ - dptr_init_search_op(dirptr); - /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ From 1d9e8ff87b1c0e7e495ebbfb230a3f0ac7c57285 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:38:41 +0200 Subject: [PATCH 41/92] smbd: remove dptr_init_search_op() This function is now not being used. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/smbd/dir.c | 8 -------- source3/smbd/proto.h | 1 - 2 files changed, 9 deletions(-) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 19e29640118..6621b4ee387 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -886,14 +886,6 @@ bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S return SearchDir(dptr->dir_hnd, name, poffset); } -/**************************************************************************** - Initialize variables & state data at the beginning of all search SMB requests. -****************************************************************************/ -void dptr_init_search_op(struct dptr_struct *dptr) -{ - SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir); -} - /**************************************************************************** Map a native directory offset to a 32-bit cookie. ****************************************************************************/ diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index c85a6cccd5b..fe376404709 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -207,7 +207,6 @@ int dptr_dnum(struct dptr_struct *dptr); bool dptr_get_priv(struct dptr_struct *dptr); void dptr_set_priv(struct dptr_struct *dptr); bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst); -void dptr_init_search_op(struct dptr_struct *dptr); bool dptr_fill(struct smbd_server_connection *sconn, char *buf1,unsigned int key); struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn, From fd1aa4a6b0f58882e3ae6a53f9116d254e036cdf Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:20:47 +0200 Subject: [PATCH 42/92] VFS examples: remove init_search_ops Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- examples/VFS/skel_opaque.c | 6 ------ examples/VFS/skel_transparent.c | 6 ------ 2 files changed, 12 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 614dcffa928..e6c066d2eb8 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -185,11 +185,6 @@ static int skel_closedir(vfs_handle_struct *handle, DIR *dir) return -1; } -static void skel_init_search_op(struct vfs_handle_struct *handle, DIR *dirp) -{ - ; -} - static int skel_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { @@ -954,7 +949,6 @@ struct vfs_fn_pointers skel_opaque_fns = { .mkdir_fn = skel_mkdir, .rmdir_fn = skel_rmdir, .closedir_fn = skel_closedir, - .init_search_op_fn = skel_init_search_op, /* File operations */ diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 2f59a3db870..59d16340025 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -182,11 +182,6 @@ static int skel_closedir(vfs_handle_struct *handle, DIR *dir) return SMB_VFS_NEXT_CLOSEDIR(handle, dir); } -static void skel_init_search_op(struct vfs_handle_struct *handle, DIR *dirp) -{ - SMB_VFS_NEXT_INIT_SEARCH_OP(handle, dirp); -} - static int skel_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { @@ -1127,7 +1122,6 @@ struct vfs_fn_pointers skel_transparent_fns = { .mkdir_fn = skel_mkdir, .rmdir_fn = skel_rmdir, .closedir_fn = skel_closedir, - .init_search_op_fn = skel_init_search_op, /* File operations */ From 0f1dede9a90996d0a0cbbe91c2a0389b47b706b7 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:39:54 +0200 Subject: [PATCH 43/92] vfs_glusterfs: remove init_search_op handling This VFS function is about to be removed. It can be removed by a separate commit because both the glusterfs and the default implementations are no-ops. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/modules/vfs_glusterfs.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 8c245573b55..9489d9d4990 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -541,12 +541,6 @@ static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle, DIR *dirp) glfs_seekdir((void *)dirp, 0); } -static void vfs_gluster_init_search_op(struct vfs_handle_struct *handle, - DIR *dirp) -{ - return; -} - static int vfs_gluster_mkdir(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, mode_t mode) @@ -1434,7 +1428,6 @@ static struct vfs_fn_pointers glusterfs_fns = { .mkdir_fn = vfs_gluster_mkdir, .rmdir_fn = vfs_gluster_rmdir, .closedir_fn = vfs_gluster_closedir, - .init_search_op_fn = vfs_gluster_init_search_op, /* File Operations */ From fba8bd6cb8315cfbab8883b12eb818a0f8fddfa7 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:47:29 +0200 Subject: [PATCH 44/92] vfs_time_audit: remove init_search_op implementation This VFS call is about to be removed in a following commit. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/modules/vfs_time_audit.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 7116796cc46..8e08a7be095 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -550,22 +550,6 @@ static int smb_time_audit_closedir(vfs_handle_struct *handle, return result; } -static void smb_time_audit_init_search_op(vfs_handle_struct *handle, - DIR *dirp) -{ - struct timespec ts1,ts2; - double timediff; - - clock_gettime_mono(&ts1); - SMB_VFS_NEXT_INIT_SEARCH_OP(handle, dirp); - clock_gettime_mono(&ts2); - timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; - - if (timediff > audit_timeout) { - smb_time_audit_log("init_search_op", timediff); - } -} - static int smb_time_audit_open(vfs_handle_struct *handle, struct smb_filename *fname, files_struct *fsp, @@ -2708,7 +2692,6 @@ static struct vfs_fn_pointers vfs_time_audit_fns = { .mkdir_fn = smb_time_audit_mkdir, .rmdir_fn = smb_time_audit_rmdir, .closedir_fn = smb_time_audit_closedir, - .init_search_op_fn = smb_time_audit_init_search_op, .open_fn = smb_time_audit_open, .create_file_fn = smb_time_audit_create_file, .close_fn = smb_time_audit_close, From 7a34ed88c88036942d955fcc1e303e147f2001fb Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:48:26 +0200 Subject: [PATCH 45/92] vfs_media_harmony: remove handling of init_search_op This VFS function is about to be removed in a following commit. In the meantime, not handling it by vfs_media_harmony poses no issue because the underlying implenentation is a no-op. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/modules/vfs_media_harmony.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index e39a4447bc9..43e69086945 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -1128,18 +1128,6 @@ static int mh_closedir(vfs_handle_struct *handle, return SMB_VFS_NEXT_CLOSEDIR(handle, realdirp); } -/* - * Success: no success result defined. - * Failure: no failure result defined. - */ -static void mh_init_search_op(vfs_handle_struct *handle, - DIR *dirp) -{ - DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_init_search_op\n")); - SMB_VFS_NEXT_INIT_SEARCH_OP(handle, - ((mh_dirinfo_struct*)dirp)->dirstream); -} - /* * Success: return non-negative file descriptor * Failure: set errno, return -1 @@ -2321,7 +2309,6 @@ static struct vfs_fn_pointers vfs_mh_fns = { .mkdir_fn = mh_mkdir, .rmdir_fn = mh_rmdir, .closedir_fn = mh_closedir, - .init_search_op_fn = mh_init_search_op, /* File operations */ From bb40fa8445d650e6d840abe96b0143950da037ca Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:50:17 +0200 Subject: [PATCH 46/92] vfs_unityed_media: remove handling of init_search_op init_search_op is about to be removed from the VFS in a following commit. In the meantime, removing it poses no issue because he underlying impementation is a no-op. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/modules/vfs_unityed_media.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index 34881bc50b7..f55061afaec 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -846,15 +846,6 @@ static int um_closedir(vfs_handle_struct *handle, return SMB_VFS_NEXT_CLOSEDIR(handle, realdirp); } -static void um_init_search_op(vfs_handle_struct *handle, - DIR *dirp) -{ - DEBUG(10, ("Entering and leaving um_init_search_op\n")); - - SMB_VFS_NEXT_INIT_SEARCH_OP(handle, - ((um_dirinfo_struct*)dirp)->dirstream); -} - static int um_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, @@ -1908,7 +1899,6 @@ static struct vfs_fn_pointers vfs_um_fns = { .mkdir_fn = um_mkdir, .rmdir_fn = um_rmdir, .closedir_fn = um_closedir, - .init_search_op_fn = um_init_search_op, /* File operations */ From 37ac8ad4bf3122c369eec6f213bb8a62f8e92884 Mon Sep 17 00:00:00 2001 From: Uri Simchoni Date: Fri, 10 Nov 2017 21:53:58 +0200 Subject: [PATCH 47/92] vfs: remove SMB_VFS_INIT_SEARCH_OP This VFS is no longer being called, hence removed. Signed-off-by: Uri Simchoni Reviewed-by: Jeremy Allison --- source3/include/vfs.h | 6 ++---- source3/include/vfs_macros.h | 5 ----- source3/modules/vfs_default.c | 7 ------- source3/modules/vfs_full_audit.c | 11 ----------- source3/smbd/vfs.c | 7 ------- 5 files changed, 2 insertions(+), 34 deletions(-) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index d71d7cc4483..7372440d38a 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -244,8 +244,9 @@ /* Version 37 - Remove SMB_VFS_STRICT_UNLOCK */ /* Version 37 - Rename SMB_VFS_STRICT_LOCK to SMB_VFS_STRICT_LOCK_CHECK */ +/* Version 38 - Remove SMB_VFS_INIT_SEARCH_OP */ -#define SMB_VFS_INTERFACE_VERSION 37 +#define SMB_VFS_INTERFACE_VERSION 38 /* All intercepted VFS operations must be declared as static functions inside module source @@ -656,7 +657,6 @@ struct vfs_fn_pointers { int (*rmdir_fn)(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname); int (*closedir_fn)(struct vfs_handle_struct *handle, DIR *dir); - void (*init_search_op_fn)(struct vfs_handle_struct *handle, DIR *dirp); /* File operations */ @@ -1145,8 +1145,6 @@ int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname); int smb_vfs_call_closedir(struct vfs_handle_struct *handle, DIR *dir); -void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle, - DIR *dirp); int smb_vfs_call_open(struct vfs_handle_struct *handle, struct smb_filename *smb_fname, struct files_struct *fsp, int flags, mode_t mode); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 3cce1925ca1..dcf788e743b 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -124,11 +124,6 @@ #define SMB_VFS_NEXT_CLOSEDIR(handle, dir) \ smb_vfs_call_closedir((handle)->next, (dir)) -#define SMB_VFS_INIT_SEARCH_OP(conn, dirp) \ - smb_vfs_call_init_search_op((conn)->vfs_handles, (dirp)) -#define SMB_VFS_NEXT_INIT_SEARCH_OP(handle, dirp) \ - smb_vfs_call_init_search_op((handle)->next, (dirp)) - /* File operations */ #define SMB_VFS_OPEN(conn, fname, fsp, flags, mode) \ smb_vfs_call_open((conn)->vfs_handles, (fname), (fsp), (flags), (mode)) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 53d97859ec3..3379493accb 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -554,12 +554,6 @@ static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp) return result; } -static void vfswrap_init_search_op(vfs_handle_struct *handle, - DIR *dirp) -{ - /* Default behavior is a NOOP */ -} - /* File operations */ static int vfswrap_open(vfs_handle_struct *handle, @@ -3052,7 +3046,6 @@ static struct vfs_fn_pointers vfs_default_fns = { .mkdir_fn = vfswrap_mkdir, .rmdir_fn = vfswrap_rmdir, .closedir_fn = vfswrap_closedir, - .init_search_op_fn = vfswrap_init_search_op, /* File operations */ diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index a205007f46f..b8471593db7 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -110,7 +110,6 @@ typedef enum _vfs_op_type { SMB_VFS_OP_MKDIR, SMB_VFS_OP_RMDIR, SMB_VFS_OP_CLOSEDIR, - SMB_VFS_OP_INIT_SEARCH_OP, /* File operations */ @@ -256,7 +255,6 @@ static struct { { SMB_VFS_OP_MKDIR, "mkdir" }, { SMB_VFS_OP_RMDIR, "rmdir" }, { SMB_VFS_OP_CLOSEDIR, "closedir" }, - { SMB_VFS_OP_INIT_SEARCH_OP, "init_search_op" }, { SMB_VFS_OP_OPEN, "open" }, { SMB_VFS_OP_CREATE_FILE, "create_file" }, { SMB_VFS_OP_CLOSE, "close" }, @@ -930,14 +928,6 @@ static int smb_full_audit_closedir(vfs_handle_struct *handle, return result; } -static void smb_full_audit_init_search_op(vfs_handle_struct *handle, - DIR *dirp) -{ - SMB_VFS_NEXT_INIT_SEARCH_OP(handle, dirp); - - do_log(SMB_VFS_OP_INIT_SEARCH_OP, True, handle, ""); -} - static int smb_full_audit_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) @@ -2516,7 +2506,6 @@ static struct vfs_fn_pointers vfs_full_audit_fns = { .mkdir_fn = smb_full_audit_mkdir, .rmdir_fn = smb_full_audit_rmdir, .closedir_fn = smb_full_audit_closedir, - .init_search_op_fn = smb_full_audit_init_search_op, .open_fn = smb_full_audit_open, .create_file_fn = smb_full_audit_create_file, .close_fn = smb_full_audit_close, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index d4fccb7eda9..59702203612 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1685,13 +1685,6 @@ int smb_vfs_call_closedir(struct vfs_handle_struct *handle, return handle->fns->closedir_fn(handle, dir); } -void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle, - DIR *dirp) -{ - VFS_FIND(init_search_op); - handle->fns->init_search_op_fn(handle, dirp); -} - int smb_vfs_call_open(struct vfs_handle_struct *handle, struct smb_filename *smb_fname, struct files_struct *fsp, int flags, mode_t mode) From a0f6ea8dec1ab3d19bc93da12a9b0a1c0ccf6142 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Sep 2017 16:20:34 -0700 Subject: [PATCH 48/92] libsmbclient: Allow server (NetApp) to return STATUS_INVALID_PARAMETER from an echo. It does this if we send a session ID of zero. The server still replied. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13007 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Sat Nov 11 08:44:37 CET 2017 on sn-devel-144 --- source3/client/client.c | 8 +++++++- source3/libsmb/libsmb_server.c | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 8f449e81311..754907d2e09 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -6027,7 +6027,13 @@ static void readline_callback(void) /* Ping the server to keep the connection alive using SMBecho. */ memset(garbage, 0xf0, sizeof(garbage)); status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage))); - if (NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_OK(status) || + NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { + /* + * Even if server returns NT_STATUS_INVALID_PARAMETER + * it still responded. + * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13007 + */ return; } diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 93b9e800910..e6067be2013 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -61,7 +61,16 @@ SMBC_check_server(SMBCCTX * context, 1, data_blob_const(data, sizeof(data))); if (!NT_STATUS_IS_OK(status)) { - return 1; + /* + * Some NetApp servers return + * NT_STATUS_INVALID_PARAMETER.That's OK, they still + * replied. + * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13007 + */ + if (!NT_STATUS_EQUAL(status, + NT_STATUS_INVALID_PARAMETER)) { + return 1; + } } server->last_echo_time = now; } From 47c13fc10a2c9709e9511b2ffcf0e1004497887d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Nov 2017 12:48:15 -0800 Subject: [PATCH 49/92] s3: smbd: kernel oplocks. Replace retry_open() with setup_kernel_oplock_poll_open(). If a O_NONBLOCK open fails with EWOULDBLOCK, this code changes smbd to do a retry open every second, until either the timeout or we get a successful open. If we're opening a file that has a kernel lease set by a non-smbd process, this is the best we can do. Prior to this, smbd would block on the second open on such a leased file (not using O_NONBLOCK) which freezes active clients. Regression test to follow. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13121 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme --- source3/smbd/open.c | 96 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 89a267b0634..8c52f4bba56 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2410,19 +2410,40 @@ static void defer_open_done(struct tevent_req *req) } /** - * Reschedule an open for immediate execution + * Actually attempt the kernel oplock polling open. + */ + +static void kernel_oplock_poll_open_timer(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + bool ok; + struct smb_request *req = (struct smb_request *)private_data; + + ok = schedule_deferred_open_message_smb(req->xconn, req->mid); + if (!ok) { + exit_server("schedule_deferred_open_message_smb failed"); + } + DBG_DEBUG("kernel_oplock_poll_open_timer fired. Retying open !\n"); +} + +/** + * Reschedule an open for 1 second from now, if not timed out. **/ -static void retry_open(struct timeval request_time, +static void setup_kernel_oplock_poll_open(struct timeval request_time, struct smb_request *req, struct file_id id) { - struct deferred_open_record *open_rec = NULL; + bool ok; + struct deferred_open_record *open_rec = NULL; + /* Maximum wait time. */ + struct timeval timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); - DBG_DEBUG("request time [%s] mid [%" PRIu64 "] file_id [%s]\n", - timeval_string(talloc_tos(), &request_time, false), - req->mid, - file_id_string_tos(&id)); + if (request_timed_out(request_time, timeout)) { + return; + } open_rec = deferred_open_record_create(false, false, id); if (open_rec == NULL) { @@ -2431,17 +2452,30 @@ static void retry_open(struct timeval request_time, ok = push_deferred_open_message_smb(req, request_time, - timeval_set(0, 0), + timeout, id, open_rec); if (!ok) { exit_server("push_deferred_open_message_smb failed"); } - ok = schedule_deferred_open_message_smb(req->xconn, req->mid); - if (!ok) { - exit_server("schedule_deferred_open_message_smb failed"); + /* + * As this timer event is owned by req, it will + * disappear if req it talloc_freed. + */ + open_rec->te = tevent_add_timer(req->sconn->ev_ctx, + req, + timeval_current_ofs(1, 0), + kernel_oplock_poll_open_timer, + req); + if (open_rec->te == NULL) { + exit_server("tevent_add_timer failed"); } + + DBG_DEBUG("poll request time [%s] mid [%" PRIu64 "] file_id [%s]\n", + timeval_string(talloc_tos(), &request_time, false), + req->mid, + file_id_string_tos(&id)); } /**************************************************************************** @@ -3160,20 +3194,18 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, flags2 &= ~(O_CREAT|O_TRUNC); } - if (first_open_attempt && lp_kernel_oplocks(SNUM(conn))) { + if (lp_kernel_oplocks(SNUM(conn))) { /* * With kernel oplocks the open breaking an oplock * blocks until the oplock holder has given up the - * oplock or closed the file. We prevent this by first + * oplock or closed the file. We prevent this by always * trying to open the file with O_NONBLOCK (see "man - * fcntl" on Linux). For the second try, triggered by - * an oplock break response, we do not need this - * anymore. + * fcntl" on Linux). * - * This is true under the assumption that only Samba - * requests kernel oplocks. Once someone else like - * NFSv4 starts to use that API, we will have to - * modify this by communicating with the NFSv4 server. + * If a process that doesn't use the smbd open files + * database or communication methods holds a kernel + * oplock we must periodically poll for available open + * using O_NONBLOCK. */ flags2 |= O_NONBLOCK; } @@ -3252,9 +3284,16 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); if (lck == NULL) { - retry_open(request_time, req, fsp->file_id); - DEBUG(10, ("No share mode lock found after " - "EWOULDBLOCK, retrying sync\n")); + /* + * No oplock from Samba around. Set up a poll every 1 + * second to retry a non-blocking open until the time + * expires. + */ + setup_kernel_oplock_poll_open(request_time, + req, + fsp->file_id); + DBG_DEBUG("No Samba oplock around after EWOULDBLOCK. " + "Retrying with poll\n"); return NT_STATUS_SHARING_VIOLATION; } @@ -3275,14 +3314,15 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } /* - * No oplock from Samba around. Immediately retry with - * a blocking open. + * No oplock from Samba around. Set up a poll every 1 + * second to retry a non-blocking open until the time + * expires. */ - retry_open(request_time, req, fsp->file_id); + setup_kernel_oplock_poll_open(request_time, req, fsp->file_id); TALLOC_FREE(lck); - DEBUG(10, ("No Samba oplock around after EWOULDBLOCK. " - "Retrying sync\n")); + DBG_DEBUG("No Samba oplock around after EWOULDBLOCK. " + "Retrying with poll\n"); return NT_STATUS_SHARING_VIOLATION; } From ad82557e1355107920ae80fd6a0df0f16d1bdb6c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Nov 2017 09:59:23 -0800 Subject: [PATCH 50/92] s4: torture: kernel oplocks. Add smb2.kernel-oplocks.kernel_oplocks8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test if the server blocks whilst waiting on a kernel lease held by a non-smbd process. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13121 Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Sat Nov 11 20:12:26 CET 2017 on sn-devel-144 --- source3/selftest/tests.py | 2 +- source4/torture/smb2/oplock.c | 236 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 1 deletion(-) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 186b2235875..5b12355ac8e 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -508,7 +508,7 @@ def plansmbtorture4testsuite(name, env, options, description=''): plansmbtorture4testsuite(t, "simpleserver", '//$SERVER/dosmode -U$USERNAME%$PASSWORD') elif t == "smb2.kernel-oplocks": if have_linux_kernel_oplocks: - plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER/kernel_oplocks -U$USERNAME%$PASSWORD') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER/kernel_oplocks -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share') elif t == "smb2.notify-inotify": if have_inotify: plansmbtorture4testsuite(t, "fileserver", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c index 3290ed42d8c..1830a017e83 100644 --- a/source4/torture/smb2/oplock.c +++ b/source4/torture/smb2/oplock.c @@ -36,6 +36,8 @@ #include "torture/torture.h" #include "torture/smb2/proto.h" +#include "lib/util/sys_rw.h" + #define CHECK_RANGE(v, min, max) do { \ if ((v) < (min) || (v) > (max)) { \ torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \ @@ -4790,6 +4792,239 @@ static bool test_smb2_kernel_oplocks7(struct torture_context *tctx, return ret; } +#if HAVE_KERNEL_OPLOCKS_LINUX + +#ifndef F_SETLEASE +#define F_SETLEASE 1024 +#endif + +#ifndef RT_SIGNAL_LEASE +#define RT_SIGNAL_LEASE (SIGRTMIN+1) +#endif + +#ifndef F_SETSIG +#define F_SETSIG 10 +#endif + +static int got_break; + +/* + * Signal handler. + */ + +static void got_rt_break(int sig) +{ + got_break = 1; +} + +/* + * Child process function. + */ + +static int do_child_process(int pipefd, const char *name) +{ + int ret = 0; + int fd = -1; + char c = 0; + struct sigaction act; + + /* Set up a signal handler for RT_SIGNAL_LEASE. */ + ZERO_STRUCT(act); + act.sa_handler = got_rt_break; + ret = sigaction(RT_SIGNAL_LEASE, &act, NULL); + if (ret == -1) { + return 1; + } + /* Open the passed in file and get a kernel oplock. */ + fd = open(name, O_RDWR, 0666); + if (fd == -1) { + return 2; + } + + ret = fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE); + if (ret == -1) { + return 3; + } + + ret = fcntl(fd, F_SETLEASE, F_WRLCK); + if (ret == -1) { + return 4; + } + + /* Tell the parent we're ready. */ + ret = sys_write(pipefd, &c, 1); + if (ret != 1) { + return 5; + } + + /* Wait for RT_SIGNAL_LEASE. */ + ret = pause(); + if (ret != -1 || errno != EINTR) { + return 6; + } + + if (got_break != 1) { + return 7; + } + + /* Force the server to wait for 3 seconds. */ + sleep(3); + + /* Remove our lease. */ + ret = fcntl(fd, F_SETLEASE, F_UNLCK); + if (ret == -1) { + return 8; + } + + ret = close(fd); + if (ret == -1) { + return 9; + } + + /* All is well. */ + return 0; +} + +static bool wait_for_child_oplock(struct torture_context *tctx, + const char *localdir, + const char *fname) +{ + int fds[2]; + int ret; + pid_t pid; + char *name = talloc_asprintf(tctx, + "%s/%s", + localdir, + fname); + + torture_assert(tctx, name != NULL, "talloc failed"); + + ret = pipe(fds); + torture_assert(tctx, ret != -1, "pipe failed"); + + pid = fork(); + torture_assert(tctx, pid != (pid_t)-1, "fork failed"); + + if (pid != (pid_t)0) { + char c; + /* Parent. */ + TALLOC_FREE(name); + ret = sys_read(fds[0], &c, 1); + torture_assert(tctx, ret == 1, "read failed"); + return true; + } + + /* Child process. */ + ret = do_child_process(fds[1], name); + _exit(ret); + /* Notreached. */ +} +#else +static bool wait_for_child_oplock(struct torture_context *tctx, + const char *localdir, + const char *fname) +{ + return false; +} +#endif + +/* + * Deal with a non-smbd process holding a kernel oplock. + */ + +static bool test_smb2_kernel_oplocks8(struct torture_context *tctx, + struct smb2_tree *tree) +{ + const char *fname = "test_kernel_oplock8.dat"; + const char *fname1 = "tmp_test_kernel_oplock8.dat"; + NTSTATUS status; + bool ret = true; + struct smb2_create io; + struct smb2_request *req = NULL; + struct smb2_handle h1 = {{0}}; + struct smb2_handle h2 = {{0}}; + const char *localdir = torture_setting_string(tctx, "localdir", NULL); + time_t start; + time_t end; + +#ifndef HAVE_KERNEL_OPLOCKS_LINUX + torture_skip(tctx, "Need kernel oplocks for test"); +#endif + + if (localdir == NULL) { + torture_skip(tctx, "Need localdir for test"); + } + + smb2_util_unlink(tree, fname); + smb2_util_unlink(tree, fname1); + status = torture_smb2_testfile(tree, fname, &h1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error creating testfile\n"); + smb2_util_close(tree, h1); + ZERO_STRUCT(h1); + + /* Take the oplock locally in a sub-process. */ + ret = wait_for_child_oplock(tctx, localdir, fname); + torture_assert_goto(tctx, ret = true, ret, done, + "Wait for child process failed.\n"); + + /* + * Now try and open. This should block for 3 seconds. + * while the child process is still alive. + */ + + ZERO_STRUCT(io); + io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; + io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + io.in.create_disposition = NTCREATEX_DISP_OPEN; + io.in.share_access = + NTCREATEX_SHARE_ACCESS_DELETE| + NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE; + io.in.create_options = 0; + io.in.fname = fname; + + req = smb2_create_send(tree, &io); + torture_assert(tctx, req != NULL, "smb2_create_send"); + + /* Ensure while the open is blocked the smbd is + still serving other requests. */ + io.in.fname = fname1; + io.in.create_disposition = NTCREATEX_DISP_CREATE; + + /* Time the start -> end of the request. */ + start = time(NULL); + status = smb2_create(tree, tctx, &io); + end = time(NULL); + + /* Should succeed. */ + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error opening the second file\n"); + h1 = io.out.file.handle; + + /* in less than 2 seconds. Otherwise the server blocks. */ + torture_assert(tctx, end - start < 2, "server was blocked !"); + + /* Pick up the return for the initial blocking open. */ + status = smb2_create_recv(req, tctx, &io); + + /* Which should also have succeeded. */ + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Error opening the file\n"); + h2 = io.out.file.handle; + +done: + if (!smb2_util_handle_empty(h1)) { + smb2_util_close(tree, h1); + } + if (!smb2_util_handle_empty(h2)) { + smb2_util_close(tree, h2); + } + smb2_util_unlink(tree, fname); + smb2_util_unlink(tree, fname1); + return ret; +} + struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -4802,6 +5037,7 @@ struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5); torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6); torture_suite_add_2smb2_test(suite, "kernel_oplocks7", test_smb2_kernel_oplocks7); + torture_suite_add_1smb2_test(suite, "kernel_oplocks8", test_smb2_kernel_oplocks8); suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests"); From 3c0b52dd37700537638e1825e5d850b2d36017c5 Mon Sep 17 00:00:00 2001 From: Fabian Fritz Date: Tue, 7 Nov 2017 22:45:23 +0100 Subject: [PATCH 51/92] Fix #12961 Signed-off-by: Fabian Fritz --- lib/ldb/tests/ldb_mod_op_test.c | 8 ++++---- lib/replace/wscript | 6 +++++- source3/wscript_build | 1 + third_party/cmocka/cmocka.h | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c index 48ad20c7662..1b0baee3038 100644 --- a/lib/ldb/tests/ldb_mod_op_test.c +++ b/lib/ldb/tests/ldb_mod_op_test.c @@ -1914,22 +1914,22 @@ static void test_ldb_modify_during_search(void **state, bool add_index, static void test_ldb_modify_during_indexed_search(void **state) { - return test_ldb_modify_during_search(state, true, false); + test_ldb_modify_during_search(state, true, false); } static void test_ldb_modify_during_unindexed_search(void **state) { - return test_ldb_modify_during_search(state, false, false); + test_ldb_modify_during_search(state, false, false); } static void test_ldb_rename_during_indexed_search(void **state) { - return test_ldb_modify_during_search(state, true, true); + test_ldb_modify_during_search(state, true, true); } static void test_ldb_rename_during_unindexed_search(void **state) { - return test_ldb_modify_during_search(state, false, true); + test_ldb_modify_during_search(state, false, true); } /* diff --git a/lib/replace/wscript b/lib/replace/wscript index 7436a90c003..548ead737f5 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -81,6 +81,8 @@ def configure(conf): conf.CHECK_HEADERS('sys/atomic.h') conf.CHECK_HEADERS('libgen.h') + if conf.CHECK_CFLAGS('-Wno-format-zero-length'): + conf.define('HAVE_WNO_FORMAT_ZERO_LENGTH', '1') if conf.CHECK_CFLAGS('-Wno-format-truncation'): conf.define('HAVE_WNO_FORMAT_TRUNCATION', '1') @@ -734,7 +736,9 @@ def build(bld): private_library=True, deps='crypt dl nsl socket rt attr' + extra_libs) - replace_test_cflags="-Wno-format-zero-length" + replace_test_cflags = "" + if bld.CONFIG_SET('HAVE_WNO_FORMAT_ZERO_LENGTH'): + replace_test_cflags += "-Wno-format-zero-length" if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): replace_test_cflags += " -Wno-format-truncation" bld.SAMBA_SUBSYSTEM('replace-test', diff --git a/source3/wscript_build b/source3/wscript_build index dc7a51cc97a..037ceeab910 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -569,6 +569,7 @@ bld.SAMBA3_SUBSYSTEM('SMBCONF_PARAM', PARAM_UTIL ldap lber + krb5 LOADPARM_CTX samba3core param_local.h diff --git a/third_party/cmocka/cmocka.h b/third_party/cmocka/cmocka.h index 72d6ae21c90..440686f3b3f 100644 --- a/third_party/cmocka/cmocka.h +++ b/third_party/cmocka/cmocka.h @@ -56,7 +56,7 @@ int __stdcall IsDebuggerPresent(); /* If __WORDSIZE is not set, try to figure it out and default to 32 bit. */ #ifndef __WORDSIZE -# if defined(__x86_64__) && !defined(__ILP32__) +# if (defined(__x86_64__) || defined(_LP64)) && !defined(__ILP32__) # define __WORDSIZE 64 # else # define __WORDSIZE 32 From 142f778c73158b71869fb7051a03d9afad91e77b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 2 Nov 2017 21:48:21 +0100 Subject: [PATCH 52/92] vfs_fruit: Unlink memory on error Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme --- source3/modules/vfs_fruit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 78170e7abdd..15e42fb4dfd 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1078,6 +1078,7 @@ static int ad_convert(struct adouble *ad, ok = ad_convert_xattr(ad, smb_fname, map); if (!ok) { + munmap(map, origlen); return -1; } From f56ce215c7fc957f5e24f015343366239c7fe900 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 2 Nov 2017 21:49:43 +0100 Subject: [PATCH 53/92] s3:passdb: Fix a memory leak in secrets_fetch_or_upgrade_domain_info() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Mon Nov 13 14:05:46 CET 2017 on sn-devel-144 --- source3/passdb/machine_account_secrets.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index 75f31cb04e2..40511f96a8b 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -1476,6 +1476,7 @@ NTSTATUS secrets_fetch_or_upgrade_domain_info(const char *domain, DBG_ERR("secrets_domain_info_password_create(pw) failed " "for %s - %s\n", domain, nt_errstr(status)); dbwrap_transaction_cancel(db); + SAFE_FREE(old_pw); TALLOC_FREE(frame); return status; } From 2e573eead96b2e98dd8a15c9c8e470679e530392 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Nov 2017 11:05:04 +0100 Subject: [PATCH 54/92] tevent: version 0.9.34 * Remove unused select backend * Fix a race condition in tevent_threaded_schedule_immediate() (bug #13130) Signed-off-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Mon Nov 13 18:02:46 CET 2017 on sn-devel-144 --- lib/tevent/ABI/tevent-0.9.34.sigs | 99 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.34.sigs diff --git a/lib/tevent/ABI/tevent-0.9.34.sigs b/lib/tevent/ABI/tevent-0.9.34.sigs new file mode 100644 index 00000000000..7a6a23689a4 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.34.sigs @@ -0,0 +1,99 @@ +_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *) +_tevent_loop_once: int (struct tevent_context *, const char *) +_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *) +_tevent_loop_wait: int (struct tevent_context *, const char *) +_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *) +_tevent_req_callback_data: void *(struct tevent_req *) +_tevent_req_cancel: bool (struct tevent_req *, const char *) +_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *) +_tevent_req_data: void *(struct tevent_req *) +_tevent_req_done: void (struct tevent_req *, const char *) +_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *) +_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *) +_tevent_req_notify_callback: void (struct tevent_req *, const char *) +_tevent_req_oom: void (struct tevent_req *, const char *) +_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *) +tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_check_signal: int (struct tevent_context *) +tevent_common_context_destructor: int (struct tevent_context *) +tevent_common_fd_destructor: int (struct tevent_fd *) +tevent_common_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_common_have_events: bool (struct tevent_context *) +tevent_common_loop_immediate: bool (struct tevent_context *) +tevent_common_loop_timer_delay: struct timeval (struct tevent_context *) +tevent_common_loop_wait: int (struct tevent_context *, const char *) +tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +tevent_context_init: struct tevent_context *(TALLOC_CTX *) +tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *) +tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_set_auto_close: void (struct tevent_fd *) +tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (void) +tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_length: size_t (struct tevent_queue *) +tevent_queue_running: bool (struct tevent_queue *) +tevent_queue_start: void (struct tevent_queue *) +tevent_queue_stop: void (struct tevent_queue *) +tevent_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *) +tevent_re_initialise: int (struct tevent_context *) +tevent_register_backend: bool (const char *, const struct tevent_ops *) +tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *) +tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *) +tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *) +tevent_req_is_in_progress: bool (struct tevent_req *) +tevent_req_poll: bool (struct tevent_req *, struct tevent_context *) +tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *) +tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: void (struct tevent_req *) +tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *) +tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn) +tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn) +tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +tevent_sa_info_queue_count: size_t (void) +tevent_set_abort_fn: void (void (*)(const char *)) +tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *) +tevent_set_debug_stderr: int (struct tevent_context *) +tevent_set_default_backend: void (const char *) +tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t) +tevent_timeval_compare: int (const struct timeval *, const struct timeval *) +tevent_timeval_current: struct timeval (void) +tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t) +tevent_timeval_is_zero: bool (const struct timeval *) +tevent_timeval_set: struct timeval (uint32_t, uint32_t) +tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *) +tevent_timeval_zero: struct timeval (void) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index 91880738f90..31f7ee7c0cc 100644 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.33' +VERSION = '0.9.34' blddir = 'bin' From fe4e24e143c28fd98faaac97ef6bc56180f0ecc7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Aug 2017 17:03:26 +0200 Subject: [PATCH 55/92] netsamlogon_cache: Use ndr_pull_struct_blob_all Be a bit more strict for error checking Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/samlogon_cache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 0a2890e4231..70645f2dc40 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -253,8 +253,9 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct do blob = data_blob_const(data.dptr, data.dsize); - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, - (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry); + ndr_err = ndr_pull_struct_blob_all( + &blob, mem_ctx, &r, + (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n")); From b0e2c669e14c83cbd198c5ea4bee94e276402c9f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Nov 2017 08:53:04 +0100 Subject: [PATCH 56/92] libcli: Fix a signed/unsigned hickup Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- libcli/security/util_sid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcli/security/util_sid.c b/libcli/security/util_sid.c index 0709a7a69e3..50133a14075 100644 --- a/libcli/security/util_sid.c +++ b/libcli/security/util_sid.c @@ -195,7 +195,7 @@ static const struct { const char *sid_type_lookup(uint32_t sid_type) { - int i; + size_t i; /* Look through list */ for (i=0; i < ARRAY_SIZE(sid_name_type); i++) { From 3c5027556aece81942bc8dc3baed25cd8d869653 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 4 Aug 2017 14:47:17 +0200 Subject: [PATCH 57/92] passdb: Fix a typo Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- 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 b06dd1b6f72..eeaf2b720a7 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -178,7 +178,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* * Finally check for a well known domain name ("NT Authority"), - * this is taken care if in lookup_wellknown_name(). + * this is being taken care of in lookup_wellknown_name(). */ if ((domain[0] != '\0') && (flags & LOOKUP_NAME_WKN) && From cd5d726c89466b4e5af11d02d98ad8be7af936da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 3 Aug 2017 17:08:48 +0200 Subject: [PATCH 58/92] util_tdb: Make a few functions static Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- lib/util/util_tdb.c | 11 +++++++---- lib/util/util_tdb.h | 24 ------------------------ 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c index e3eefdac2b1..24fb6584899 100644 --- a/lib/util/util_tdb.c +++ b/lib/util/util_tdb.c @@ -132,7 +132,7 @@ void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval) Output is int32_t in native byte order. ****************************************************************************/ -int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key) +static int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key) { TDB_DATA data; int32_t ret; @@ -163,7 +163,8 @@ int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr) Input is int32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32_byblob(struct tdb_context *tdb, TDB_DATA key, int32_t v) +static int tdb_store_int32_byblob(struct tdb_context *tdb, TDB_DATA key, + int32_t v) { TDB_DATA data; int32_t v_store; @@ -190,7 +191,8 @@ int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v) Output is uint32_t in native byte order. ****************************************************************************/ -bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t *value) +static bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, + uint32_t *value) { TDB_DATA data; @@ -220,7 +222,8 @@ bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *val Input is uint32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -bool tdb_store_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t value) +static bool tdb_store_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, + uint32_t value) { TDB_DATA data; uint32_t v_store; diff --git a/lib/util/util_tdb.h b/lib/util/util_tdb.h index 63d80d1fb58..de82660f6ea 100644 --- a/lib/util/util_tdb.h +++ b/lib/util/util_tdb.h @@ -54,48 +54,24 @@ int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval); ****************************************************************************/ void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval); -/**************************************************************************** - Fetch a int32_t value by a arbitrary blob key, return -1 if not found. - Output is int32_t in native byte order. -****************************************************************************/ -int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key); - /**************************************************************************** Fetch a int32_t value by string key, return -1 if not found. Output is int32_t in native byte order. ****************************************************************************/ int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr); -/**************************************************************************** - Store a int32_t value by an arbitrary blob key, return 0 on success, -ve on failure. - Input is int32_t in native byte order. Output in tdb is in little-endian. -****************************************************************************/ -int tdb_store_int32_byblob(struct tdb_context *tdb, TDB_DATA key, int32_t v); - /**************************************************************************** Store a int32_t value by string key, return 0 on success, -ve on failure. Input is int32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v); -/**************************************************************************** - Fetch a uint32_t value by a arbitrary blob key, return -1 if not found. - Output is uint32_t in native byte order. -****************************************************************************/ -bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t *value); - /**************************************************************************** Fetch a uint32_t value by string key, return -1 if not found. Output is uint32_t in native byte order. ****************************************************************************/ bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value); -/**************************************************************************** - Store a uint32_t value by an arbitrary blob key, return true on success, false on failure. - Input is uint32_t in native byte order. Output in tdb is in little-endian. -****************************************************************************/ -bool tdb_store_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t value); - /**************************************************************************** Store a uint32_t value by string key, return true on success, false on failure. Input is uint32_t in native byte order. Output in tdb is in little-endian. From 1f071b1a25b33d5667acd6d4185de2a4b6826b2d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 4 Aug 2017 10:44:59 +0200 Subject: [PATCH 59/92] smbd: Avoid an "else" We always return in the if-branch before. The else is redundant Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/smbd/process.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b65ae2c1b1c..11a5ae8314c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1973,7 +1973,8 @@ static void process_smb(struct smbXsrv_connection *xconn, size_t pdulen = nread - NBT_HDR_SIZE; smbd_smb2_process_negprot(xconn, 0, inpdu, pdulen); return; - } else if (nread >= smb_size && valid_smb_header(inbuf) + } + if (nread >= smb_size && valid_smb_header(inbuf) && CVAL(inbuf, smb_com) != 0x72) { /* This is a non-negprot SMB1 packet. Disable SMB2 from now on. */ From 1c6e2704fb8f97ab8658df6354e9b5dc1e7b1b96 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Nov 2017 14:48:24 +0100 Subject: [PATCH 60/92] lib: Avoid a ZERO_STRUCT, save a few bytes .text Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libnet/libnet_dssync.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source3/libnet/libnet_dssync.c b/source3/libnet/libnet_dssync.c index 267709e3c11..e593ae8536c 100644 --- a/source3/libnet/libnet_dssync.c +++ b/source3/libnet/libnet_dssync.c @@ -337,7 +337,6 @@ static NTSTATUS libnet_dssync_build_request(TALLOC_CTX *mem_ctx, uint32_t count; uint32_t level; union drsuapi_DsGetNCChangesRequest req; - struct dom_sid null_sid; enum drsuapi_DsExtendedOperation extended_op; struct drsuapi_DsReplicaObjectIdentifier *nc = NULL; struct drsuapi_DsReplicaCursorCtrEx *cursors = NULL; @@ -348,7 +347,6 @@ static NTSTATUS libnet_dssync_build_request(TALLOC_CTX *mem_ctx, DRSUAPI_DRS_GET_ANC | DRSUAPI_DRS_NEVER_SYNCED; - ZERO_STRUCT(null_sid); ZERO_STRUCT(req); if (ctx->remote_info28.supported_extensions @@ -366,7 +364,7 @@ static NTSTATUS libnet_dssync_build_request(TALLOC_CTX *mem_ctx, } nc->dn = dn; nc->guid = GUID_zero(); - nc->sid = null_sid; + nc->sid = (struct dom_sid) {0}; if (!ctx->single_object_replication && !ctx->force_full_replication && utdv) From 3b2ba9c884931808cc1870dbad5d072366b16d2a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Nov 2017 14:48:24 +0100 Subject: [PATCH 61/92] rpcclient: Avoid a ZERO_STRUCT, save a few bytes .text Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/rpcclient/cmd_drsuapi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source3/rpcclient/cmd_drsuapi.c b/source3/rpcclient/cmd_drsuapi.c index 6a1fac7bfad..b2221a713dd 100644 --- a/source3/rpcclient/cmd_drsuapi.c +++ b/source3/rpcclient/cmd_drsuapi.c @@ -328,7 +328,6 @@ static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli, union drsuapi_DsGetNCChangesRequest req; union drsuapi_DsGetNCChangesCtr ctr; struct drsuapi_DsReplicaObjectIdentifier nc; - struct dom_sid null_sid; struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL; struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL; @@ -362,7 +361,6 @@ static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli, ZERO_STRUCT(info28); - ZERO_STRUCT(null_sid); ZERO_STRUCT(req); GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); @@ -463,7 +461,7 @@ static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli, nc.dn = nc_dn; nc.guid = GUID_zero(); - nc.sid = null_sid; + nc.sid = (struct dom_sid) {0}; if (supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) { level = 8; From 01a54627a09d1c0d32aba3faf1b114a46f1e5bff Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Nov 2017 14:55:40 +0100 Subject: [PATCH 62/92] lib: Save a few bytes of .text Looks surprising, but this does save bytes if you look at the object with "size". Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- libcli/security/util_sid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcli/security/util_sid.c b/libcli/security/util_sid.c index 50133a14075..e84cfb48265 100644 --- a/libcli/security/util_sid.c +++ b/libcli/security/util_sid.c @@ -431,6 +431,6 @@ bool add_rid_to_array_unique(TALLOC_CTX *mem_ctx, bool is_null_sid(const struct dom_sid *sid) { - static const struct dom_sid null_sid = {0}; + const struct dom_sid null_sid = {0}; return dom_sid_equal(sid, &null_sid); } From a1b2daa06f85772fd23b59b24c838b6f699dce89 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Nov 2017 16:07:48 +0100 Subject: [PATCH 63/92] dreplsrv: Use is_null_sid Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source4/dsdb/repl/drepl_partitions.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source4/dsdb/repl/drepl_partitions.c b/source4/dsdb/repl/drepl_partitions.c index 586da1983dc..83ea3586415 100644 --- a/source4/dsdb/repl/drepl_partitions.c +++ b/source4/dsdb/repl/drepl_partitions.c @@ -445,12 +445,10 @@ WERROR dreplsrv_partition_find_for_nc(struct dreplsrv_service *s, { struct dreplsrv_partition *p; bool valid_sid, valid_guid; - struct dom_sid null_sid; - ZERO_STRUCT(null_sid); SMB_ASSERT(_p); - valid_sid = nc_sid && !dom_sid_equal(&null_sid, nc_sid); + valid_sid = nc_sid && !is_null_sid(nc_sid); valid_guid = nc_guid && !GUID_all_zero(nc_guid); if (!valid_sid && !valid_guid && (!nc_dn_str)) { From 2e5ea35f0b6c114581a8434a8b8824d17b353062 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Nov 2017 16:09:35 +0100 Subject: [PATCH 64/92] smbtorture: Remove an unused variable Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Nov 14 03:55:37 CET 2017 on sn-devel-144 --- source4/torture/drs/rpc/dssync.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source4/torture/drs/rpc/dssync.c b/source4/torture/drs/rpc/dssync.c index 27cc72f5613..67fde7c2b61 100644 --- a/source4/torture/drs/rpc/dssync.c +++ b/source4/torture/drs/rpc/dssync.c @@ -935,11 +935,9 @@ static bool test_FetchNT4Data(struct torture_context *tctx, union drsuapi_DsGetNT4ChangeLogInfo info; uint32_t level_out = 0; struct GUID null_guid; - struct dom_sid null_sid; DATA_BLOB cookie; ZERO_STRUCT(null_guid); - ZERO_STRUCT(null_sid); ZERO_STRUCT(cookie); ZERO_STRUCT(r); From 700560924fe8188dd2ef449820a80c4bec6ec331 Mon Sep 17 00:00:00 2001 From: ulkuderner Date: Tue, 1 Aug 2017 12:01:22 +0300 Subject: [PATCH 65/92] pam_winbind: initial Turkish translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Bjoern Jacke Reviewed-by: Karolin Seeger Autobuild-User(master): Björn Jacke Autobuild-Date(master): Wed Nov 15 13:52:05 CET 2017 on sn-devel-144 --- source3/locale/pam_winbind/tr.po | 548 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 548 insertions(+) create mode 100644 source3/locale/pam_winbind/tr.po diff --git a/source3/locale/pam_winbind/tr.po b/source3/locale/pam_winbind/tr.po new file mode 100644 index 00000000000..ae3d3137167 --- /dev/null +++ b/source3/locale/pam_winbind/tr.po @@ -0,0 +1,548 @@ +# This file is distributed under the same license as the pam_winbind package. +# +# Copyright (C) 2009 Lars Mueller +# Copyright (C) 2010 Christian Perrier +msgid "" +msgstr "" +"Project-Id-Version: pam_winbind\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-03-06 01:55+0800\n" +"PO-Revision-Date: 2017-07-02 15:23+0300\n" +"Last-Translator: Caglar Ulkuderner \n" +"Language-Team: French \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Language: tr\n" + +#: ../../../nsswitch/pam_winbind.c:583 ../../libsmb/nterr.c:558 +msgid "Success" +msgstr "Başarılı" + +#: ../../../nsswitch/pam_winbind.c:585 +msgid "No primary Domain Controler available" +msgstr "Birincil Etki Alanı Denetleyicisi bulunamadı." + +#: ../../../nsswitch/pam_winbind.c:587 +msgid "No domain controllers found" +msgstr "Hiçbir etki alanı denetleyicileri bulunamadı." + +#: ../../../nsswitch/pam_winbind.c:589 ../../libsmb/nterr.c:566 +msgid "No logon servers" +msgstr "Hiçbir oturum açma sunucusu bulunamadı." + +#: ../../../nsswitch/pam_winbind.c:591 +msgid "Password too short" +msgstr "Parola çok kısa." + +#: ../../../nsswitch/pam_winbind.c:593 +msgid "The password of this user is too recent to change" +msgstr "Kullanıcının parolası değiştirmek için çok yeni." + +#: ../../../nsswitch/pam_winbind.c:595 +msgid "Password is already in password history" +msgstr "Girilen parola, parola geçmişinde mevcut." + +#: ../../../nsswitch/pam_winbind.c:597 +msgid "Your password has expired" +msgstr "Parolanızın süresi dolmuş." + +#: ../../../nsswitch/pam_winbind.c:599 +msgid "You need to change your password now" +msgstr "Parolanızı değiştirmeniz gerekiyor." + +#: ../../../nsswitch/pam_winbind.c:601 +msgid "You are not allowed to logon from this workstation" +msgstr "Bu iş istasyonunda oturum açmanıza izin verilmiyor." + +#: ../../../nsswitch/pam_winbind.c:603 +msgid "You are not allowed to logon at this time" +msgstr "Bu saatte oturum açmanıza izin verilmiyor." + +#: ../../../nsswitch/pam_winbind.c:605 +msgid "Your account has expired. Please contact your System administrator" +msgstr "Hesabınızın süresi dolmuş. Sistem yöneticinize başvurunuz." + +#: ../../../nsswitch/pam_winbind.c:608 +msgid "Your account is disabled. Please contact your System administrator" +msgstr "Hesabınız devre dışı bırakılmış. Sistem yöneticinize başvurunuz." + +#: ../../../nsswitch/pam_winbind.c:611 +msgid "Your account has been locked. Please contact your System administrator" +msgstr "Hesabınız kilitlenmiş. Sistem yöneticinize başvurunuz." + +#: ../../../nsswitch/pam_winbind.c:614 ../../../nsswitch/pam_winbind.c:616 +#: ../../../nsswitch/pam_winbind.c:618 +msgid "Invalid Trust Account" +msgstr "Geçersiz Güven Hesabı." + +#: ../../../nsswitch/pam_winbind.c:620 +msgid "Access is denied" +msgstr "Erişim engellendi." + +#: ../../../nsswitch/pam_winbind.c:818 +msgid "Do you want to change your password now?" +msgstr "Parolanızı şimdi değiştirmek istiyor musunuz?" + +#: ../../../nsswitch/pam_winbind.c:902 +msgid "Your password expires today.\n" +msgstr "Parolanızın süresi bugün sona eriyor.\n" + +#: ../../../nsswitch/pam_winbind.c:932 +#, c-format +msgid "Your password will expire in %d %s.\n" +msgstr "Parolanız %d %s içerisinde geçersiz olacak.\n" + +#: ../../../nsswitch/pam_winbind.c:933 +msgid "days" +msgstr "gün" + +#: ../../../nsswitch/pam_winbind.c:933 +msgid "day" +msgstr "gün" + +#: ../../../nsswitch/pam_winbind.c:1169 ../../../nsswitch/pam_winbind.c:1193 +#, c-format +msgid "Cannot convert group %s to sid, please contact your administrator to see if group %s is valid." +msgstr "%s grubu, sid türüne dönüştürülemiyor, yöneticiniz ile başlantı kurup %s grubunun geçerliliğini kontrol ediniz." + +#: ../../../nsswitch/pam_winbind.c:1387 +msgid "Grace login. Please change your password as soon you're online again" +msgstr "Çevrimiçi olduğunuz en kısa süre içerisinde parolanızı değiştiriniz." + +#: ../../../nsswitch/pam_winbind.c:1397 +msgid "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable" +msgstr "Etki Alanı Denetleyicisine ulaşılamadığı için kimlik bilgileri önbellekten kullanılıyor. Ağ kaynakları kullanılamıyor olabilir." + +#: ../../../nsswitch/pam_winbind.c:1422 +msgid "" +"Failed to establish your Kerberos Ticket cache due time differences\n" +"with the domain controller. Please verify the system time.\n" +msgstr "" +"Etki Alanı Denetleyicisi ile aradaki zaman farkından dolayı\n" +"Kerberos Bileti Önbelleği oluşturulamıyor. Sistem zamanını kontrol ediniz.\n" + +#: ../../../nsswitch/pam_winbind.c:1490 +msgid "Your password " +msgstr "Parolanız " + +#: ../../../nsswitch/pam_winbind.c:1497 +#, c-format +msgid "must be at least %d characters; " +msgstr "en az %d karakter olmalıdır; " + +#: ../../../nsswitch/pam_winbind.c:1506 +#, c-format +msgid "cannot repeat any of your previous %d passwords; " +msgstr "Son %d parola tekrar edilemez; " + +#: ../../../nsswitch/pam_winbind.c:1516 +msgid "must contain capitals, numerals or punctuation; and cannot contain your account or full name; " +msgstr "büyük harfler, sayılar ve noktalama işaretleri içermelidir; ve tam hesap adınızı içeremez;" + +#: ../../../nsswitch/pam_winbind.c:1526 +msgid "Please type a different password. Type a password which meets these requirements in both text boxes." +msgstr "Başka bir parola giriniz. Her iki kutucuğa da parola kriterlerine uygun parolanızı giriniz." + +#: ../../../nsswitch/pam_winbind.c:1553 +#, c-format +msgid "Creating directory: %s failed: %s" +msgstr "Klasör oluşturuluyor: %s başarısız: %s" + +#: ../../../nsswitch/pam_winbind.c:2018 +msgid "Password does not meet complexity requirements" +msgstr "Parola karmaşıklık gereksinimlerini karşılamıyor." + +#. +#. * First get the name of a user +#. +#: ../../../nsswitch/pam_winbind.c:2489 ../../../nsswitch/pam_winbind.c:3035 +msgid "Username: " +msgstr "Kullanıcı Adı: " + +#: ../../../nsswitch/pam_winbind.c:2665 +msgid "Password: " +msgstr "Parola: " + +#. instruct user what is happening +#: ../../../nsswitch/pam_winbind.c:3073 +msgid "Changing password for" +msgstr "Parolası değiştirilen kullanıcı: " + +#: ../../../nsswitch/pam_winbind.c:3086 +msgid "(current) NT password: " +msgstr "(geçerli) Parola: " + +#: ../../../nsswitch/pam_winbind.c:3156 +msgid "Enter new NT password: " +msgstr "Yeni parola: " + +#: ../../../nsswitch/pam_winbind.c:3157 +msgid "Retype new NT password: " +msgstr "Yeni parola (tekrar): " + +#. +#. * here is the string to inform the user that the new passwords they +#. * typed were not the same. +#. +#: ../../../nsswitch/pam_winbind.h:128 +msgid "Sorry, passwords do not match" +msgstr "Parolalar uyuşmuyor" + +#: ../../libsmb/nterr.c:559 +msgid "Undetermined error" +msgstr "Belirsiz hata" + +#: ../../libsmb/nterr.c:560 +msgid "Access denied" +msgstr "Erişim engellendi" + +#: ../../libsmb/nterr.c:561 +msgid "Account locked out" +msgstr "Hesap kilitlendi" + +#: ../../libsmb/nterr.c:562 +msgid "Must change password" +msgstr "Parola değiştirilmelidir" + +#: ../../libsmb/nterr.c:563 +msgid "Password is too short" +msgstr "Parola çok kısa" + +#: ../../libsmb/nterr.c:564 +msgid "Password is too recent" +msgstr "Parola çok yeni" + +#: ../../libsmb/nterr.c:565 +msgid "Password history conflict" +msgstr "Parola geçmişi çakışması" + +#: ../../libsmb/nterr.c:567 +msgid "Improperly formed account name" +msgstr "Yanlış oluşturulmuş hesap adı" + +#: ../../libsmb/nterr.c:568 +msgid "User exists" +msgstr "Kullanıcı mevcut" + +#: ../../libsmb/nterr.c:569 +msgid "No such user" +msgstr "Kullanıcı bulunamadı" + +#: ../../libsmb/nterr.c:570 +msgid "Group exists" +msgstr "Grup mevcut" + +#: ../../libsmb/nterr.c:571 +msgid "No such group" +msgstr "Grup bulunamadı" + +#: ../../libsmb/nterr.c:572 +msgid "Member not in group" +msgstr "Üye bu grupta değil" + +#: ../../libsmb/nterr.c:573 +msgid "Wrong Password" +msgstr "Yanlış Parola" + +#: ../../libsmb/nterr.c:574 +msgid "Ill formed password" +msgstr "Kötü parola" + +#: ../../libsmb/nterr.c:575 +msgid "Password restriction" +msgstr "Parola kısıtlaması" + +#: ../../libsmb/nterr.c:576 +msgid "Logon failure" +msgstr "Oturum açma hatası" + +#: ../../libsmb/nterr.c:577 +msgid "Account restriction" +msgstr "Hesap kısıtlaması" + +#: ../../libsmb/nterr.c:578 +msgid "Invalid logon hours" +msgstr "Geçersiz oturum açma saati" + +#: ../../libsmb/nterr.c:579 +msgid "Invalid workstation" +msgstr "Geçersiz Çalışma İstasyonu" + +#: ../../libsmb/nterr.c:580 +msgid "Password expired" +msgstr "Parolanın süresi doldu" + +#: ../../libsmb/nterr.c:581 +msgid "Account disabled" +msgstr "Hesap devre dışı" + +#: ../../libsmb/nterr.c:582 +msgid "Memory allocation error" +msgstr "Bellek ayarlama hatası" + +#: ../../libsmb/nterr.c:583 +msgid "No domain controllers located" +msgstr "Hiçbir Etki Alanı Denetleyicisi bulunamadı" + +#: ../../libsmb/nterr.c:584 +msgid "Named pipe not available" +msgstr "Named pipe uygun değil" + +#: ../../libsmb/nterr.c:585 +msgid "Not implemented" +msgstr "Henüz geliştirilmedi" + +#: ../../libsmb/nterr.c:586 +msgid "Invalid information class" +msgstr "Geçersiz bilgi sınıfı" + +#: ../../libsmb/nterr.c:587 +msgid "Information length mismatch" +msgstr "Bilgi uzunluğu uyumsuz" + +#: ../../libsmb/nterr.c:588 +msgid "Access violation" +msgstr "Erişim ihlali" + +#: ../../libsmb/nterr.c:589 +msgid "Invalid handle" +msgstr "Geçersiz yönetim" + +#: ../../libsmb/nterr.c:590 +msgid "Invalid parameter" +msgstr "Geçersiz parametre" + +#: ../../libsmb/nterr.c:591 +msgid "No memory" +msgstr "Bellek yok" + +#: ../../libsmb/nterr.c:592 +msgid "Buffer too small" +msgstr "Tampon bölge çok küçük" + +#: ../../libsmb/nterr.c:593 +msgid "Revision mismatch" +msgstr "Revizyon uyumsuzluğu" + +#: ../../libsmb/nterr.c:594 +msgid "No such logon session" +msgstr "Böyle bir oturum yok" + +#: ../../libsmb/nterr.c:595 +msgid "No such privilege" +msgstr "Böyle bir yetki yok" + +#: ../../libsmb/nterr.c:596 +msgid "Procedure not found" +msgstr "Prosedür bulunamadı" + +#: ../../libsmb/nterr.c:597 +msgid "Server disabled" +msgstr "Sunucu devre dışı" + +#: ../../libsmb/nterr.c:598 +msgid "Invalid pipe state" +msgstr "Geçersiz pipe durumu" + +#: ../../libsmb/nterr.c:599 +msgid "Named pipe busy" +msgstr "Named pipe meşgul" + +#: ../../libsmb/nterr.c:600 +msgid "Illegal function" +msgstr "Geçersiz fonksiyon" + +#: ../../libsmb/nterr.c:601 +msgid "Named pipe disconnected" +msgstr "Named pipe çevirim dışı" + +#: ../../libsmb/nterr.c:602 +msgid "Named pipe closing" +msgstr "Named pipe kapatılıyor" + +#: ../../libsmb/nterr.c:603 +msgid "Remote host not listening" +msgstr "Uzak sunucu dinlemiyor" + +#: ../../libsmb/nterr.c:604 +msgid "Duplicate name on network" +msgstr "Ağ üzerinde çift isim" + +#: ../../libsmb/nterr.c:605 +msgid "Print queue is full" +msgstr "Yazırma kuyruğu dolu" + +#: ../../libsmb/nterr.c:606 +msgid "No print spool space available" +msgstr "Yazdırma biriktirme alanı dolu" + +#: ../../libsmb/nterr.c:607 +msgid "The network name cannot be found" +msgstr "Ağ adı bulunamıyor" + +#: ../../libsmb/nterr.c:608 +msgid "The connection was refused" +msgstr "Bağlantı reddedildi" + +#: ../../libsmb/nterr.c:609 +msgid "Too many names" +msgstr "Çok fazla isim" + +#: ../../libsmb/nterr.c:610 +msgid "Too many sessions" +msgstr "Çok fazla oturum" + +#: ../../libsmb/nterr.c:611 +msgid "Invalid server state" +msgstr "Geçersiz sunucu durumu" + +#: ../../libsmb/nterr.c:612 +msgid "Invalid domain state" +msgstr "Geçersiz etki alanı durumu" + +#: ../../libsmb/nterr.c:613 +msgid "Invalid domain role" +msgstr "Geçersiz etki alanı rolü" + +#: ../../libsmb/nterr.c:614 +msgid "No such domain" +msgstr "Böyle bir etki alanı yok" + +#: ../../libsmb/nterr.c:615 +msgid "Domain exists" +msgstr "Etki alanı mevcut" + +#: ../../libsmb/nterr.c:616 +msgid "Domain limit exceeded" +msgstr "Etki alanı limiti aşıldı" + +#: ../../libsmb/nterr.c:617 +msgid "Bad logon session state" +msgstr "Kötü oturum açma oturumu durumu" + +#: ../../libsmb/nterr.c:618 +msgid "Logon session collision" +msgstr "Oturum açma oturum çakışması" + +#: ../../libsmb/nterr.c:619 +msgid "Invalid logon type" +msgstr "Hatalı oturum açma tipi" + +#: ../../libsmb/nterr.c:620 +msgid "Cancelled" +msgstr "İptal edildi" + +#: ../../libsmb/nterr.c:621 +msgid "Invalid computer name" +msgstr "Geçersiz bilgisayar adı" + +#: ../../libsmb/nterr.c:622 +msgid "Logon server conflict" +msgstr "Oturum açma sunucusu çakışması" + +#: ../../libsmb/nterr.c:623 +msgid "Time difference at domain controller" +msgstr "Etki alanı saati farklı" + +#: ../../libsmb/nterr.c:624 +msgid "Pipe broken" +msgstr "Pipe bozuk" + +#: ../../libsmb/nterr.c:625 +msgid "Registry corrupt" +msgstr "Kayıt defteri bozuk" + +#: ../../libsmb/nterr.c:626 +msgid "Too many secrets" +msgstr "Çok fazla secrets var" + +#: ../../libsmb/nterr.c:627 +msgid "Too many SIDs" +msgstr "Çok fazla SID var" + +#: ../../libsmb/nterr.c:628 +msgid "Lanmanager cross encryption required" +msgstr "Lanmanager cross encryption gerekli" + +#: ../../libsmb/nterr.c:629 +msgid "Log file full" +msgstr "Kayıt dosyası dolu" + +#: ../../libsmb/nterr.c:630 +msgid "No trusted LSA secret" +msgstr "No trusted LSA secret" + +#: ../../libsmb/nterr.c:631 +msgid "No trusted SAM account" +msgstr "No trusted SAM account" + +#: ../../libsmb/nterr.c:632 +msgid "Trusted domain failure" +msgstr "Güvenlien etki alanı hatası" + +#: ../../libsmb/nterr.c:633 +msgid "Trust relationship failure" +msgstr "Güven ilişkisi hatası" + +#: ../../libsmb/nterr.c:634 +msgid "Trust failure" +msgstr "Güven hatası" + +#: ../../libsmb/nterr.c:635 +msgid "Netlogon service not started" +msgstr "Netlogon servisi başlamadı" + +#: ../../libsmb/nterr.c:636 +msgid "Account expired" +msgstr "Hesap süresi dolmuş" + +#: ../../libsmb/nterr.c:637 +msgid "Network credential conflict" +msgstr "Ağ kimliği çakışması" + +#: ../../libsmb/nterr.c:638 +msgid "Remote session limit" +msgstr "Uzak oturum limiti" + +#: ../../libsmb/nterr.c:639 +msgid "No logon interdomain trust account" +msgstr "No logon interdomain trust account" + +#: ../../libsmb/nterr.c:640 +msgid "No logon workstation trust account" +msgstr "No logon workstation trust account" + +#: ../../libsmb/nterr.c:641 +msgid "No logon server trust account" +msgstr "No logon server trust account" + +#: ../../libsmb/nterr.c:642 +msgid "Domain trust inconsistent" +msgstr "Domain trust inconsistent" + +#: ../../libsmb/nterr.c:643 +msgid "No user session key available" +msgstr "No user session key available" + +#: ../../libsmb/nterr.c:644 +msgid "User session deleted" +msgstr "Kullanıcı oturumu silindi" + +#: ../../libsmb/nterr.c:645 +msgid "Insufficient server resources" +msgstr "Yetersiz sunucu kaynağı" + +#: ../../libsmb/nterr.c:646 +msgid "Insufficient logon information" +msgstr "Yetersiz oturum açma bilgileri" + +#: ../../libsmb/nterr.c:648 +msgid "License quota exceeded" +msgstr "Lisans limiti aşıldı" + +#: ../../libsmb/nterr.c:649 +msgid "No more files" +msgstr "Başka dosya yok" From eefc7a27155b70d027b1193187dd435267d863ea Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Nov 2017 13:52:03 -0800 Subject: [PATCH 66/92] s3: libsmb: smbc_statvfs is missing the supporting SMB2 calls. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13138 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider --- source3/libsmb/cli_smb2_fnum.c | 97 ++++++++++++++++++++++++++++++++++++++++++ source3/libsmb/cli_smb2_fnum.h | 6 +++ source3/libsmb/clifsinfo.c | 9 ++++ 3 files changed, 112 insertions(+) diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index b8179b0a48c..cb5c6fef4c0 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -1992,6 +1992,103 @@ NTSTATUS cli_smb2_dskattr(struct cli_state *cli, const char *path, return status; } +/*************************************************************** + Wrapper that allows SMB2 to query file system sizes. + Synchronous only. +***************************************************************/ + +NTSTATUS cli_smb2_get_fs_full_size_info(struct cli_state *cli, + uint64_t *total_allocation_units, + uint64_t *caller_allocation_units, + uint64_t *actual_allocation_units, + uint64_t *sectors_per_allocation_unit, + uint64_t *bytes_per_sector) +{ + NTSTATUS status; + uint16_t fnum = 0xffff; + DATA_BLOB outbuf = data_blob_null; + struct smb2_hnd *ph = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (smbXcli_conn_has_async_calls(cli->conn)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + /* First open the top level directory. */ + status = + cli_smb2_create_fnum(cli, "", 0, /* create_flags */ + FILE_READ_ATTRIBUTES, /* desired_access */ + FILE_ATTRIBUTE_DIRECTORY, /* file attributes */ + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, /* share_access */ + FILE_OPEN, /* create_disposition */ + FILE_DIRECTORY_FILE, /* create_options */ + &fnum, + NULL); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + status = map_fnum_to_smb2_handle(cli, fnum, &ph); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* getinfo on the returned handle with info_type SMB2_GETINFO_FS (2), + level 7 (SMB_FS_FULL_SIZE_INFORMATION). */ + + status = smb2cli_query_info(cli->conn, + cli->timeout, + cli->smb2.session, + cli->smb2.tcon, + SMB2_GETINFO_FS, /* in_info_type */ + /* in_file_info_class */ + SMB_FS_FULL_SIZE_INFORMATION - 1000, + 0xFFFF, /* in_max_output_length */ + NULL, /* in_input_buffer */ + 0, /* in_additional_info */ + 0, /* in_flags */ + ph->fid_persistent, + ph->fid_volatile, + frame, + &outbuf); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + if (outbuf.length < 32) { + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto fail; + } + + *total_allocation_units = BIG_UINT(outbuf.data, 0); + *caller_allocation_units = BIG_UINT(outbuf.data, 8); + *actual_allocation_units = BIG_UINT(outbuf.data, 16); + *sectors_per_allocation_unit = (uint64_t)IVAL(outbuf.data, 24); + *bytes_per_sector = (uint64_t)IVAL(outbuf.data, 28); + +fail: + + if (fnum != 0xffff) { + cli_smb2_close_fnum(cli, fnum); + } + + cli->raw_status = status; + + TALLOC_FREE(frame); + return status; +} + /*************************************************************** Wrapper that allows SMB2 to query file system attributes. Synchronous only. diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h index a6c36275eb8..793efc719ea 100644 --- a/source3/libsmb/cli_smb2_fnum.h +++ b/source3/libsmb/cli_smb2_fnum.h @@ -136,6 +136,12 @@ NTSTATUS cli_smb2_dskattr(struct cli_state *cli, uint64_t *total, uint64_t *avail); NTSTATUS cli_smb2_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr); +NTSTATUS cli_smb2_get_fs_full_size_info(struct cli_state *cli, + uint64_t *total_allocation_units, + uint64_t *caller_allocation_units, + uint64_t *actual_allocation_units, + uint64_t *sectors_per_allocation_unit, + uint64_t *bytes_per_sector); NTSTATUS cli_smb2_query_security_descriptor(struct cli_state *cli, uint16_t fnum, uint32_t sec_info, diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 119b1216fb2..46236390022 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -439,6 +439,15 @@ NTSTATUS cli_get_fs_full_size_info(struct cli_state *cli, uint32_t rdata_count; NTSTATUS status; + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + return cli_smb2_get_fs_full_size_info(cli, + total_allocation_units, + caller_allocation_units, + actual_allocation_units, + sectors_per_allocation_unit, + bytes_per_sector); + } + SSVAL(setup, 0, TRANSACT2_QFSINFO); SSVAL(param, 0, SMB_FS_FULL_SIZE_INFORMATION); From aaa52ab7b5ae711b80e3967ab1ecc91888c346f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Nov 2017 15:42:14 -0800 Subject: [PATCH 67/92] s3: smbclient: Implement "volume" command over SMB2. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13140 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider --- source3/libsmb/cli_smb2_fnum.c | 130 +++++++++++++++++++++++++++++++++++++++++ source3/libsmb/cli_smb2_fnum.h | 5 ++ source3/libsmb/clifsinfo.c | 8 +++ 3 files changed, 143 insertions(+) diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index cb5c6fef4c0..628b17b293b 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -2168,6 +2168,136 @@ NTSTATUS cli_smb2_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr) return status; } +/*************************************************************** + Wrapper that allows SMB2 to query file system volume info. + Synchronous only. +***************************************************************/ + +NTSTATUS cli_smb2_get_fs_volume_info(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + char **_volume_name, + uint32_t *pserial_number, + time_t *pdate) +{ + NTSTATUS status; + uint16_t fnum = 0xffff; + DATA_BLOB outbuf = data_blob_null; + struct smb2_hnd *ph = NULL; + uint32_t nlen; + char *volume_name = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (smbXcli_conn_has_async_calls(cli->conn)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + /* First open the top level directory. */ + status = + cli_smb2_create_fnum(cli, "", 0, /* create_flags */ + FILE_READ_ATTRIBUTES, /* desired_access */ + FILE_ATTRIBUTE_DIRECTORY, /* file attributes */ + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, /* share_access */ + FILE_OPEN, /* create_disposition */ + FILE_DIRECTORY_FILE, /* create_options */ + &fnum, + NULL); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + status = map_fnum_to_smb2_handle(cli, fnum, &ph); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* getinfo on the returned handle with info_type SMB2_GETINFO_FS (2), + level 1 (SMB_FS_VOLUME_INFORMATION). */ + + status = smb2cli_query_info(cli->conn, + cli->timeout, + cli->smb2.session, + cli->smb2.tcon, + SMB2_GETINFO_FS, /* in_info_type */ + /* in_file_info_class */ + SMB_FS_VOLUME_INFORMATION - 1000, + 0xFFFF, /* in_max_output_length */ + NULL, /* in_input_buffer */ + 0, /* in_additional_info */ + 0, /* in_flags */ + ph->fid_persistent, + ph->fid_volatile, + frame, + &outbuf); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + if (outbuf.length < 24) { + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto fail; + } + + if (pdate) { + struct timespec ts; + ts = interpret_long_date((char *)outbuf.data); + *pdate = ts.tv_sec; + } + if (pserial_number) { + *pserial_number = IVAL(outbuf.data,8); + } + nlen = IVAL(outbuf.data,12); + if (nlen + 18 < 18) { + /* Integer wrap. */ + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto fail; + } + /* + * The next check is safe as we know outbuf.length >= 24 + * from above. + */ + if (nlen > (outbuf.length - 18)) { + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto fail; + } + + clistr_pull_talloc(mem_ctx, + (const char *)outbuf.data, + 0, + &volume_name, + outbuf.data + 18, + nlen, + STR_UNICODE); + if (volume_name == NULL) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + *_volume_name = volume_name; + +fail: + + if (fnum != 0xffff) { + cli_smb2_close_fnum(cli, fnum); + } + + cli->raw_status = status; + + TALLOC_FREE(frame); + return status; +} + + /*************************************************************** Wrapper that allows SMB2 to query a security descriptor. Synchronous only. diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h index 793efc719ea..3d9b6eb3fe6 100644 --- a/source3/libsmb/cli_smb2_fnum.h +++ b/source3/libsmb/cli_smb2_fnum.h @@ -142,6 +142,11 @@ NTSTATUS cli_smb2_get_fs_full_size_info(struct cli_state *cli, uint64_t *actual_allocation_units, uint64_t *sectors_per_allocation_unit, uint64_t *bytes_per_sector); +NTSTATUS cli_smb2_get_fs_volume_info(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + char **_volume_name, + uint32_t *pserial_number, + time_t *pdate); NTSTATUS cli_smb2_query_security_descriptor(struct cli_state *cli, uint16_t fnum, uint32_t sec_info, diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 46236390022..09c0d9535f1 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -375,6 +375,14 @@ NTSTATUS cli_get_fs_volume_info(struct cli_state *cli, unsigned int nlen; char *volume_name = NULL; + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + return cli_smb2_get_fs_volume_info(cli, + mem_ctx, + _volume_name, + pserial_number, + pdate); + } + SSVAL(setup, 0, TRANSACT2_QFSINFO); SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO); From f8cd211acc3824e01d89a6f8b6666c39aa5cd54e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Nov 2017 15:54:19 -0800 Subject: [PATCH 68/92] s3: smbclient: tests: Test "volume" command over SMB1 and SMB2+. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13140 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Wed Nov 15 19:50:54 CET 2017 on sn-devel-144 --- source3/script/tests/test_smbclient_s3.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh index 45005776cf8..d98da0dd260 100755 --- a/source3/script/tests/test_smbclient_s3.sh +++ b/source3/script/tests/test_smbclient_s3.sh @@ -1525,7 +1525,34 @@ EOF fi } +# Test doing a volume command. +test_volume() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat > $tmpfile < Date: Wed, 15 Nov 2017 10:12:06 -0800 Subject: [PATCH 69/92] s4: torture: Ensure kernel oplock test can't hang in pause(). Use an alarm to break out of waiting for a signal. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13121 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Thu Nov 16 22:27:06 CET 2017 on sn-devel-144 --- source4/torture/smb2/oplock.c | 67 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c index 1830a017e83..b6d9f842336 100644 --- a/source4/torture/smb2/oplock.c +++ b/source4/torture/smb2/oplock.c @@ -4817,6 +4817,17 @@ static void got_rt_break(int sig) got_break = 1; } +static int got_alarm; + +/* + * Signal handler. + */ + +static void got_alarm_fn(int sig) +{ + got_alarm = 1; +} + /* * Child process function. */ @@ -4835,6 +4846,13 @@ static int do_child_process(int pipefd, const char *name) if (ret == -1) { return 1; } + /* Set up a signal handler for SIGALRM. */ + ZERO_STRUCT(act); + act.sa_handler = got_alarm_fn; + ret = sigaction(SIGALRM, &act, NULL); + if (ret == -1) { + return 1; + } /* Open the passed in file and get a kernel oplock. */ fd = open(name, O_RDWR, 0666); if (fd == -1) { @@ -4857,16 +4875,26 @@ static int do_child_process(int pipefd, const char *name) return 5; } + /* Ensure the pause doesn't hang forever. */ + alarm(5); + /* Wait for RT_SIGNAL_LEASE. */ ret = pause(); if (ret != -1 || errno != EINTR) { return 6; } + if (got_alarm == 1) { + return 10; + } + if (got_break != 1) { return 7; } + /* Cancel any pending alarm. */ + alarm(0); + /* Force the server to wait for 3 seconds. */ sleep(3); @@ -4928,6 +4956,23 @@ static bool wait_for_child_oplock(struct torture_context *tctx, } #endif +static void child_sig_term_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + int *pstatus = (int *)private_data; + int status; + wait(&status); + if (WIFEXITED(status)) { + *pstatus = WEXITSTATUS(status); + } else { + *pstatus = status; + } +} + /* * Deal with a non-smbd process holding a kernel oplock. */ @@ -4944,6 +4989,8 @@ static bool test_smb2_kernel_oplocks8(struct torture_context *tctx, struct smb2_handle h1 = {{0}}; struct smb2_handle h2 = {{0}}; const char *localdir = torture_setting_string(tctx, "localdir", NULL); + struct tevent_signal *se = NULL; + int child_exit_code = -1; time_t start; time_t end; @@ -4963,6 +5010,14 @@ static bool test_smb2_kernel_oplocks8(struct torture_context *tctx, smb2_util_close(tree, h1); ZERO_STRUCT(h1); + se = tevent_add_signal(tctx->ev, + tctx, + SIGCHLD, + 0, + child_sig_term_handler, + &child_exit_code); + torture_assert(tctx, se != NULL, "tevent_add_signal failed\n"); + /* Take the oplock locally in a sub-process. */ ret = wait_for_child_oplock(tctx, localdir, fname); torture_assert_goto(tctx, ret = true, ret, done, @@ -5013,6 +5068,18 @@ static bool test_smb2_kernel_oplocks8(struct torture_context *tctx, "Error opening the file\n"); h2 = io.out.file.handle; + /* Wait for the exit code from the child. */ + while (child_exit_code == -1) { + int rval = tevent_loop_once(tctx->ev); + torture_assert(tctx, rval == 0, "tevent_loop_once error\n"); + } + + if (child_exit_code != 0) { + torture_comment(tctx, "Bad child exit code %d\n", + child_exit_code); + ret = false; + } + done: if (!smb2_util_handle_empty(h1)) { smb2_util_close(tree, h1); From 3b16bfe483da19c500ab511fd3d8c81528cfe608 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 11 Nov 2017 13:05:03 +0100 Subject: [PATCH 70/92] pthreadpool: create a tevent_threaded_context per registered event context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We just need one tevent_threaded_context per unique combintation of tevent event contexts and pthreadpool_tevent pools, not multiple copies for identical combinations of a tevent contexts and a pthreadpool_tevent pools. With this commit we register tevent contexts in a list in the pthreadpool_tevent structure and will only have one tevent_threaded_context object per tevent context per pool. With many pthreadpool_tevent_job_send reqs this pays off, I've seen a small decrease in cpu-ticks with valgrind callgrind and a modified local.messaging.ping-speed torture test. The test modification ensured messages we never directly send, but always submitted via pthreadpool_tevent_job_send. Pair-Programmed-With: Jeremy Allison Signed-off-by: Ralph Boehme Signed-off-by: Jeremy Allison Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Fri Nov 17 02:35:52 CET 2017 on sn-devel-144 --- lib/pthreadpool/pthreadpool_tevent.c | 184 +++++++++++++++++++++++++++++++---- 1 file changed, 167 insertions(+), 17 deletions(-) diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c index 253a8673518..493083406ab 100644 --- a/lib/pthreadpool/pthreadpool_tevent.c +++ b/lib/pthreadpool/pthreadpool_tevent.c @@ -25,8 +25,37 @@ struct pthreadpool_tevent_job_state; +/* + * We need one pthreadpool_tevent_glue object per unique combintaion of tevent + * contexts and pthreadpool_tevent objects. Maintain a list of used tevent + * contexts in a pthreadpool_tevent. + */ +struct pthreadpool_tevent_glue { + struct pthreadpool_tevent_glue *prev, *next; + struct pthreadpool_tevent *pool; /* back-pointer to owning object. */ + /* Tuple we are keeping track of in this list. */ + struct tevent_context *ev; + struct tevent_threaded_context *tctx; + /* Pointer to link object owned by *ev. */ + struct pthreadpool_tevent_glue_ev_link *ev_link; +}; + +/* + * The pthreadpool_tevent_glue_ev_link and its destructor ensure we remove the + * tevent context from our list of active event contexts if the event context + * is destroyed. + * This structure is talloc()'ed from the struct tevent_context *, and is a + * back-pointer allowing the related struct pthreadpool_tevent_glue object + * to be removed from the struct pthreadpool_tevent glue list if the owning + * tevent_context is talloc_free()'ed. + */ +struct pthreadpool_tevent_glue_ev_link { + struct pthreadpool_tevent_glue *glue; +}; + struct pthreadpool_tevent { struct pthreadpool *pool; + struct pthreadpool_tevent_glue *glue_list; struct pthreadpool_tevent_job_state *jobs; }; @@ -35,7 +64,6 @@ struct pthreadpool_tevent_job_state { struct pthreadpool_tevent_job_state *prev, *next; struct pthreadpool_tevent *pool; struct tevent_context *ev; - struct tevent_threaded_context *tctx; struct tevent_immediate *im; struct tevent_req *req; @@ -77,6 +105,7 @@ int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads, static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool) { struct pthreadpool_tevent_job_state *state, *next; + struct pthreadpool_tevent_glue *glue = NULL; int ret; ret = pthreadpool_destroy(pool->pool); @@ -91,6 +120,118 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool) state->pool = NULL; } + /* + * Delete all the registered + * tevent_context/tevent_threaded_context + * pairs. + */ + for (glue = pool->glue_list; glue != NULL; glue = pool->glue_list) { + /* The glue destructor removes it from the list */ + TALLOC_FREE(glue); + } + pool->glue_list = NULL; + + return 0; +} + +static int pthreadpool_tevent_glue_destructor( + struct pthreadpool_tevent_glue *glue) +{ + if (glue->pool->glue_list != NULL) { + DLIST_REMOVE(glue->pool->glue_list, glue); + } + + /* Ensure the ev_link destructor knows we're gone */ + glue->ev_link->glue = NULL; + + TALLOC_FREE(glue->ev_link); + TALLOC_FREE(glue->tctx); + + return 0; +} + +/* + * Destructor called either explicitly from + * pthreadpool_tevent_glue_destructor(), or indirectly + * when owning tevent_context is destroyed. + * + * When called from pthreadpool_tevent_glue_destructor() + * ev_link->glue is already NULL, so this does nothing. + * + * When called from talloc_free() of the owning + * tevent_context we must ensure we also remove the + * linked glue object from the list inside + * struct pthreadpool_tevent. + */ +static int pthreadpool_tevent_glue_link_destructor( + struct pthreadpool_tevent_glue_ev_link *ev_link) +{ + TALLOC_FREE(ev_link->glue); + return 0; +} + +static int pthreadpool_tevent_register_ev(struct pthreadpool_tevent *pool, + struct tevent_context *ev) +{ + struct pthreadpool_tevent_glue *glue = NULL; + struct pthreadpool_tevent_glue_ev_link *ev_link = NULL; + + /* + * See if this tevent_context was already registered by + * searching the glue object list. If so we have nothing + * to do here - we already have a tevent_context/tevent_threaded_context + * pair. + */ + for (glue = pool->glue_list; glue != NULL; glue = glue->next) { + if (glue->ev == ev) { + return 0; + } + } + + /* + * Event context not yet registered - create a new glue + * object containing a tevent_context/tevent_threaded_context + * pair and put it on the list to remember this registration. + * We also need a link object to ensure the event context + * can't go away without us knowing about it. + */ + glue = talloc_zero(pool, struct pthreadpool_tevent_glue); + if (glue == NULL) { + return ENOMEM; + } + *glue = (struct pthreadpool_tevent_glue) { + .pool = pool, + .ev = ev, + }; + talloc_set_destructor(glue, pthreadpool_tevent_glue_destructor); + + /* + * Now allocate the link object to the event context. Note this + * is allocated OFF THE EVENT CONTEXT ITSELF, so if the event + * context is freed we are able to cleanup the glue object + * in the link object destructor. + */ + + ev_link = talloc_zero(ev, struct pthreadpool_tevent_glue_ev_link); + if (ev_link == NULL) { + TALLOC_FREE(glue); + return ENOMEM; + } + ev_link->glue = glue; + talloc_set_destructor(ev_link, pthreadpool_tevent_glue_link_destructor); + + glue->ev_link = ev_link; + +#ifdef HAVE_PTHREAD + glue->tctx = tevent_threaded_context_create(pool, ev); + if (glue->tctx == NULL) { + TALLOC_FREE(ev_link); + TALLOC_FREE(glue); + return ENOMEM; + } +#endif + + DLIST_ADD(pool->glue_list, glue); return 0; } @@ -147,20 +288,11 @@ struct tevent_req *pthreadpool_tevent_job_send( return tevent_req_post(req, ev); } -#ifdef HAVE_PTHREAD - state->tctx = tevent_threaded_context_create(state, ev); - if (state->tctx == NULL && errno == ENOSYS) { - /* - * Samba build with pthread support but - * tevent without??? - */ - tevent_req_error(req, ENOSYS); - return tevent_req_post(req, ev); - } - if (tevent_req_nomem(state->tctx, req)) { + ret = pthreadpool_tevent_register_ev(pool, ev); + if (ret != 0) { + tevent_req_error(req, errno); return tevent_req_post(req, ev); } -#endif ret = pthreadpool_add_job(pool->pool, 0, pthreadpool_tevent_job_fn, @@ -194,10 +326,30 @@ static int pthreadpool_tevent_job_signal(int jobid, { struct pthreadpool_tevent_job_state *state = talloc_get_type_abort( job_private_data, struct pthreadpool_tevent_job_state); + struct tevent_threaded_context *tctx = NULL; + struct pthreadpool_tevent_glue *g = NULL; - if (state->tctx != NULL) { + if (state->pool == NULL) { + /* The pthreadpool_tevent is already gone */ + return 0; + } + +#ifdef HAVE_PTHREAD + for (g = state->pool->glue_list; g != NULL; g = g->next) { + if (g->ev == state->ev) { + tctx = g->tctx; + break; + } + } + + if (tctx == NULL) { + abort(); + } +#endif + + if (tctx != NULL) { /* with HAVE_PTHREAD */ - tevent_threaded_schedule_immediate(state->tctx, state->im, + tevent_threaded_schedule_immediate(tctx, state->im, pthreadpool_tevent_job_done, state); } else { @@ -222,8 +374,6 @@ static void pthreadpool_tevent_job_done(struct tevent_context *ctx, state->pool = NULL; } - TALLOC_FREE(state->tctx); - if (state->req == NULL) { /* * There was a talloc_free() state->req From 993fa5793fd6a95173eda574562661ab8959c544 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Nov 2017 19:26:55 -0800 Subject: [PATCH 71/92] lib: tevent: Minor cleanup. wakeup_fd can always be gotten from the event context. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't need to store it. I prefer this as it shows that we must always get wakeup_fd from the event context at time of use, rather than possibly storing an out-of-date variable. Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Fri Nov 17 12:43:01 CET 2017 on sn-devel-144 --- lib/tevent/tevent_internal.h | 1 - lib/tevent/tevent_threads.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index 47ea39b3cd1..ec3955e70a4 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -235,7 +235,6 @@ struct tevent_threaded_context { pthread_mutex_t event_ctx_mutex; #endif struct tevent_context *event_ctx; - int wakeup_fd; }; struct tevent_debug_ops { diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index 2e83f1b66c2..2c6e66b0904 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -424,7 +424,6 @@ struct tevent_threaded_context *tevent_threaded_context_create( return NULL; } tctx->event_ctx = ev; - tctx->wakeup_fd = ev->wakeup_fd; ret = pthread_mutex_init(&tctx->event_ctx_mutex, NULL); if (ret != 0) { @@ -489,14 +488,13 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, } DLIST_ADD_END(ev->scheduled_immediates, im); + wakeup_fd = ev->wakeup_fd; ret = pthread_mutex_unlock(&ev->scheduled_mutex); if (ret != 0) { abort(); } - wakeup_fd = tctx->wakeup_fd; - ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); From 625d27d3fc5b5dbddb43d21aa467431f2043d89d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Nov 2017 13:04:21 +0100 Subject: [PATCH 72/92] libsmb: Fix a typo Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/namequery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index e39d76176cc..afc2bc06d3f 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -2556,7 +2556,7 @@ static NTSTATUS resolve_ads(const char *name, freeaddrinfo(res); } } else { - /* use all the IP addresses from the SRV sresponse */ + /* use all the IP addresses from the SRV response */ int j; for (j = 0; j < dcs[i].num_ips; j++) { (*return_iplist)[*return_count].port = dcs[i].port; From c19b49bad8071bc33089e5b3c053fcb890a8ea11 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Oct 2017 13:51:25 +0100 Subject: [PATCH 73/92] tevent: Fix typos While there, fix comment formatting Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- lib/tevent/tevent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 728cf6267f1..7284a8559d2 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -936,8 +936,8 @@ void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); * * @param[in] req The request to use. * - * @return This function returns true is the request is cancelable, - * othererwise false is returned. + * @return This function returns true if the request is + * cancelable, otherwise false is returned. * * @note Even if the function returns true, the caller need to wait * for the function to complete normally. From df5a5341987eee1ef4666ab01d7e714159388a75 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Jul 2017 15:40:11 +0200 Subject: [PATCH 74/92] nsswitch: Fix a typo Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- nsswitch/winbind_struct_protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h index a2e7d4c392c..9100dbcf6ea 100644 --- a/nsswitch/winbind_struct_protocol.h +++ b/nsswitch/winbind_struct_protocol.h @@ -258,7 +258,7 @@ struct winbindd_request { gid_t gid; /* getgrgid, gid_to_sid */ uint32_t ndrcmd; struct { - /* We deliberatedly don't split into domain/user to + /* We deliberately don't split into domain/user to avoid having the client know what the separator character is. */ fstring user; From 03be840a7a59d8e443f0d6c3a3f071fc6fcf340b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Aug 2017 18:04:12 +0200 Subject: [PATCH 75/92] winbindd: Fix some signed/unsigned warnings Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/winbindd/winbindd_cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index faea764cb5d..502232544c4 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -452,7 +452,7 @@ static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now ) /* have we expired? */ time_diff = now - domain->last_seq_check; - if ( time_diff > lp_winbind_cache_time() ) { + if ((int)time_diff > lp_winbind_cache_time()) { DEBUG(10,("fetch_cache_seqnum: timeout [%s][%u @ %u]\n", domain->name, domain->sequence_number, (uint32_t)domain->last_seq_check)); @@ -619,7 +619,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s current sequence number or it did not timeout then it is OK */ if (wcache_server_down(domain) || ((centry->sequence_number == domain->sequence_number) - && (centry->timeout > time(NULL)))) { + && ((time_t)centry->timeout > time(NULL)))) { DEBUG(10,("centry_expired: Key %s for domain %s is good.\n", keystr, domain->name )); return false; @@ -4802,7 +4802,7 @@ bool wcache_fetch_ndr(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, goto fail; } entry_timeout = BVAL(data.dptr, 4); - if (time(NULL) > entry_timeout) { + if (time(NULL) > (time_t)entry_timeout) { DEBUG(10, ("Entry has timed out\n")); goto fail; } From 2a86876c223aca33865fcb11ba59af1faf91f86c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Nov 2017 16:15:42 +0100 Subject: [PATCH 76/92] lib: Avoid a pointless static variable Saves a few bytes of .text Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- lib/util/util_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/util_net.c b/lib/util/util_net.c index cbc836cc54c..b3ed9f262fe 100644 --- a/lib/util/util_net.c +++ b/lib/util/util_net.c @@ -44,7 +44,7 @@ void zero_sockaddr(struct sockaddr_storage *pss) static char *normalize_ipv6_literal(const char *str, char *buf, size_t *_len) { #define IPv6_LITERAL_NET ".ipv6-literal.net" - static const size_t llen = sizeof(IPv6_LITERAL_NET) - 1; + const size_t llen = sizeof(IPv6_LITERAL_NET) - 1; size_t len = *_len; int cmp; size_t i; From 98dd651f8dd728aaeb09aa53c4c38d132b02fa50 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Nov 2017 16:54:09 +0100 Subject: [PATCH 77/92] lib: Simplify is_ipaddress_v6 Do an early return, avoid an "else", avoid an indentation level Review with git show -b Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- lib/util/util_net.c | 107 ++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/lib/util/util_net.c b/lib/util/util_net.c index b3ed9f262fe..d52d401e4c7 100644 --- a/lib/util/util_net.c +++ b/lib/util/util_net.c @@ -490,76 +490,75 @@ bool is_ipaddress_v6(const char *str) #if defined(HAVE_IPV6) int ret = -1; char *p = NULL; + char buf[INET6_ADDRSTRLEN] = { 0, }; + size_t len; + const char *addr = str; + const char *idxs = NULL; + unsigned int idx = 0; + struct in6_addr ip6; p = strchr_m(str, ':'); if (p == NULL) { return is_ipv6_literal(str); - } else { - char buf[INET6_ADDRSTRLEN] = { 0, }; - size_t len; - const char *addr = str; - const char *idxs = NULL; - unsigned int idx = 0; - struct in6_addr ip6; - - p = strchr_m(str, SCOPE_DELIMITER); - if (p && (p > str)) { - len = PTR_DIFF(p, str); - idxs = p + 1; - } else { - len = strlen(str); - } + } - if (len >= sizeof(buf)) { - return false; - } - if (idxs != NULL) { - strncpy(buf, str, len); - addr = buf; - } + p = strchr_m(str, SCOPE_DELIMITER); + if (p && (p > str)) { + len = PTR_DIFF(p, str); + idxs = p + 1; + } else { + len = strlen(str); + } - /* - * Cope with link-local. - * This is IP:v6:addr%ifidx. - */ - if (idxs != NULL) { - char c; + if (len >= sizeof(buf)) { + return false; + } + if (idxs != NULL) { + strncpy(buf, str, len); + addr = buf; + } - ret = sscanf(idxs, "%5u%c", &idx, &c); - if (ret != 1) { - idx = 0; - } + /* + * Cope with link-local. + * This is IP:v6:addr%ifidx. + */ + if (idxs != NULL) { + char c; - if (idx > 0 && idx < UINT16_MAX) { - /* a valid index */ - idxs = NULL; - } + ret = sscanf(idxs, "%5u%c", &idx, &c); + if (ret != 1) { + idx = 0; } - /* - * Cope with link-local. - * This is IP:v6:addr%ifname. - */ - if (idxs != NULL) { - idx = if_nametoindex(idxs); - - if (idx > 0) { - /* a valid index */ - idxs = NULL; - } + if (idx > 0 && idx < UINT16_MAX) { + /* a valid index */ + idxs = NULL; } + } - if (idxs != NULL) { - return false; - } + /* + * Cope with link-local. + * This is IP:v6:addr%ifname. + */ + if (idxs != NULL) { + idx = if_nametoindex(idxs); - ret = inet_pton(AF_INET6, addr, &ip6); - if (ret <= 0) { - return false; + if (idx > 0) { + /* a valid index */ + idxs = NULL; } + } - return true; + if (idxs != NULL) { + return false; + } + + ret = inet_pton(AF_INET6, addr, &ip6); + if (ret <= 0) { + return false; } + + return true; #endif return false; } From 73533b90cc60d684c60ffb5c18e9d940e2ce3c32 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Nov 2017 16:21:31 +0100 Subject: [PATCH 78/92] lib: Fix a false/NULL hickup Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- lib/util/util_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/util_net.c b/lib/util/util_net.c index d52d401e4c7..57db4fae4d8 100644 --- a/lib/util/util_net.c +++ b/lib/util/util_net.c @@ -53,7 +53,7 @@ static char *normalize_ipv6_literal(const char *str, char *buf, size_t *_len) size_t cnt_chars = 0; if (len <= llen) { - return false; + return NULL; } /* ignore a trailing '.' */ From e83f3891b2f6a105d30120c2f6917fa7cc8ae969 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 15 Nov 2017 13:12:05 +0100 Subject: [PATCH 79/92] lib: Save a few bytes of .text Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- lib/util/util_net.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/util/util_net.c b/lib/util/util_net.c index 57db4fae4d8..f0a30168342 100644 --- a/lib/util/util_net.c +++ b/lib/util/util_net.c @@ -36,9 +36,8 @@ void zero_sockaddr(struct sockaddr_storage *pss) { - ZERO_STRUCTP(pss); /* Ensure we're at least a valid sockaddr-storage. */ - pss->ss_family = AF_INET; + *pss = (struct sockaddr_storage) { .ss_family = AF_INET }; } static char *normalize_ipv6_literal(const char *str, char *buf, size_t *_len) From 87c443256223a91192b8ea3db94fbd40557be881 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 13 Jul 2017 15:52:15 +0200 Subject: [PATCH 80/92] libwbclient: Fix two signed/unsigned hickups Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- nsswitch/libwbclient/wbc_pam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c index cb2d5a0f4c4..c31220ae7eb 100644 --- a/nsswitch/libwbclient/wbc_pam.c +++ b/nsswitch/libwbclient/wbc_pam.c @@ -727,7 +727,7 @@ wbcErr wbcCtxLogoffUserEx(struct wbcContext *ctx, struct winbindd_request request; struct winbindd_response response; wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - int i; + size_t i; /* validate input */ @@ -1269,7 +1269,7 @@ wbcErr wbcCtxCredentialCache(struct wbcContext *ctx, struct winbindd_response response; struct wbcNamedBlob *initial_blob = NULL; struct wbcNamedBlob *challenge_blob = NULL; - int i; + size_t i; ZERO_STRUCT(request); ZERO_STRUCT(response); From 5781cefc427b3f9f89b4470c1504ab941fa5334e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Jul 2017 10:52:17 +0200 Subject: [PATCH 81/92] ntlm_auth: Use libwbclient in winbind_separator() Avoid direct winbindd_request_response() Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/utils/ntlm_auth.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 5a10e27719f..faba67c3b29 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -280,24 +280,24 @@ static void gensec_want_feature_list(struct gensec_security *state, char* featur static char winbind_separator(void) { - struct winbindd_response response; + struct wbcInterfaceDetails *details; + wbcErr ret; static bool got_sep; static char sep; if (got_sep) return sep; - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request_response(NULL, WINBINDD_INFO, NULL, &response) != - NSS_STATUS_SUCCESS) { + ret = wbcInterfaceDetails(&details); + if (!WBC_ERROR_IS_OK(ret)) { d_fprintf(stderr, "could not obtain winbind separator!\n"); return *lp_winbind_separator(); } - sep = response.data.info.winbind_separator; + sep = details->winbind_separator; + + wbcFreeMemory(details); + got_sep = True; if (!sep) { From 25e85a4507d959a922ffc9f2eea144fbe02c37d2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Jul 2017 10:55:09 +0200 Subject: [PATCH 82/92] ntlm_auth: Use libwbclient in get_winbind_domain() Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/utils/ntlm_auth.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index faba67c3b29..932f91c22ad 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -310,24 +310,25 @@ static char winbind_separator(void) const char *get_winbind_domain(void) { - struct winbindd_response response; + struct wbcInterfaceDetails *details; + wbcErr ret; static fstring winbind_domain; if (*winbind_domain) { return winbind_domain; } - ZERO_STRUCT(response); - /* Send off request */ - if (winbindd_request_response(NULL, WINBINDD_DOMAIN_NAME, NULL, &response) != - NSS_STATUS_SUCCESS) { + ret = wbcInterfaceDetails(&details); + if (!WBC_ERROR_IS_OK(ret)) { DEBUG(1, ("could not obtain winbind domain name!\n")); return lp_workgroup(); } - fstrcpy(winbind_domain, response.data.domain_name); + fstrcpy(winbind_domain, details->netbios_domain); + + wbcFreeMemory(details); return winbind_domain; From 403003b528a2445ac128db5750b87de3967372bd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Jul 2017 11:06:38 +0200 Subject: [PATCH 83/92] ntlm_auth: Use libwbclient in get_require_membership_sid() Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/utils/ntlm_auth.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 932f91c22ad..c0e1c2a6525 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -392,8 +392,10 @@ static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain, } static bool get_require_membership_sid(void) { - struct winbindd_request request; - struct winbindd_response response; + fstring domain, name, sidbuf; + struct wbcDomainSid sid; + enum wbcSidType type; + wbcErr ret; if (!require_membership_of) { return True; @@ -405,25 +407,23 @@ static bool get_require_membership_sid(void) { /* Otherwise, ask winbindd for the name->sid request */ - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (!parse_ntlm_auth_domain_user(require_membership_of, - request.data.name.dom_name, - request.data.name.name)) { + if (!parse_ntlm_auth_domain_user(require_membership_of, + domain, name)) { DEBUG(0, ("Could not parse %s into separate domain/name parts!\n", require_membership_of)); return False; } - if (winbindd_request_response(NULL, WINBINDD_LOOKUPNAME, &request, &response) != - NSS_STATUS_SUCCESS) { + ret = wbcLookupName(domain, name, &sid, &type); + if (!WBC_ERROR_IS_OK(ret)) { DEBUG(0, ("Winbindd lookupname failed to resolve %s into a SID!\n", require_membership_of)); return False; } - require_membership_of_sid = SMB_STRDUP(response.data.sid.sid); + wbcSidToStringBuf(&sid, sidbuf, sizeof(sidbuf)); + + require_membership_of_sid = SMB_STRDUP(sidbuf); if (require_membership_of_sid) return True; From ffbf393fba69d715d150fbc4f147bf0a97fbb69a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Jul 2017 10:56:47 +0200 Subject: [PATCH 84/92] ntlm_auth: Use libwbclient in get_winbind_netbios_name() Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/utils/ntlm_auth.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index c0e1c2a6525..3f544902a24 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -336,7 +336,8 @@ const char *get_winbind_domain(void) const char *get_winbind_netbios_name(void) { - struct winbindd_response response; + struct wbcInterfaceDetails *details; + wbcErr ret; static fstring winbind_netbios_name; @@ -344,17 +345,17 @@ const char *get_winbind_netbios_name(void) return winbind_netbios_name; } - ZERO_STRUCT(response); - /* Send off request */ - if (winbindd_request_response(NULL, WINBINDD_NETBIOS_NAME, NULL, &response) != - NSS_STATUS_SUCCESS) { + ret = wbcInterfaceDetails(&details); + if (!WBC_ERROR_IS_OK(ret)) { DEBUG(1, ("could not obtain winbind netbios name!\n")); return lp_netbios_name(); } - fstrcpy(winbind_netbios_name, response.data.netbios_name); + fstrcpy(winbind_netbios_name, details->netbios_name); + + wbcFreeMemory(details); return winbind_netbios_name; From d74c60807cdaec2835c400a6de0fa5e381cc1392 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Jul 2017 11:54:14 +0200 Subject: [PATCH 85/92] nsswitch: Slightly simplify winbindd_request_response We don't need a separate variable, C passes a copy on the stack Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- nsswitch/wb_common.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c index 262181a3cff..d6746b4f535 100644 --- a/nsswitch/wb_common.c +++ b/nsswitch/wb_common.c @@ -719,16 +719,15 @@ NSS_STATUS winbindd_request_response(struct winbindd_context *ctx, struct winbindd_response *response) { NSS_STATUS status = NSS_STATUS_UNAVAIL; - struct winbindd_context *wb_ctx = ctx; if (ctx == NULL) { - wb_ctx = &wb_global_ctx; + ctx = &wb_global_ctx; } - status = winbindd_send_request(wb_ctx, req_type, 0, request); + status = winbindd_send_request(ctx, req_type, 0, request); if (status != NSS_STATUS_SUCCESS) return (status); - status = winbindd_get_response(wb_ctx, response); + status = winbindd_get_response(ctx, response); return status; } @@ -739,16 +738,15 @@ NSS_STATUS winbindd_priv_request_response(struct winbindd_context *ctx, struct winbindd_response *response) { NSS_STATUS status = NSS_STATUS_UNAVAIL; - struct winbindd_context *wb_ctx = ctx; if (ctx == NULL) { - wb_ctx = &wb_global_ctx; + ctx = &wb_global_ctx; } - status = winbindd_send_request(wb_ctx, req_type, 1, request); + status = winbindd_send_request(ctx, req_type, 1, request); if (status != NSS_STATUS_SUCCESS) return (status); - status = winbindd_get_response(wb_ctx, response); + status = winbindd_get_response(ctx, response); return status; } From 9466796c87cc4ca8d32da553421cd8ecef1bb8e4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Nov 2017 15:51:36 +0100 Subject: [PATCH 86/92] s3:selftest: add samba3.blackbox.net_rpc_oldjoin test This demonstrates that "net rpc oldjoin" is currently broken. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13149 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- selftest/knownfail.d/oldjoin | 1 + source3/script/tests/test_net_rpc_oldjoin.sh | 32 ++++++++++++++++++++++++++++ source3/selftest/tests.py | 4 ++++ 3 files changed, 37 insertions(+) create mode 100644 selftest/knownfail.d/oldjoin create mode 100755 source3/script/tests/test_net_rpc_oldjoin.sh diff --git a/selftest/knownfail.d/oldjoin b/selftest/knownfail.d/oldjoin new file mode 100644 index 00000000000..86fca85f900 --- /dev/null +++ b/selftest/knownfail.d/oldjoin @@ -0,0 +1 @@ +^samba3.blackbox.net_rpc_oldjoin.net.* diff --git a/source3/script/tests/test_net_rpc_oldjoin.sh b/source3/script/tests/test_net_rpc_oldjoin.sh new file mode 100755 index 00000000000..070fcc1add7 --- /dev/null +++ b/source3/script/tests/test_net_rpc_oldjoin.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then +cat < Date: Thu, 16 Nov 2017 21:09:20 +0000 Subject: [PATCH 87/92] libnet_join: fix "net rpc oldjoin" We need to open the ncacn_np (smb) transport connection with anonymous credentials. In order to do netr_ServerPasswordSet*() we need to establish a 2nd netlogon connection using dcerpc schannel authentication. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13149 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- selftest/knownfail.d/oldjoin | 1 - source3/libnet/libnet_join.c | 53 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 9 deletions(-) delete mode 100644 selftest/knownfail.d/oldjoin diff --git a/selftest/knownfail.d/oldjoin b/selftest/knownfail.d/oldjoin deleted file mode 100644 index 86fca85f900..00000000000 --- a/selftest/knownfail.d/oldjoin +++ /dev/null @@ -1 +0,0 @@ -^samba3.blackbox.net_rpc_oldjoin.net.* diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index eb6b894908f..0595cfe64ab 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1044,12 +1044,23 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx, NTSTATUS status, result; union lsa_PolicyInformation *info = NULL; struct dcerpc_binding_handle *b; + const char *account = r->in.admin_account; + const char *domain = r->in.admin_domain; + const char *password = r->in.admin_password; + bool use_kerberos = r->in.use_kerberos; + + if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) { + account = ""; + domain = ""; + password = NULL; + use_kerberos = false; + } status = libnet_join_connect_dc_ipc(r->in.dc_name, - r->in.admin_account, - r->in.admin_domain, - r->in.admin_password, - r->in.use_kerberos, + account, + domain, + password, + use_kerberos, cli); if (!NT_STATUS_IS_OK(status)) { goto done; @@ -1121,16 +1132,19 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, struct cli_state *cli) { TALLOC_CTX *frame = talloc_stackframe(); - struct rpc_pipe_client *netlogon_pipe = NULL; + struct rpc_pipe_client *authenticate_pipe = NULL; + struct rpc_pipe_client *passwordset_pipe = NULL; struct cli_credentials *cli_creds; struct netlogon_creds_cli_context *netlogon_creds = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + uint32_t netlogon_flags = 0; size_t len = 0; bool ok; DATA_BLOB new_trust_blob = data_blob_null; NTSTATUS status; status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, - &netlogon_pipe); + &authenticate_pipe); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; @@ -1167,7 +1181,7 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, CRED_SPECIFIED); status = rpccli_create_netlogon_creds_ctx( - cli_creds, netlogon_pipe->desthost, r->in.msg_ctx, + cli_creds, authenticate_pipe->desthost, r->in.msg_ctx, frame, &netlogon_creds); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); @@ -1182,6 +1196,29 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, return status; } + status = netlogon_creds_cli_get(netlogon_creds, frame, &creds); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + netlogon_flags = creds->negotiate_flags; + TALLOC_FREE(creds); + + if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) { + status = cli_rpc_pipe_open_schannel_with_creds(cli, + &ndr_table_netlogon, + NCACN_NP, + netlogon_creds, + &passwordset_pipe); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + } else { + passwordset_pipe = authenticate_pipe; + } + len = strlen(r->in.machine_password); ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16, r->in.machine_password, len, @@ -1197,7 +1234,7 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, } status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds, - netlogon_pipe->binding_handle, + passwordset_pipe->binding_handle, &new_trust_blob, NULL); /* new_version */ if (!NT_STATUS_IS_OK(status)) { From 7e83d1489406cd53d72097e40bf02295c88ea61e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 17 Nov 2017 11:35:19 +0100 Subject: [PATCH 88/92] winbind: Replace winbind_event_context with server_event_context There's no point in having two global event contexts BUG: https://bugzilla.samba.org/show_bug.cgi?id=13150 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/winbindd/idmap_ldap.c | 2 +- source3/winbindd/idmap_rfc2307.c | 2 +- source3/winbindd/winbindd.c | 58 +++++++++++----------- source3/winbindd/winbindd_cm.c | 4 +- source3/winbindd/winbindd_cred_cache.c | 14 +++--- source3/winbindd/winbindd_dual.c | 16 +++--- source3/winbindd/winbindd_irpc.c | 10 ++-- source3/winbindd/winbindd_misc.c | 2 +- source3/winbindd/winbindd_pam_auth.c | 2 +- source3/winbindd/winbindd_pam_auth_crap.c | 2 +- source3/winbindd/winbindd_pam_chauthtok.c | 2 +- .../winbindd/winbindd_pam_chng_pswd_auth_crap.c | 2 +- source3/winbindd/winbindd_pam_logoff.c | 2 +- source3/winbindd/winbindd_util.c | 2 +- 14 files changed, 60 insertions(+), 60 deletions(-) diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 39aa8330735..6765dfc217a 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -455,7 +455,7 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom) /* get_credentials deals with setting up creds */ - ret = smbldap_init(ctx, winbind_event_context(), ctx->url, + ret = smbldap_init(ctx, server_event_context(), ctx->url, false, NULL, NULL, &ctx->smbldap_state); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url)); diff --git a/source3/winbindd/idmap_rfc2307.c b/source3/winbindd/idmap_rfc2307.c index 668a7a4e28e..264ccb034fb 100644 --- a/source3/winbindd/idmap_rfc2307.c +++ b/source3/winbindd/idmap_rfc2307.c @@ -193,7 +193,7 @@ static NTSTATUS idmap_rfc2307_init_ldap(struct idmap_rfc2307_context *ctx, } /* assume anonymous if we don't have a specified user */ - ret = smbldap_init(mem_ctx, winbind_event_context(), url, + ret = smbldap_init(mem_ctx, server_event_context(), url, (user_dn == NULL), user_dn, secret, &ctx->smbldap_state); SAFE_FREE(secret); diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index f24451649b6..981888068c1 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -91,7 +91,7 @@ struct messaging_context *winbind_messaging_context(void) * Note we MUST use the NULL context here, not the autofree context, * to avoid side effects in forked children exiting. */ - msg = messaging_init(NULL, winbind_event_context()); + msg = messaging_init(NULL, server_event_context()); if (msg == NULL) { smb_panic("Could not init winbindd's messaging context.\n"); } @@ -124,7 +124,7 @@ struct imessaging_context *winbind_imessaging_context(void) * Note we MUST use the NULL context here, not the autofree context, * to avoid side effects in forked children exiting. */ - msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context()); + msg = imessaging_init(NULL, lp_ctx, myself, server_event_context()); talloc_unlink(NULL, lp_ctx); if (msg == NULL) { @@ -307,14 +307,14 @@ bool winbindd_setup_sig_term_handler(bool parent) struct tevent_signal *se; bool *is_parent; - is_parent = talloc(winbind_event_context(), bool); + is_parent = talloc(server_event_context(), bool); if (!is_parent) { return false; } *is_parent = parent; - se = tevent_add_signal(winbind_event_context(), + se = tevent_add_signal(server_event_context(), is_parent, SIGTERM, 0, winbindd_sig_term_handler, @@ -325,7 +325,7 @@ bool winbindd_setup_sig_term_handler(bool parent) return false; } - se = tevent_add_signal(winbind_event_context(), + se = tevent_add_signal(server_event_context(), is_parent, SIGINT, 0, winbindd_sig_term_handler, @@ -336,7 +336,7 @@ bool winbindd_setup_sig_term_handler(bool parent) return false; } - se = tevent_add_signal(winbind_event_context(), + se = tevent_add_signal(server_event_context(), is_parent, SIGQUIT, 0, winbindd_sig_term_handler, @@ -357,7 +357,7 @@ bool winbindd_setup_stdin_handler(bool parent, bool foreground) if (foreground) { struct stat st; - is_parent = talloc(winbind_event_context(), bool); + is_parent = talloc(server_event_context(), bool); if (!is_parent) { return false; } @@ -373,7 +373,7 @@ bool winbindd_setup_stdin_handler(bool parent, bool foreground) return false; } if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { - tevent_add_fd(winbind_event_context(), + tevent_add_fd(server_event_context(), is_parent, 0, TEVENT_FD_READ, @@ -405,15 +405,15 @@ bool winbindd_setup_sig_hup_handler(const char *lfile) char *file = NULL; if (lfile) { - file = talloc_strdup(winbind_event_context(), + file = talloc_strdup(server_event_context(), lfile); if (!file) { return false; } } - se = tevent_add_signal(winbind_event_context(), - winbind_event_context(), + se = tevent_add_signal(server_event_context(), + server_event_context(), SIGHUP, 0, winbindd_sig_hup_handler, file); @@ -442,8 +442,8 @@ static bool winbindd_setup_sig_chld_handler(void) { struct tevent_signal *se; - se = tevent_add_signal(winbind_event_context(), - winbind_event_context(), + se = tevent_add_signal(server_event_context(), + server_event_context(), SIGCHLD, 0, winbindd_sig_chld_handler, NULL); @@ -468,8 +468,8 @@ static bool winbindd_setup_sig_usr2_handler(void) { struct tevent_signal *se; - se = tevent_add_signal(winbind_event_context(), - winbind_event_context(), + se = tevent_add_signal(server_event_context(), + server_event_context(), SIGUSR2, 0, winbindd_sig_usr2_handler, NULL); @@ -734,7 +734,7 @@ static void process_request(struct winbindd_cli_state *state) DEBUG(10, ("process_request: Handling async request %d:%s\n", (int)state->pid, state->cmd_name)); - req = atable->send_req(state->mem_ctx, winbind_event_context(), + req = atable->send_req(state->mem_ctx, server_event_context(), state, state->request); if (req == NULL) { DEBUG(0, ("process_request: atable->send failed for " @@ -828,7 +828,7 @@ static void request_finished(struct winbindd_cli_state *state) TALLOC_FREE(state->request); - req = wb_resp_write_send(state, winbind_event_context(), + req = wb_resp_write_send(state, server_event_context(), state->out_queue, state->sock, state->response); if (req == NULL) { @@ -869,7 +869,7 @@ static void winbind_client_response_written(struct tevent_req *req) state->cmd_name = "no request"; state->recv_fn = NULL; - req = wb_req_read_send(state, winbind_event_context(), state->sock, + req = wb_req_read_send(state, server_event_context(), state->sock, WINBINDD_MAX_EXTRA_DATA); if (req == NULL) { remove_client(state); @@ -937,7 +937,7 @@ static void new_connection(int listen_sock, bool privileged) state->privileged = privileged; - req = wb_req_read_send(state, winbind_event_context(), state->sock, + req = wb_req_read_send(state, server_event_context(), state->sock, WINBINDD_MAX_EXTRA_DATA); if (req == NULL) { TALLOC_FREE(state); @@ -977,7 +977,7 @@ static void winbind_client_request_read(struct tevent_req *req) return; } - req = wait_for_read_send(state, winbind_event_context(), state->sock, + req = wait_for_read_send(state, server_event_context(), state->sock, true); if (req == NULL) { DEBUG(0, ("winbind_client_request_read[%d:%s]:" @@ -1239,7 +1239,7 @@ static bool winbindd_setup_listeners(void) int rc; char *socket_path; - pub_state = talloc(winbind_event_context(), + pub_state = talloc(server_event_context(), struct winbindd_listen_state); if (!pub_state) { goto failed; @@ -1256,7 +1256,7 @@ static bool winbindd_setup_listeners(void) goto failed; } - fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd, + fde = tevent_add_fd(server_event_context(), pub_state, pub_state->fd, TEVENT_FD_READ, winbindd_listen_fde_handler, pub_state); if (fde == NULL) { @@ -1265,7 +1265,7 @@ static bool winbindd_setup_listeners(void) } tevent_fd_set_auto_close(fde); - priv_state = talloc(winbind_event_context(), + priv_state = talloc(server_event_context(), struct winbindd_listen_state); if (!priv_state) { goto failed; @@ -1288,7 +1288,7 @@ static bool winbindd_setup_listeners(void) goto failed; } - fde = tevent_add_fd(winbind_event_context(), priv_state, + fde = tevent_add_fd(server_event_context(), priv_state, priv_state->fd, TEVENT_FD_READ, winbindd_listen_fde_handler, priv_state); if (fde == NULL) { @@ -1297,7 +1297,7 @@ static bool winbindd_setup_listeners(void) } tevent_fd_set_auto_close(fde); - winbindd_scrub_clients_handler(winbind_event_context(), NULL, + winbindd_scrub_clients_handler(server_event_context(), NULL, timeval_current(), NULL); return true; failed: @@ -1412,7 +1412,7 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx, smb_nscd_flush_group_cache(); if (lp_allow_trusted_domains()) { - if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(), + if (tevent_add_timer(server_event_context(), NULL, timeval_zero(), rescan_trusted_domains, NULL) == NULL) { DEBUG(0, ("Could not trigger rescan_trusted_domains()\n")); exit(1); @@ -1777,7 +1777,7 @@ int main(int argc, const char **argv) */ status = reinit_after_fork(winbind_messaging_context(), - winbind_event_context(), + server_event_context(), false, NULL); if (!NT_STATUS_IS_OK(status)) { exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status)); @@ -1807,7 +1807,7 @@ int main(int argc, const char **argv) rpc_lsarpc_init(NULL); rpc_samr_init(NULL); - winbindd_init_addrchange(NULL, winbind_event_context(), + winbindd_init_addrchange(NULL, server_event_context(), winbind_messaging_context()); /* setup listen sockets */ @@ -1828,7 +1828,7 @@ int main(int argc, const char **argv) while (1) { frame = talloc_stackframe(); - if (tevent_loop_once(winbind_event_context()) == -1) { + if (tevent_loop_once(server_event_context()) == -1) { DEBUG(1, ("tevent_loop_once() failed: %s\n", strerror(errno))); return 1; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 1fa688241dd..cece96e7166 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -428,7 +428,7 @@ void set_domain_offline(struct winbindd_domain *domain) calc_new_online_timeout_check(domain); - domain->check_online_event = tevent_add_timer(winbind_event_context(), + domain->check_online_event = tevent_add_timer(server_event_context(), NULL, timeval_current_ofs(domain->check_online_timeout,0), check_domain_online_handler, @@ -604,7 +604,7 @@ void set_domain_online_request(struct winbindd_domain *domain) TALLOC_FREE(domain->check_online_event); - domain->check_online_event = tevent_add_timer(winbind_event_context(), + domain->check_online_event = tevent_add_timer(server_event_context(), NULL, tev, check_domain_online_handler, diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index ed2dd10c91d..5e019dfce0c 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -284,7 +284,7 @@ static void krb5_ticket_refresh_handler(struct tevent_context *event_ctx, if (entry->refresh_time == 0) { entry->refresh_time = new_start; } - entry->event = tevent_add_timer(winbind_event_context(), entry, + entry->event = tevent_add_timer(server_event_context(), entry, timeval_set(new_start, 0), krb5_ticket_refresh_handler, entry); @@ -383,7 +383,7 @@ static void krb5_ticket_gain_handler(struct tevent_context *event_ctx, if (entry->refresh_time == 0) { entry->refresh_time = t.tv_sec; } - entry->event = tevent_add_timer(winbind_event_context(), + entry->event = tevent_add_timer(server_event_context(), entry, t, krb5_ticket_refresh_handler, @@ -402,7 +402,7 @@ static void add_krb5_ticket_gain_handler_event(struct WINBINDD_CCACHE_ENTRY *ent struct timeval t) { entry->refresh_time = 0; - entry->event = tevent_add_timer(winbind_event_context(), + entry->event = tevent_add_timer(server_event_context(), entry, t, krb5_ticket_gain_handler, @@ -422,13 +422,13 @@ void ccache_regain_all_now(void) * the event has the krb5_ticket_gain_handler */ if (cur->refresh_time == 0) { - new_event = tevent_add_timer(winbind_event_context(), + new_event = tevent_add_timer(server_event_context(), cur, t, krb5_ticket_gain_handler, cur); } else { - new_event = tevent_add_timer(winbind_event_context(), + new_event = tevent_add_timer(server_event_context(), cur, t, krb5_ticket_refresh_handler, @@ -545,7 +545,7 @@ NTSTATUS add_ccache_to_list(const char *princ_name, if (!entry->refresh_time) { entry->refresh_time = t.tv_sec; } - entry->event = tevent_add_timer(winbind_event_context(), + entry->event = tevent_add_timer(server_event_context(), entry, t, krb5_ticket_refresh_handler, @@ -643,7 +643,7 @@ NTSTATUS add_ccache_to_list(const char *princ_name, if (entry->refresh_time == 0) { entry->refresh_time = t.tv_sec; } - entry->event = tevent_add_timer(winbind_event_context(), + entry->event = tevent_add_timer(server_event_context(), entry, t, krb5_ticket_refresh_handler, diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 97e1c88a636..d36eb0525c9 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -175,7 +175,7 @@ static void wb_child_request_trigger(struct tevent_req *req, return; } - subreq = wb_simple_trans_send(state, winbind_event_context(), NULL, + subreq = wb_simple_trans_send(state, server_event_context(), NULL, state->child->sock, state->request); if (tevent_req_nomem(subreq, req)) { return; @@ -968,7 +968,7 @@ static void account_lockout_policy_handler(struct tevent_context *ctx, nt_errstr(result))); } - child->lockout_policy_event = tevent_add_timer(winbind_event_context(), NULL, + child->lockout_policy_event = tevent_add_timer(server_event_context(), NULL, timeval_current_ofs(3600, 0), account_lockout_policy_handler, child); @@ -1130,7 +1130,7 @@ static void machine_password_change_handler(struct tevent_context *ctx, } done: - child->machine_password_change_event = tevent_add_timer(winbind_event_context(), NULL, + child->machine_password_change_event = tevent_add_timer(server_event_context(), NULL, next_change, machine_password_change_handler, child); @@ -1251,7 +1251,7 @@ NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself, status = reinit_after_fork( winbind_messaging_context(), - winbind_event_context(), + server_event_context(), true, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); @@ -1556,7 +1556,7 @@ static bool fork_domain_child(struct winbindd_child *child) } child->lockout_policy_event = tevent_add_timer( - winbind_event_context(), NULL, timeval_zero(), + server_event_context(), NULL, timeval_zero(), account_lockout_policy_handler, child); } @@ -1570,13 +1570,13 @@ static bool fork_domain_child(struct winbindd_child *child) if (calculate_next_machine_pwd_change(child->domain->name, &next_change)) { child->machine_password_change_event = tevent_add_timer( - winbind_event_context(), NULL, next_change, + server_event_context(), NULL, next_change, machine_password_change_handler, child); } } - fde = tevent_add_fd(winbind_event_context(), NULL, state.cli.sock, + fde = tevent_add_fd(server_event_context(), NULL, state.cli.sock, TEVENT_FD_READ, child_handler, &state); if (fde == NULL) { DEBUG(1, ("tevent_add_fd failed\n")); @@ -1588,7 +1588,7 @@ static bool fork_domain_child(struct winbindd_child *child) int ret; TALLOC_CTX *frame = talloc_stackframe(); - ret = tevent_loop_once(winbind_event_context()); + ret = tevent_loop_once(server_event_context()); if (ret != 0) { DEBUG(1, ("tevent_loop_once failed: %s\n", strerror(errno))); diff --git a/source3/winbindd/winbindd_irpc.c b/source3/winbindd/winbindd_irpc.c index fface90cfad..d0d68c89411 100644 --- a/source3/winbindd/winbindd_irpc.c +++ b/source3/winbindd/winbindd_irpc.c @@ -123,7 +123,7 @@ static NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *m DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords called\n")); return wb_irpc_forward_rpc_call(msg, msg, - winbind_event_context(), + server_event_context(), req, NDR_WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS, "winbind_DsrUpdateReadOnlyServerDnsRecords", domain, IRPC_CALL_TIMEOUT); @@ -206,7 +206,7 @@ static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg, DEBUG(5, ("wb_irpc_SamLogon called\n")); return wb_irpc_forward_rpc_call(msg, msg, - winbind_event_context(), + server_event_context(), req, NDR_WINBIND_SAMLOGON, "winbind_SamLogon", domain, IRPC_CALL_TIMEOUT); @@ -266,7 +266,7 @@ static NTSTATUS wb_irpc_LogonControl(struct irpc_message *msg, TALLOC_FREE(frame); return wb_irpc_forward_rpc_call(msg, msg, - winbind_event_context(), + server_event_context(), req, NDR_WINBIND_LOGONCONTROL, "winbind_LogonControl", domain, 45 /* timeout */); @@ -306,7 +306,7 @@ static NTSTATUS wb_irpc_GetForestTrustInformation(struct irpc_message *msg, DEBUG(5, ("wb_irpc_GetForestTrustInformation called\n")); return wb_irpc_forward_rpc_call(msg, msg, - winbind_event_context(), + server_event_context(), req, NDR_WINBIND_GETFORESTTRUSTINFORMATION, "winbind_GetForestTrustInformation", domain, 45 /* timeout */); @@ -324,7 +324,7 @@ static NTSTATUS wb_irpc_SendToSam(struct irpc_message *msg, DEBUG(5, ("wb_irpc_SendToSam called\n")); return wb_irpc_forward_rpc_call(msg, msg, - winbind_event_context(), + server_event_context(), req, NDR_WINBIND_SENDTOSAM, "winbind_SendToSam", domain, IRPC_CALL_TIMEOUT); diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 30730dcec12..6cf33420768 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -277,7 +277,7 @@ void winbindd_domain_info(struct winbindd_cli_state *cli) * Send a ping down. This implicitly initializes the domain. */ - req = wb_domain_request_send(state, winbind_event_context(), + req = wb_domain_request_send(state, server_event_context(), domain, &state->ping_request); if (req == NULL) { DEBUG(3, ("wb_domain_request_send failed\n")); diff --git a/source3/winbindd/winbindd_pam_auth.c b/source3/winbindd/winbindd_pam_auth.c index 4f963a32818..7ff44888975 100644 --- a/source3/winbindd/winbindd_pam_auth.c +++ b/source3/winbindd/winbindd_pam_auth.c @@ -81,7 +81,7 @@ struct tevent_req *winbindd_pam_auth_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - subreq = wb_domain_request_send(state, winbind_event_context(), domain, + subreq = wb_domain_request_send(state, server_event_context(), domain, request); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c index e6a47c86785..cfeafbcfda8 100644 --- a/source3/winbindd/winbindd_pam_auth_crap.c +++ b/source3/winbindd/winbindd_pam_auth_crap.c @@ -93,7 +93,7 @@ struct tevent_req *winbindd_pam_auth_crap_send( fstrcpy(request->data.auth_crap.workstation, lp_netbios_name()); } - subreq = wb_domain_request_send(state, winbind_event_context(), domain, + subreq = wb_domain_request_send(state, server_event_context(), domain, request); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/winbindd/winbindd_pam_chauthtok.c b/source3/winbindd/winbindd_pam_chauthtok.c index 8ffbc29b973..0d749fbcecd 100644 --- a/source3/winbindd/winbindd_pam_chauthtok.c +++ b/source3/winbindd/winbindd_pam_chauthtok.c @@ -79,7 +79,7 @@ struct tevent_req *winbindd_pam_chauthtok_send( return tevent_req_post(req, ev); } - subreq = wb_domain_request_send(state, winbind_event_context(), + subreq = wb_domain_request_send(state, server_event_context(), contact_domain, request); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c b/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c index 9133a91fa50..e9ee0ab63ce 100644 --- a/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c +++ b/source3/winbindd/winbindd_pam_chng_pswd_auth_crap.c @@ -73,7 +73,7 @@ struct tevent_req *winbindd_pam_chng_pswd_auth_crap_send( return tevent_req_post(req, ev); } - subreq = wb_domain_request_send(state, winbind_event_context(), + subreq = wb_domain_request_send(state, server_event_context(), domain, request); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/winbindd/winbindd_pam_logoff.c b/source3/winbindd/winbindd_pam_logoff.c index b3c60adf857..b5b7840f99c 100644 --- a/source3/winbindd/winbindd_pam_logoff.c +++ b/source3/winbindd/winbindd_pam_logoff.c @@ -94,7 +94,7 @@ struct tevent_req *winbindd_pam_logoff_send(TALLOC_CTX *mem_ctx, break; } - subreq = wb_domain_request_send(state, winbind_event_context(), domain, + subreq = wb_domain_request_send(state, server_event_context(), domain, request); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 6eed02e9fe8..7b443c79fa5 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -321,7 +321,7 @@ static void add_trusted_domains( struct winbindd_domain *domain ) state->request.length = sizeof(state->request); state->request.cmd = WINBINDD_LIST_TRUSTDOM; - req = wb_domain_request_send(state, winbind_event_context(), + req = wb_domain_request_send(state, server_event_context(), domain, &state->request); if (req == NULL) { DEBUG(1, ("wb_domain_request_send failed\n")); From e1f12acc13a3cc004518ac3460c6000ea0b95115 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 17 Nov 2017 11:37:30 +0100 Subject: [PATCH 89/92] winbind: Remove winbind_event_context BUG: https://bugzilla.samba.org/show_bug.cgi?id=13150 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/torture/torture.c | 9 --------- source3/winbindd/winbindd.c | 19 ------------------- source3/winbindd/winbindd_proto.h | 1 - 3 files changed, 29 deletions(-) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 360adad5953..481154fc36f 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -11588,15 +11588,6 @@ static struct { { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 }, {NULL, NULL, 0}}; -/* - * dummy function to satisfy linker dependency - */ -struct tevent_context *winbind_event_context(void); -struct tevent_context *winbind_event_context(void) -{ - return NULL; -} - /**************************************************************************** run a specified test or "ALL" ****************************************************************************/ diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 981888068c1..75f9dbb142e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -60,25 +60,6 @@ static bool interactive = False; extern bool override_logfile; -struct tevent_context *winbind_event_context(void) -{ - static struct tevent_context *ev = NULL; - - if (ev != NULL) { - return ev; - } - - /* - * Note we MUST use the NULL context here, not the autofree context, - * to avoid side effects in forked children exiting. - */ - ev = samba_tevent_context_init(NULL); - if (ev == NULL) { - smb_panic("Could not init winbindd's messaging context.\n"); - } - return ev; -} - struct messaging_context *winbind_messaging_context(void) { static struct messaging_context *msg = NULL; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 46e6530105a..ccf39e57508 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -34,7 +34,6 @@ bool winbindd_setup_sig_hup_handler(const char *lfile); bool winbindd_use_idmap_cache(void); bool winbindd_use_cache(void); char *get_winbind_priv_pipe_dir(void); -struct tevent_context *winbind_event_context(void); /* The following definitions come from winbindd/winbindd_ads.c */ From d8a01d09c13728f36107f6eb94ecb7653706a4db Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 17 Nov 2017 11:42:34 +0100 Subject: [PATCH 90/92] winbind: winbind_messaging_context -> server_messaging_context Don't use winbind_messaging_context anymore. This fixes a bug analysed by Peter Somogyi : If a parent winbind forks, it only called reinit_after_fork on winbind_messaging_context. On the other hand, deep in dbwrap_open we use server_messaging_context(). This is not reinitialized by winbind_reinit_after fork, so the parent and child share a ctdb connection. This is invalid, because replies from ctdb end up in the wrong process. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13150 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/winbindd/winbindd.c | 16 ++++++++-------- source3/winbindd/winbindd_cm.c | 32 ++++++++++++++++---------------- source3/winbindd/winbindd_dual.c | 34 +++++++++++++++++----------------- source3/winbindd/winbindd_dual_srv.c | 6 +++--- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 75f9dbb142e..679faefe2fd 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -240,7 +240,7 @@ static void terminate(bool is_parent) #endif if (is_parent) { - struct messaging_context *msg = winbind_messaging_context(); + struct messaging_context *msg = server_messaging_context(); struct server_id self = messaging_server_id(msg); serverid_deregister(self); pidfile_unlink(lp_pid_directory(), "winbindd"); @@ -1350,9 +1350,9 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx, MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus); /* Handle domain online/offline messages for domains */ - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline); - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online); messaging_register(msg_ctx, NULL, @@ -1663,7 +1663,7 @@ int main(int argc, const char **argv) /* Initialise messaging system */ - if (winbind_messaging_context() == NULL) { + if (server_messaging_context() == NULL) { exit(1); } @@ -1757,7 +1757,7 @@ int main(int argc, const char **argv) * winbindd-specific resources we must free yet. JRA. */ - status = reinit_after_fork(winbind_messaging_context(), + status = reinit_after_fork(server_messaging_context(), server_event_context(), false, NULL); if (!NT_STATUS_IS_OK(status)) { @@ -1774,9 +1774,9 @@ int main(int argc, const char **argv) exit_daemon(nt_errstr(status), map_errno_from_nt_status(status)); } - winbindd_register_handlers(winbind_messaging_context(), !Fork); + winbindd_register_handlers(server_messaging_context(), !Fork); - if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) { + if (!messaging_parent_dgm_cleanup_init(server_messaging_context())) { exit(1); } @@ -1789,7 +1789,7 @@ int main(int argc, const char **argv) rpc_samr_init(NULL); winbindd_init_addrchange(NULL, server_event_context(), - winbind_messaging_context()); + server_messaging_context()); /* setup listen sockets */ diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index cece96e7166..f88c704c014 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -223,10 +223,10 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) if (domain->dc_probe_pid != (pid_t)0) { /* Parent */ - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_TRY_TO_GO_ONLINE, msg_try_to_go_online); - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_FAILED_TO_GO_ONLINE, msg_failed_to_go_online); return True; @@ -247,7 +247,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n", nt_errstr(status))); - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE, (const uint8_t *)domain->name, @@ -259,7 +259,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) mem_ctx = talloc_init("fork_child_dc_connect"); if (!mem_ctx) { DEBUG(0,("talloc_init failed.\n")); - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE, (const uint8_t *)domain->name, @@ -269,7 +269,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0)) || (num_dcs == 0)) { /* Still offline ? Can't find DC's. */ - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE, (const uint8_t *)domain->name, @@ -280,7 +280,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) /* We got a DC. Send a message to our parent to get it to try and do the same. */ - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE, (const uint8_t *)domain->name, @@ -444,7 +444,7 @@ void set_domain_offline(struct winbindd_domain *domain) /* Send a message to the parent that the domain is offline. */ if (parent_pid > 1 && !domain->internal) { - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_DOMAIN_OFFLINE, (uint8_t *)domain->name, @@ -458,7 +458,7 @@ void set_domain_offline(struct winbindd_domain *domain) struct winbindd_child *idmap = idmap_child(); if ( idmap->pid != 0 ) { - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(idmap->pid), MSG_WINBIND_OFFLINE, (const uint8_t *)domain->name, @@ -521,16 +521,16 @@ static void set_domain_online(struct winbindd_domain *domain) TALLOC_FREE(domain->check_online_event); /* Ensure we ignore any pending child messages. */ - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_TRY_TO_GO_ONLINE, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL); domain->online = True; /* Send a message to the parent that the domain is online. */ if (parent_pid > 1 && !domain->internal) { - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_DOMAIN_ONLINE, (uint8_t *)domain->name, @@ -544,7 +544,7 @@ static void set_domain_online(struct winbindd_domain *domain) struct winbindd_child *idmap = idmap_child(); if ( idmap->pid != 0 ) { - messaging_send_buf(winbind_messaging_context(), + messaging_send_buf(server_messaging_context(), pid_to_procid(idmap->pid), MSG_WINBIND_ONLINE, (const uint8_t *)domain->name, @@ -1420,7 +1420,7 @@ static bool dcip_check_name(TALLOC_CTX *mem_ctx, } #endif - status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name, + status = nbt_getdc(server_messaging_context(), 10, pss, domain->name, &domain->sid, nt_version, mem_ctx, &nt_version, &dc_name, NULL); if (NT_STATUS_IS_OK(status)) { @@ -1789,7 +1789,7 @@ NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx, session_info, NULL, NULL, - winbind_messaging_context(), + server_messaging_context(), &cli); } else { status = rpc_pipe_open_internal(mem_ctx, @@ -1797,7 +1797,7 @@ NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx, session_info, NULL, NULL, - winbind_messaging_context(), + server_messaging_context(), &cli); } if (!NT_STATUS_IS_OK(status)) { @@ -3211,7 +3211,7 @@ static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain, enum dcerpc_transport_t transport, struct rpc_pipe_client **cli) { - struct messaging_context *msg_ctx = winbind_messaging_context(); + struct messaging_context *msg_ctx = server_messaging_context(); struct winbindd_cm_conn *conn; NTSTATUS result; struct cli_credentials *creds = NULL; diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index d36eb0525c9..3b25e53e786 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1051,7 +1051,7 @@ static void machine_password_change_handler(struct tevent_context *ctx, struct timeval now, void *private_data) { - struct messaging_context *msg_ctx = winbind_messaging_context(); + struct messaging_context *msg_ctx = server_messaging_context(); struct winbindd_child *child = (struct winbindd_child *)private_data; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -1250,7 +1250,7 @@ NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself, NTSTATUS status; status = reinit_after_fork( - winbind_messaging_context(), + server_messaging_context(), server_event_context(), true, NULL); if (!NT_STATUS_IS_OK(status)) { @@ -1275,26 +1275,26 @@ NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself, CatchChild(); /* Don't handle the same messages as our parent. */ - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_SMB_CONF_UPDATED, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_SHUTDOWN, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_OFFLINE, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_ONLINE, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_ONLINESTATUS, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_DUMP_EVENT_LIST, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_DUMP_DOMAIN_LIST, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_DEBUG, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_DOMAIN_OFFLINE, NULL); - messaging_deregister(winbind_messaging_context(), + messaging_deregister(server_messaging_context(), MSG_WINBIND_DOMAIN_ONLINE, NULL); /* We have destroyed all events in the winbindd_event_context @@ -1492,15 +1492,15 @@ static bool fork_domain_child(struct winbindd_child *child) } /* Handle online/offline messages. */ - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_OFFLINE, child_msg_offline); - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_ONLINE, child_msg_online); - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_DUMP_EVENT_LIST, child_msg_dump_event_list); - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_DEBUG, debug_message); - messaging_register(winbind_messaging_context(), NULL, + messaging_register(server_messaging_context(), NULL, MSG_WINBIND_IP_DROPPED, winbind_msg_ip_dropped); diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 9fb15e9b0ab..797a9d95493 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -523,7 +523,7 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r) struct dcerpc_binding_handle *b; if (domain == NULL) { - return dsgetdcname(p->mem_ctx, winbind_messaging_context(), + return dsgetdcname(p->mem_ctx, server_messaging_context(), r->in.domain_name, r->in.domain_guid, r->in.site_name ? r->in.site_name : "", r->in.flags, @@ -715,7 +715,7 @@ NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p, NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p, struct wbint_ChangeMachineAccount *r) { - struct messaging_context *msg_ctx = winbind_messaging_context(); + struct messaging_context *msg_ctx = server_messaging_context(); struct winbindd_domain *domain; NTSTATUS status; struct rpc_pipe_client *netlogon_pipe; @@ -1364,7 +1364,7 @@ static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p, struct winbindd_domain *domain, struct winbind_LogonControl *r) { - struct messaging_context *msg_ctx = winbind_messaging_context(); + struct messaging_context *msg_ctx = server_messaging_context(); NTSTATUS status; struct rpc_pipe_client *netlogon_pipe; struct cli_credentials *creds = NULL; From 050ca45dc7fc5bbab6e1c60b919ac0b1e9661e27 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 17 Nov 2017 11:47:37 +0100 Subject: [PATCH 91/92] winbind: Remove winbind_messaging_context BUG: https://bugzilla.samba.org/show_bug.cgi?id=13150 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Sat Nov 18 04:07:24 CET 2017 on sn-devel-144 --- source3/winbindd/winbindd.c | 19 ------------------- source3/winbindd/winbindd_proto.h | 1 - 2 files changed, 20 deletions(-) diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 679faefe2fd..ceb131e9b32 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -60,25 +60,6 @@ static bool interactive = False; extern bool override_logfile; -struct messaging_context *winbind_messaging_context(void) -{ - static struct messaging_context *msg = NULL; - - if (msg != NULL) { - return msg; - } - - /* - * Note we MUST use the NULL context here, not the autofree context, - * to avoid side effects in forked children exiting. - */ - msg = messaging_init(NULL, server_event_context()); - if (msg == NULL) { - smb_panic("Could not init winbindd's messaging context.\n"); - } - return msg; -} - struct imessaging_context *winbind_imessaging_context(void) { static struct imessaging_context *msg = NULL; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index ccf39e57508..83136996dd2 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -24,7 +24,6 @@ #define _WINBINDD_PROTO_H_ /* The following definitions come from winbindd/winbindd.c */ -struct messaging_context *winbind_messaging_context(void); struct imessaging_context *winbind_imessaging_context(void); void request_error(struct winbindd_cli_state *state); void request_ok(struct winbindd_cli_state *state); From 2a9193b3ea09748245f56ea31805e5c036f9b5d8 Mon Sep 17 00:00:00 2001 From: Fabian Fritz Date: Tue, 7 Nov 2017 22:45:23 +0100 Subject: [PATCH 92/92] Fix #12961 --- lib/ldb/tests/ldb_mod_op_test.c | 8 ++++---- lib/replace/wscript | 6 +++++- source3/wscript_build | 1 + third_party/cmocka/cmocka.h | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c index 48ad20c7662..1b0baee3038 100644 --- a/lib/ldb/tests/ldb_mod_op_test.c +++ b/lib/ldb/tests/ldb_mod_op_test.c @@ -1914,22 +1914,22 @@ static void test_ldb_modify_during_search(void **state, bool add_index, static void test_ldb_modify_during_indexed_search(void **state) { - return test_ldb_modify_during_search(state, true, false); + test_ldb_modify_during_search(state, true, false); } static void test_ldb_modify_during_unindexed_search(void **state) { - return test_ldb_modify_during_search(state, false, false); + test_ldb_modify_during_search(state, false, false); } static void test_ldb_rename_during_indexed_search(void **state) { - return test_ldb_modify_during_search(state, true, true); + test_ldb_modify_during_search(state, true, true); } static void test_ldb_rename_during_unindexed_search(void **state) { - return test_ldb_modify_during_search(state, false, true); + test_ldb_modify_during_search(state, false, true); } /* diff --git a/lib/replace/wscript b/lib/replace/wscript index 7436a90c003..548ead737f5 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -81,6 +81,8 @@ def configure(conf): conf.CHECK_HEADERS('sys/atomic.h') conf.CHECK_HEADERS('libgen.h') + if conf.CHECK_CFLAGS('-Wno-format-zero-length'): + conf.define('HAVE_WNO_FORMAT_ZERO_LENGTH', '1') if conf.CHECK_CFLAGS('-Wno-format-truncation'): conf.define('HAVE_WNO_FORMAT_TRUNCATION', '1') @@ -734,7 +736,9 @@ def build(bld): private_library=True, deps='crypt dl nsl socket rt attr' + extra_libs) - replace_test_cflags="-Wno-format-zero-length" + replace_test_cflags = "" + if bld.CONFIG_SET('HAVE_WNO_FORMAT_ZERO_LENGTH'): + replace_test_cflags += "-Wno-format-zero-length" if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): replace_test_cflags += " -Wno-format-truncation" bld.SAMBA_SUBSYSTEM('replace-test', diff --git a/source3/wscript_build b/source3/wscript_build index dc7a51cc97a..037ceeab910 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -569,6 +569,7 @@ bld.SAMBA3_SUBSYSTEM('SMBCONF_PARAM', PARAM_UTIL ldap lber + krb5 LOADPARM_CTX samba3core param_local.h diff --git a/third_party/cmocka/cmocka.h b/third_party/cmocka/cmocka.h index 72d6ae21c90..440686f3b3f 100644 --- a/third_party/cmocka/cmocka.h +++ b/third_party/cmocka/cmocka.h @@ -56,7 +56,7 @@ int __stdcall IsDebuggerPresent(); /* If __WORDSIZE is not set, try to figure it out and default to 32 bit. */ #ifndef __WORDSIZE -# if defined(__x86_64__) && !defined(__ILP32__) +# if (defined(__x86_64__) || defined(_LP64)) && !defined(__ILP32__) # define __WORDSIZE 64 # else # define __WORDSIZE 32