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.
****************************************************************************/
{
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;
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;
}
/****************************************************************************