svn commit: samba r21097 - in branches: SAMBA_3_0/source/smbd SAMBA_3_0_24/source/smbd

jra at samba.org jra at samba.org
Wed Jan 31 19:26:48 GMT 2007


Author: jra
Date: 2007-01-31 19:26:46 +0000 (Wed, 31 Jan 2007)
New Revision: 21097

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21097

Log:
Ensure that when manipulating UNIX permissions via
the UNIX extensions we use the correct mask/force mask
settings for new and existing files/directories. Bug
reported by Juran David <ext-david.juran at nokia.com>.
Jeremy.

Modified:
   branches/SAMBA_3_0/source/smbd/trans2.c
   branches/SAMBA_3_0_24/source/smbd/trans2.c


Changeset:
Modified: branches/SAMBA_3_0/source/smbd/trans2.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/trans2.c	2007-01-31 19:25:08 UTC (rev 21096)
+++ branches/SAMBA_3_0/source/smbd/trans2.c	2007-01-31 19:26:46 UTC (rev 21097)
@@ -1005,12 +1005,24 @@
  Map wire perms onto standard UNIX permissions. Obey share restrictions.
 ****************************************************************************/
 
-static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
+enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
+
+static NTSTATUS unix_perms_from_wire( connection_struct *conn,
+				SMB_STRUCT_STAT *psbuf,
+				uint32 perms,
+				enum perm_type ptype,
+				mode_t *ret_perms)
 {
 	mode_t ret = 0;
 
-	if (perms == SMB_MODE_NO_CHANGE)
-		return pst->st_mode;
+	if (perms == SMB_MODE_NO_CHANGE) {
+		if (!VALID_STAT(*psbuf)) {
+			return NT_STATUS_INVALID_PARAMETER;
+		} else {
+			*ret_perms = psbuf->st_mode;
+			return NT_STATUS_OK;
+		}
+	}
 
 	ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
 	ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
@@ -1031,18 +1043,34 @@
 	ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
 #endif
 
-	if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
+	switch (ptype) {
+	case PERM_NEW_FILE:
+		/* Apply mode mask */
+		ret &= lp_create_mask(SNUM(conn));
+		/* Add in force bits */
+		ret |= lp_force_create_mode(SNUM(conn));
+		break;
+	case PERM_NEW_DIR:
 		ret &= lp_dir_mask(SNUM(conn));
 		/* Add in force bits */
 		ret |= lp_force_dir_mode(SNUM(conn));
-	} else {
+		break;
+	case PERM_EXISTING_FILE:
 		/* Apply mode mask */
-		ret &= lp_create_mask(SNUM(conn));
+		ret &= lp_security_mask(SNUM(conn));
 		/* Add in force bits */
-		ret |= lp_force_create_mode(SNUM(conn));
+		ret |= lp_force_security_mode(SNUM(conn));
+		break;
+	case PERM_EXISTING_DIR:
+		/* Apply mode mask */
+		ret &= lp_dir_security_mask(SNUM(conn));
+		/* Add in force bits */
+		ret |= lp_force_dir_security_mode(SNUM(conn));
+		break;
 	}
 
-	return ret;
+	*ret_perms = ret;
+	return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -4585,18 +4613,18 @@
 #endif
 	SMB_DEV_T dev = (SMB_DEV_T)0;
 	uint32 raw_unixmode = IVAL(pdata,84);
+	NTSTATUS status;
 	mode_t unixmode;
 
 	if (total_data < 100) {
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	if (raw_unixmode == SMB_MODE_NO_CHANGE) {
-		return NT_STATUS_INVALID_PARAMETER;
+	status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
 	}
 
-	unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode);
-
 #if defined(HAVE_MAKEDEV)
 	dev = makedev(dev_major, dev_minor);
 #endif
@@ -4645,7 +4673,7 @@
 	}
 
 	if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
-		NTSTATUS status = map_nt_error_from_unix(errno);
+		status = map_nt_error_from_unix(errno);
 		SMB_VFS_UNLINK(conn,fname);
 		return status;
 	}
@@ -4671,6 +4699,7 @@
 	gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
 	NTSTATUS status = NT_STATUS_OK;
 	BOOL delete_on_fail = False;
+	enum perm_type ptype;
 
 	if (total_data < 100) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -4694,8 +4723,22 @@
 	set_owner = (uid_t)IVAL(pdata,40);
 	set_grp = (gid_t)IVAL(pdata,48);
 	raw_unixmode = IVAL(pdata,84);
-	unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode);
 
