unix chmod not following NTFS/FAT attrib operation [w/patch]

Mike808 mike808 at networkusa.net
Fri Dec 8 21:58:55 GMT 2000


I think I posted from work on the problems I've been having using
groups and Samba.

It appears that Samba follows unix operation when performing chmod's
on a file. Whereas, on a real FAT WinXX host, any user can perform
run attrib.exe and change the file's attributes. Not so in Samba-land.
On an NTFS host, you need "ChangePermissions" access rights to do this.

But, Samba only maps the usual RWHAS attributes. I'll give a quick
synopsis of the problem, followed by patch diffs that I think really
close this hole in Samba functionality.

Scenario: Programmer "abe" and Programmer "bob", both in Group "web"
use a Samba share configured as follows:

  # everybody's in the web group.
  force group = web
  # -rw-rw-r-- (allow group write access)
  force create mode = 0664
  # drwxrwsr-x (set-guid on directories)
  force directory mode = 2775
  
"abe" creates a file, checks it into VSS (Microsoft's Visual Source
Safe).
VSS tells Samba to make the file read-only. Since "abe" owns the file,
the chmod succeeds.

"bob" tries to checkout the file in VSS to edit it.
VSS tells Samba to make the file add write permissions. Since "abe" owns
the file, but "bob" is the user issuing the chmod, it fails.

This doesn't happen with NTFS when the users have "ChangePermissions"
access.
This doesn't happen with FAT when users use "attrib.exe" to alter
permissions.

As promised, here's the patches (after a short explanation of the
approach).

I could have just wired dosmode.c: file_chmod() to go become_root(),
but thought that this might be an option the Samba administrator 
would want to control, like the DOS/Posix file timestamp behavior flag.
So, I hacked in a new BOOL bDosChmod option to control this.

If FALSE, unix chmod behavior occurs, and only the owner of the file
may alter the permissions of the file (notably read/write).

If TRUE, my idea of reasonable DOS behavior occurs, which is similar 
to the filestamp behavior.
i.e.
  1) you must have write access to the share
  2) you are a share administrative user
  3) *OR* you are the owner of the file
  4) *OR* you are a member of the same group as the file
  5) *OR* the file has world-writable permissions.

I note that #5 creates a situation whereby you can "lock yourself out"
of write permissions if you aren't #2 or #3 or #4, and you use
the file's world-writable status to make the file read-only. I can't
fix that without making the checks meaningless and letting anybody
change anything they want to.

Will someone please verify the alignment being adjusted downward by 1 
for alignment after adding a new BOOL to the structure?

And now the patches:

$ diff -c loadparm.c.orig loadparm.c
*** loadparm.c.orig     Tue Apr 25 18:07:00 2000
--- loadparm.c  Wed Dec  6 17:53:27 2000
***************
*** 362,368 ****
    BOOL bFakeDirCreateTimes;
    BOOL bBlockingLocks;
    BOOL bInheritPerms;
!   char dummy[3]; /* for alignment */
  } service;


--- 362,369 ----
    BOOL bFakeDirCreateTimes;
    BOOL bBlockingLocks;
    BOOL bInheritPerms;
!   BOOL bDosChmod;
!   char dummy[2]; /* for alignment */
  } service;


***************
*** 468,473 ****
--- 469,475 ----
    False, /* bFakeDirCreateTimes */
    True,  /* bBlockingLocks */
    False, /* bInheritPerms */
+   False, /* bDosChmod */
    ""     /* dummy */
  };

***************
*** 863,868 ****
--- 865,871 ----
    {"delete readonly",  P_BOOL,    P_LOCAL, 
&sDefault.bDeleteReadonly,  NULL,
  NULL,  FLAG_SHARE|FLAG_GLOBAL},
    {"dos filetimes",    P_BOOL,    P_LOCAL, 
&sDefault.bDosFiletimes,    NULL,
  NULL,  FLAG_SHARE|FLAG_GLOBAL},
    {"dos filetime
resolution",P_BOOL,P_LOCAL,&sDefault.bDosFiletimeResolution,
  NULL,  NULL,  FLAG_SHARE|FLAG_GLOBAL},
+   {"dos chmod",        P_BOOL,   P_LOCAL,  &sDefault.bDosChmod, 
NULL,   NULL,
  FLAG_SHARE|FLAG_GLOBAL},

    {"fake directory create times", P_BOOL,P_LOCAL, 
&sDefault.bFakeDirCreateTim
es, NULL,   NULL, FLAG_SHARE|FLAG_GLOBAL},
    {"panic action",     P_STRING,  P_GLOBAL,
&Globals.szPanicAction,     NULL,
  NULL,  0},
***************
*** 1406,1411 ****
--- 1409,1415 ----
  FN_LOCAL_BOOL(lp_fake_dir_create_times,bFakeDirCreateTimes)
  FN_LOCAL_BOOL(lp_blocking_locks,bBlockingLocks)
  FN_LOCAL_BOOL(lp_inherit_perms,bInheritPerms)
+ FN_LOCAL_BOOL(lp_dos_chmod,bDosChmod)

  FN_LOCAL_INTEGER(lp_create_mask,iCreate_mask)
  FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode)

---------------------------------------------

$ diff -b -c dosmode.c.orig dosmode.c | more
*** dosmode.c.orig      Tue Apr 25 18:07:10 2000
--- dosmode.c   Wed Dec  6 17:32:39 2000
***************
*** 182,191 ****
--- 182,193 ----
  ********************************************************************/
  int file_chmod(connection_struct *conn,char *fname,int
dosmode,SMB_STRUCT_STAT
 *st)
  {
+   extern struct current_user current_user;
    SMB_STRUCT_STAT st1;
    int mask=0;
    mode_t tmp;
    mode_t unixmode;
+   int ret = -1;

    if (!st) {
      st = &st1;
***************
*** 225,231 ****
--- 227,262 ----
      unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
    }

+
+   /* Normal unix chmod semantics */
+   if(!lp_dos_chmod(SNUM(conn)))
      return(dos_chmod(fname,unixmode));
+
+   /* We have permission (given by the Samba admin) to
+      break unix chmod semantics and allow a user to change
+      the permissions on a file they don't own.
+      (As DOS does and as NT does with ChangePermissions access).
+    */
+
+   /* Check if we have write access to the share */
+   if (!CAN_WRITE(conn)) return -1;
+
+   if (
+
+     (st->st_mode & S_IWOTH)          || /* the file is world writable
*/
+     conn->admin_user                 || /* we are an admin user */
+     (current_user.uid == st->st_uid) || /* we are the owner */
+     /* we are in the same group as the file */
+     in_group(
+       st->st_gid, current_user.gid, current_user.ngroups,
current_user.groups
+     )
+   ) {
+     /* We are allowed to become root and change the permissions. */
+     become_root(False);
+     ret = dos_chmod(fname,unixmode);
+     unbecome_root(False);
+   }
+   return(ret);
  }

---------------------------------------------

I'll see what I can do for adding it into SWAT, the documentation,
the example smb.conf, and the smb.conf man pages, but I think I've
done the hard part.

Is there some other way I should submit these patches?

mike808/
-- 
perl -e "print
pack\"H*\",\"596f752063616e277420666978207374757069642e\""




More information about the samba-technical mailing list