The branch, master has been updated via 8f42b8431ef s3: smbd: Allow fchmod from the NFS-style mode ACL in set_nt_acl() for a SMB2 POSIX handle. via 631e6aa0d02 smbd: bring back "smb3 unix extensions" option via b124c2e1823 smbd: factor out smb2_negotiate_context_process_posix() via 6e300ef7314 smbd: tweak POSIX check in smbd_do_qfilepathinfo() via 55d98b29eb2 smbd: check is POSIX is enabled on the fsp in fsinfo_unix_valid_level() via 01022d036f5 smbd: pass fsp to fsinfo_unix_valid_level() via bca6f0298fe smbd: pass fsp to smbd_do_qfsinfo() via 3f73bb591cf smbd: leave comment on broken SMB1 POSIX open handling of SMB_O_DIRECT from 0b74adb3f01 samba-tool: Improve help messages for "samba-tool domain auth policy"
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 8f42b8431efcdeee9e270423bab9e111775430c9 Author: Jeremy Allison <j...@samba.org> Date: Thu Mar 1 14:37:52 2018 -0800 s3: smbd: Allow fchmod from the NFS-style mode ACL in set_nt_acl() for a SMB2 POSIX handle. To set a mode, send a one-element ACL. Pair-Programmed-With: Ralph Boehme <s...@samba.org> Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Ralph Boehme <s...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Mon Nov 27 19:31:01 UTC 2023 on atb-devel-224 commit 631e6aa0d02756d6ebbc9dff5c9d81fdbca58d7f Author: Ralph Boehme <s...@samba.org> Date: Wed Nov 8 17:49:19 2023 +0100 smbd: bring back "smb3 unix extensions" option This basically reverts commit b3cae8dcf192f65031f143e5bb9135c895611d98 with a few important differences: * SMB3 UNIX extensions are always built, but disabled by default at runtime. * They are globally enabled in the fileserver test environment. * It's now a per-share option, so admins can selectively disable them on a per-share basis. This allows clients to detect early that a share doesn't support user mount requested POSIX and fail appropiately, passing the failure to the requesting application (mount command). Signed-off-by: Ralph Boehme <s...@samba.org> commit b124c2e1823d96e51d9d19cb2ccb0286b923ac8d Author: Ralph Boehme <s...@samba.org> Date: Wed Nov 22 12:53:36 2023 +0100 smbd: factor out smb2_negotiate_context_process_posix() No change in behaviour. Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 6e300ef73147e6549748593ce168e9763cd567be Author: Ralph Boehme <s...@samba.org> Date: Mon Nov 13 10:36:14 2023 +0100 smbd: tweak POSIX check in smbd_do_qfilepathinfo() This check is only needed for SMB2, so check for that, and in the SMB2 codepath we'll always have a valid fsp, so we can drop that check. Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 55d98b29eb294542cc4947573f233e0d5e6966cb Author: Ralph Boehme <s...@samba.org> Date: Mon Nov 13 10:35:30 2023 +0100 smbd: check is POSIX is enabled on the fsp in fsinfo_unix_valid_level() Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 01022d036f5c9c8296d9174240a58e437c84f848 Author: Ralph Boehme <s...@samba.org> Date: Mon Nov 13 08:04:33 2023 +0100 smbd: pass fsp to fsinfo_unix_valid_level() We need the fsp down in fsinfo_unix_valid_level(), pass it down. Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit bca6f0298fe7230bbf54950dab4329dee6cc9a51 Author: Ralph Boehme <s...@samba.org> Date: Mon Nov 13 07:43:11 2023 +0100 smbd: pass fsp to smbd_do_qfsinfo() We need the fsp down in fsinfo_unix_valid_level(), start passing it down. Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 3f73bb591cf0ab4e7e305c9b58727790e54b32ed Author: Ralph Boehme <s...@samba.org> Date: Fri Nov 24 16:29:57 2023 +0100 smbd: leave comment on broken SMB1 POSIX open handling of SMB_O_DIRECT Since e0814dc5082dd4ecca8a155e0ce24b073158fd92 the passed in attributes get replaced by the mode in create_file_default(). As FILE_FLAG_NO_BUFFERING is never checked when doing the final IO, it doesn't really matter. Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: WHATSNEW.txt | 2 +- .../smbdotconf/protocol/smb3unixextensions.xml | 9 ++ selftest/target/Samba3.pm | 1 + source3/param/loadparm.c | 8 +- source3/smbd/globals.h | 1 + source3/smbd/smb1_trans2.c | 7 ++ source3/smbd/smb2_create.c | 4 +- source3/smbd/smb2_getinfo.c | 1 + source3/smbd/smb2_negprot.c | 97 +++++++++++++--------- source3/smbd/smb2_nttrans.c | 69 ++++++++++++++- source3/smbd/smb2_trans2.c | 26 ++++-- 11 files changed, 175 insertions(+), 50 deletions(-) create mode 100644 docs-xml/smbdotconf/protocol/smb3unixextensions.xml Changeset truncated at 500 lines: diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 2bd3f02e1dc..12dff08271c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -57,7 +57,7 @@ smb.conf changes Parameter Name Description Default -------------- ----------- ------- - smb3 unix extensions removed always offered + smb3 unix extensions Per share - KNOWN ISSUES diff --git a/docs-xml/smbdotconf/protocol/smb3unixextensions.xml b/docs-xml/smbdotconf/protocol/smb3unixextensions.xml new file mode 100644 index 00000000000..4c0319976a7 --- /dev/null +++ b/docs-xml/smbdotconf/protocol/smb3unixextensions.xml @@ -0,0 +1,9 @@ +<samba:parameter name="smb3 unix extensions" + context="S" + type="boolean" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> + <description> + <para>Experimental SMB 3.1.1 Unix Extensions.</para> + </description> + <value type="default">no</value> +</samba:parameter> diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index d56f12ee57a..4218a54358b 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1855,6 +1855,7 @@ sub setup_fileserver my $ip4 = Samba::get_ipv4_addr("FILESERVER"); my $fileserver_options = " + smb3 unix extensions = yes kernel change notify = yes spotlight backend = elasticsearch elasticsearch:address = $ip4 diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 6b2f23ce633..797baa66309 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4680,6 +4680,12 @@ void widelinks_warning(int snum) "These parameters are incompatible. " "Wide links will be disabled for this share.\n", lp_const_servicename(snum)); + } else if (lp_smb3_unix_extensions(snum)) { + DBG_ERR("Share '%s' has wide links and SMB3 Unix " + "extensions enabled. " + "These parameters are incompatible. " + "Wide links will be disabled for this share.\n", + lp_const_servicename(snum)); } } } @@ -4687,7 +4693,7 @@ void widelinks_warning(int snum) bool lp_widelinks(int snum) { /* wide links is always incompatible with unix extensions */ - if (lp_smb1_unix_extensions()) { + if (lp_smb1_unix_extensions() || lp_smb3_unix_extensions(snum)) { /* * Unless we have "allow insecure widelinks" * turned on. diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 0c7e791711f..119483377c0 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -155,6 +155,7 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn, uint16_t flags2, unsigned int max_data_bytes, size_t *fixed_portion, + struct files_struct *fsp, struct smb_filename *smb_fname, char **ppdata, int *ret_data_len); diff --git a/source3/smbd/smb1_trans2.c b/source3/smbd/smb1_trans2.c index 77a5d361649..18caa41dce3 100644 --- a/source3/smbd/smb1_trans2.c +++ b/source3/smbd/smb1_trans2.c @@ -1681,6 +1681,7 @@ static void call_trans2qfsinfo(connection_struct *conn, max_data_bytes, &fixed_portion, NULL, + NULL, ppdata, &data_len); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -3461,6 +3462,12 @@ static NTSTATUS smb_posix_open(connection_struct *conn, access_mask |= FILE_APPEND_DATA; } if (wire_open_mode & SMB_O_DIRECT) { + /* + * BUG: this doesn't work anymore since + * e0814dc5082dd4ecca8a155e0ce24b073158fd92. But since + * FILE_FLAG_NO_BUFFERING isn't used at all in the IO codepath, + * it doesn't really matter. + */ attributes |= FILE_FLAG_NO_BUFFERING; } diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index abcce5afb4f..8a40717235c 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -736,7 +736,9 @@ static NTSTATUS smbd_smb2_create_fetch_create_ctx( state->svhdx = smb2_create_blob_find( in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT); } - if (xconn->smb2.server.posix_extensions_negotiated) { + if (xconn->smb2.server.posix_extensions_negotiated && + lp_smb3_unix_extensions(SNUM(state->smb1req->conn))) + { /* * Negprot only allowed this for proto>=3.11 */ diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 51283eb174e..55dca5e8031 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -473,6 +473,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, STR_UNICODE, in_output_buffer_length, &fixed_portion, + fsp, fsp->fsp_name, &data, &data_size); diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index f9d5ae58b58..8f4167fc6a2 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -129,6 +129,61 @@ enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn, return PROTOCOL_NONE; } +static NTSTATUS smb2_negotiate_context_process_posix( + const struct smb2_negotiate_contexts *in_c, + bool *posix) +{ + struct smb2_negotiate_context *in_posix = NULL; + const uint8_t *inbuf = NULL; + size_t inbuflen; + bool posix_found = false; + size_t ofs; + int cmp; + + *posix = false; + + if (!lp_smb3_unix_extensions(GLOBAL_SECTION_SNUM)) { + return NT_STATUS_OK; + } + + in_posix = smb2_negotiate_context_find(in_c, + SMB2_POSIX_EXTENSIONS_AVAILABLE); + if (in_posix == NULL) { + return NT_STATUS_OK; + } + + inbuf = in_posix->data.data; + inbuflen = in_posix->data.length; + + /* + * For now the server only supports one variant. + * Check it's the right one. + */ + if ((inbuflen % 16) != 0) { + return NT_STATUS_INVALID_PARAMETER; + } + + SMB_ASSERT(strlen(SMB2_CREATE_TAG_POSIX) == 16); + + for (ofs = 0; ofs < inbuflen; ofs += 16) { + cmp = memcmp(inbuf+ofs, SMB2_CREATE_TAG_POSIX, 16); + if (cmp == 0) { + posix_found = true; + break; + } + } + + if (!posix_found) { + DBG_DEBUG("Client requested unknown SMB3 Unix extensions:\n"); + dump_data(10, inbuf, inbuflen); + return NT_STATUS_OK; + } + + DBG_DEBUG("Client requested SMB3 Unix extensions\n"); + *posix = true; + return NT_STATUS_OK; +} + struct smbd_smb2_request_process_negprot_state { struct smbd_smb2_request *req; DATA_BLOB outbody; @@ -163,7 +218,6 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) struct smb2_negotiate_context *in_cipher = NULL; struct smb2_negotiate_context *in_sign_algo = NULL; struct smb2_negotiate_contexts out_c = { .num_contexts = 0, }; - struct smb2_negotiate_context *in_posix = NULL; const struct smb311_capabilities default_smb3_capabilities = smb311_capabilities_parse("server", lp_server_smb3_signing_algorithms(), @@ -181,6 +235,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) uint32_t max_read = lp_smb2_max_read(); uint32_t max_write = lp_smb2_max_write(); NTTIME now = timeval_to_nttime(&req->request_time); + bool posix = false; bool ok; status = smbd_smb2_request_verify_sizes(req, 0x24); @@ -276,41 +331,9 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, status); } - in_posix = smb2_negotiate_context_find( - &in_c, - SMB2_POSIX_EXTENSIONS_AVAILABLE); - - if (in_posix != NULL) { - const uint8_t *inbuf = in_posix->data.data; - size_t inbuflen = in_posix->data.length; - bool posix_found = false; - /* - * For now the server only supports one variant. - * Check it's the right one. - */ - if ((inbuflen % 16) != 0) { - return smbd_smb2_request_error( - req, - NT_STATUS_INVALID_PARAMETER); - } - SMB_ASSERT(strlen(SMB2_CREATE_TAG_POSIX) == 16); - for (ofs = 0; ofs < inbuflen; ofs += 16) { - if (memcmp(inbuf + ofs, - SMB2_CREATE_TAG_POSIX, - 16) == 0) { - posix_found = true; - break; - } - } - if (posix_found) { - DBG_DEBUG("Client requested SMB2 unix " - "extensions\n"); - } else { - DBG_DEBUG("Client requested unknown " - "SMB2 unix extensions:\n"); - dump_data(10, inbuf, inbuflen); - in_posix = NULL; - } + status = smb2_negotiate_context_process_posix(&in_c, &posix); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); } } @@ -688,7 +711,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) security_buffer = data_blob_const(NULL, 0); #endif - if (in_posix != NULL) { + if (posix) { /* Client correctly negotiated SMB2 unix extensions. */ const uint8_t *buf = (const uint8_t *)SMB2_CREATE_TAG_POSIX; status = smb2_negotiate_context_add( diff --git a/source3/smbd/smb2_nttrans.c b/source3/smbd/smb2_nttrans.c index 1312d9bfc36..bf5170f07d4 100644 --- a/source3/smbd/smb2_nttrans.c +++ b/source3/smbd/smb2_nttrans.c @@ -167,6 +167,50 @@ NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd, return status; } +static bool check_smb2_posix_chmod_ace(const struct files_struct *fsp, + uint32_t security_info_sent, + struct security_descriptor *psd, + mode_t *pmode) +{ + int cmp; + + /* + * This must be an ACL with one ACE containing an + * MS NFS style mode entry coming in on a POSIX + * handle over SMB2+. + */ + if (!fsp->conn->sconn->using_smb2) { + return false; + } + + if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) { + return false; + } + + if (!(security_info_sent & SECINFO_DACL)) { + return false; + } + + if (psd->dacl == NULL) { + return false; + } + + if (psd->dacl->num_aces != 1) { + return false; + } + + cmp = dom_sid_compare_domain(&global_sid_Unix_NFS_Mode, + &psd->dacl->aces[0].trustee); + if (cmp != 0) { + return false; + } + + *pmode = (mode_t)psd->dacl->aces[0].trustee.sub_auths[2]; + *pmode &= (S_IRWXU | S_IRWXG | S_IRWXO); + + return true; +} + /**************************************************************************** Internal fn to set security descriptors from a data blob. ****************************************************************************/ @@ -176,6 +220,9 @@ NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len, { struct security_descriptor *psd = NULL; NTSTATUS status; + bool do_chmod = false; + mode_t smb2_posix_mode = 0; + int ret; if (sd_len == 0) { return NT_STATUS_INVALID_PARAMETER; @@ -187,7 +234,27 @@ NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len, return status; } - return set_sd(fsp, psd, security_info_sent); + do_chmod = check_smb2_posix_chmod_ace(fsp, + security_info_sent, + psd, + &smb2_posix_mode); + if (!do_chmod) { + return set_sd(fsp, psd, security_info_sent); + } + + TALLOC_FREE(psd); + + ret = SMB_VFS_FCHMOD(fsp, smb2_posix_mode); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + DBG_ERR("smb2_posix_chmod [%s] [%04o] failed: %s\n", + fsp_str_dbg(fsp), + (unsigned)smb2_posix_mode, + nt_errstr(status)); + return status; + } + + return NT_STATUS_OK; } /**************************************************************************** diff --git a/source3/smbd/smb2_trans2.c b/source3/smbd/smb2_trans2.c index 0dc3fa62b3f..3d13d05673b 100644 --- a/source3/smbd/smb2_trans2.c +++ b/source3/smbd/smb2_trans2.c @@ -1948,10 +1948,13 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info) } static bool fsinfo_unix_valid_level(connection_struct *conn, + struct files_struct *fsp, uint16_t info_level) { if (conn->sconn->using_smb2 && - info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) { + fsp->posix_flags == FSP_POSIX_FLAGS_OPEN && + info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) + { return true; } #if defined(SMB1SERVER) @@ -1963,6 +1966,9 @@ static bool fsinfo_unix_valid_level(connection_struct *conn, return false; } +/* + * fsp is only valid for SMB2. + */ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn, connection_struct *conn, TALLOC_CTX *mem_ctx, @@ -1970,6 +1976,7 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn, uint16_t flags2, unsigned int max_data_bytes, size_t *fixed_portion, + struct files_struct *fsp, struct smb_filename *fname, char **ppdata, int *ret_data_len) @@ -2311,14 +2318,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned /* we need to fake up a fsp here, * because its not send in this call */ - files_struct fsp; + files_struct tmpfsp; SMB_NTQUOTA_STRUCT quotas; - ZERO_STRUCT(fsp); + ZERO_STRUCT(tmpfsp); ZERO_STRUCT(quotas); - fsp.conn = conn; - fsp.fnum = FNUM_FIELD_INVALID; + tmpfsp.conn = conn; + tmpfsp.fnum = FNUM_FIELD_INVALID; /* access check */ if (get_current_uid(conn) != 0) { @@ -2329,7 +2336,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return NT_STATUS_ACCESS_DENIED; } - status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, + status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn)))); @@ -2466,7 +2473,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int rc; struct vfs_statvfs_struct svfs; - if (!fsinfo_unix_valid_level(conn, info_level)) { + if (!fsinfo_unix_valid_level(conn, fsp, info_level)) { return NT_STATUS_INVALID_LEVEL; } @@ -2993,8 +3000,9 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, ok = true; } - if ((fsp != NULL) && - (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) { + if (conn->sconn->using_smb2 && + (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) + { DBG_DEBUG("SMB2 posix open\n"); ok = true; } -- Samba Shared Repository