+	if (VALID_STAT(*psbuf)) {
+		if (S_ISDIR(psbuf->st_mode)) {
+			ptype = PERM_EXISTING_DIR;
+		} else {
+			ptype = PERM_EXISTING_FILE;
+		}
+	} else {
+		ptype = PERM_NEW_FILE;
+	}
+
+	status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 		fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));

Modified: branches/SAMBA_3_0_24/source/smbd/trans2.c
===================================================================
--- branches/SAMBA_3_0_24/source/smbd/trans2.c	2007-01-31 19:25:08 UTC (rev 21096)
+++ branches/SAMBA_3_0_24/source/smbd/trans2.c	2007-01-31 19:26:46 UTC (rev 21097)
@@ -1005,12 +1005,24 @@
  Map wire perms onto standard UNIX permissions. Obey share restrictions.
 ****************************************************************************/
 
-static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
+enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
+
+static NTSTATUS unix_perms_from_wire( connection_struct *conn,
+				SMB_STRUCT_STAT *psbuf,
+				uint32 perms,
+				enum perm_type ptype,
+				mode_t *ret_perms)
 {
 	mode_t ret = 0;
 
-	if (perms == SMB_MODE_NO_CHANGE)
-		return pst->st_mode;
+	if (perms == SMB_MODE_NO_CHANGE) {
+		if (!VALID_STAT(*psbuf)) {
+			return NT_STATUS_INVALID_PARAMETER;
+		} else {
+			*ret_perms = psbuf->st_mode;
+			return NT_STATUS_OK;
+		}
+	}
 
 	ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
 	ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
@@ -1031,18 +1043,34 @@
 	ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
 #endif
 
-	if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
+	switch (ptype) {
+	case PERM_NEW_FILE:
+		/* Apply mode mask */
+		ret &= lp_create_mask(SNUM(conn));
+		/* Add in force bits */
+		ret |= lp_force_create_mode(SNUM(conn));
+		break;
+	case PERM_NEW_DIR:
 		ret &= lp_dir_mask(SNUM(conn));
 		/* Add in force bits */
 		ret |= lp_force_dir_mode(SNUM(conn));
-	} else {
+		break;
+	case PERM_EXISTING_FILE:
 		/* Apply mode mask */
-		ret &= lp_create_mask(SNUM(conn));
+		ret &= lp_security_mask(SNUM(conn));
 		/* Add in force bits */
-		ret |= lp_force_create_mode(SNUM(conn));
+		ret |= lp_force_security_mode(SNUM(conn));
+		break;
+	case PERM_EXISTING_DIR:
+		/* Apply mode mask */
+		ret &= lp_dir_security_mask(SNUM(conn));
+		/* Add in force bits */
+		ret |= lp_force_dir_security_mode(SNUM(conn));
+		break;
 	}
 
-	return ret;
+	*ret_perms = ret;
+	return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -4589,18 +4617,18 @@
 #endif
 	SMB_DEV_T dev = (SMB_DEV_T)0;
 	uint32 raw_unixmode = IVAL(pdata,84);
+	NTSTATUS status;
 	mode_t unixmode;
 
 	if (total_data < 100) {
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	if (raw_unixmode == SMB_MODE_NO_CHANGE) {
-		return NT_STATUS_INVALID_PARAMETER;
+	status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
 	}
 
-	unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode);
-
 #if defined(HAVE_MAKEDEV)
 	dev = makedev(dev_major, dev_minor);
 #endif
@@ -4649,7 +4677,7 @@
 	}
 
 	if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
-		NTSTATUS status = map_nt_error_from_unix(errno);
+		status = map_nt_error_from_unix(errno);
 		SMB_VFS_UNLINK(conn,fname);
 		return status;
 	}
@@ -4675,6 +4703,7 @@
 	gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
 	NTSTATUS status = NT_STATUS_OK;
 	BOOL delete_on_fail = False;
+	enum perm_type ptype;
 
 	if (total_data < 100) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -4698,8 +4727,22 @@
 	set_owner = (uid_t)IVAL(pdata,40);
 	set_grp = (gid_t)IVAL(pdata,48);
 	raw_unixmode = IVAL(pdata,84);
-	unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode);
 
+	if (VALID_STAT(*psbuf)) {
+		if (S_ISDIR(psbuf->st_mode)) {
+			ptype = PERM_EXISTING_DIR;
+		} else {
+			ptype = PERM_EXISTING_FILE;
+		}
+	} else {
+		ptype = PERM_NEW_FILE;
+	}
+
+	status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 		fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));



More information about the samba-cvs mailing list