misc/151517: 'force create user' patch for samba33

Michael Meelis m.meelis at easybow.com
Sun Oct 17 14:20:08 UTC 2010


>Number:         151517
>Category:       misc
>Synopsis:       'force create user' patch for samba33
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Oct 17 14:20:07 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Michael Meelis
>Release:        8.1-RELEASE
>Organization:
EasyBOW
>Environment:
8.1-RELEASE
>Description:
Patch for samba33 to allow a file created/modified to get the system UID of the 'force create user' (set in smb.conf) and not the user name under which the user is logged in. It in the style of 'force create mode = xxx'.

The 'force create user = UID' will be set in smb.conf.

>How-To-Repeat:

>Fix:
diff --git a/source/include/proto.h b/source/include/proto.h
index 8fdd454..e2bb6a8 100644
--- source/include/proto.h
+++ source/include/proto.h
@@ -5923,6 +5923,7 @@ bool lp_acl_group_control(int );
 bool lp_acl_map_full_control(int );
 int lp_create_mask(int );
 int lp_force_create_mode(int );
+int lp_force_create_user(int );
 int lp_security_mask(int );
 int lp_force_security_mode(int );
 int lp_dir_mask(int );
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index ce1e6b6..54f65ad 100644
--- source/param/loadparm.c
+++ source/param/loadparm.c
@@ -403,6 +403,7 @@ struct service {
        int iWriteCacheSize;
        int iCreate_mask;
        int iCreate_force_mode;
+       int iCreate_force_user;
        int iSecurity_mask;
        int iSecurity_force_mode;
        int iDir_mask;
@@ -546,6 +547,7 @@ static struct service sDefault = {
        0,                      /* iWriteCacheSize */
        0744,                   /* iCreate_mask */
        0000,                   /* iCreate_force_mode */
+       -1,                     /* iCreate_force_user */
        0777,                   /* iSecurity_mask */
        0,                      /* iSecurity_force_mode */
        0755,                   /* iDir_mask */
@@ -1545,6 +1547,15 @@ static struct parm_struct parm_table[] = {
                .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
        },
        {
+               .label          = "force create user",
+               .type           = P_INTEGER,
+               .p_class        = P_LOCAL,
+               .ptr            = &sDefault.iCreate_force_user,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
+       },
+       {
                .label          = "security mask",
                .type           = P_OCTAL,
                .p_class        = P_LOCAL,
@@ -5346,6 +5357,7 @@ FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
+FN_LOCAL_INTEGER(lp_force_create_user, iCreate_force_user)
 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 2ec9632..654c3b1 100644
--- source/smbd/open.c
+++ source/smbd/open.c
@@ -156,6 +156,102 @@ NTSTATUS fd_close(files_struct *fsp)
        return NT_STATUS_OK;
 }

+static void change_file_owner(connection_struct *conn,
+                    int uid,
+                    files_struct *fsp)
+{
+       int ret;
+       if (uid == -1)
+               return;
+
+       become_root();
+       ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
+       unbecome_root();
+       if (ret == -1) {
+               DEBUG(0,("change_file_owner: failed to fchown "
+                        "file %s to parent directory uid %u. Error "
+                        "was %s\n", fsp->fsp_name,
+                        (unsigned int)uid,
+                        strerror(errno) ));
+       }
+
+       DEBUG(10,("change_file_owner: changed new file %s to "
+                 "uid %u.\n",  fsp->fsp_name,
+                 (unsigned int)uid ));
+}
+
+static NTSTATUS change_dir_owner(connection_struct *conn,
+                                      int uid,
+                                      const char *fname,
+                                      SMB_STRUCT_STAT *psbuf)
+{
+       char *saved_dir = NULL;
+       SMB_STRUCT_STAT sbuf;
+       TALLOC_CTX *ctx = talloc_tos();
+       NTSTATUS status = NT_STATUS_OK;
+       int ret;
+
+       saved_dir = vfs_GetWd(ctx,conn);
+       if (!saved_dir) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(0,("change_dir_owner: failed to get "
+                        "current working directory. Error was %s\n",
+                        strerror(errno)));
+               return status;
+       }
+
+       /* Chdir into the new path. */
+       if (vfs_ChDir(conn, fname) == -1) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(0,("change_dir_owner: failed to change "
+                        "current working directory to %s. Error "
+                        "was %s\n", fname, strerror(errno) ));
+               goto out2;
+       }
+
+       if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(0,("change_dir_owner: failed to stat "
+                        "directory '.' (%s) Error was %s\n",
+                        fname, strerror(errno)));
+               goto out2;
+       }
+
+       /* Ensure we're pointing at the same place. */
+       if (sbuf.st_dev != psbuf->st_dev ||
+           sbuf.st_ino != psbuf->st_ino ||
+           sbuf.st_mode != psbuf->st_mode ) {
+               DEBUG(0,("change_dir_owner: "
+                        "device/inode/mode on directory %s changed. "
+                        "Refusing to chown !\n", fname ));
+               status = NT_STATUS_ACCESS_DENIED;
+               goto out2;
+       }
+
+       become_root();
+       ret = SMB_VFS_CHOWN(conn, ".", uid, (gid_t)-1);
+       unbecome_root();
+       if (ret == -1) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(10,("change_dir_owner: failed to chown "
+                         "directory %s to parent directory uid %u. "
+                         "Error was %s\n", fname,
+                         (unsigned int)uid, strerror(errno) ));
+               goto out2;
+       }
+
+       DEBUG(10,("change_dir_owner: changed ownership of new "
+                 "directory %s to parent directory uid %u.\n",
+                 fname, (unsigned int)uid ));
+
+ out2:
+
+       vfs_ChDir(conn,saved_dir);
+       return status;
+}
+
+
+
 /****************************************************************************
  Change the ownership of a file to that of the parent directory.
  Do this by fd if possible.
@@ -299,6 +395,7 @@ static NTSTATUS open_file(files_struct *fsp,
        int accmode = (flags & O_ACCMODE);
        int local_flags = flags;
        bool file_existed = VALID_STAT(*psbuf);
+       int uid = -1;

        fsp->fh->fd = -1;
        errno = EPERM;
@@ -410,6 +507,10 @@ static NTSTATUS open_file(files_struct *fsp,
                                                            fsp);
                        }

+                       if ((uid = lp_force_create_user(SNUM(conn))) != -1) {
+                               change_file_owner(conn, uid, fsp);
+                       }
+
                        notify_fname(conn, NOTIFY_ACTION_ADDED,
                                     FILE_NOTIFY_CHANGE_FILE_NAME, path);
                }
@@ -2282,6 +2383,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
        const char *dirname;
        NTSTATUS status;
        bool posix_open = false;
+       int uid = -1;

        if(!CAN_WRITE(conn)) {
                DEBUG(5,("mkdir_internal: failing create on read-only share "
@@ -2356,6 +2458,10 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
        }

+       if ((uid = lp_force_create_user(SNUM(conn))) != -1) {
+               change_dir_owner(conn, uid, name, psbuf);
+       }
+
        notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME,
                     name);


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list