Patch to handle the FILE_OPEN_FOR_BACKUP_INTENT portion of Se{Backup, Restore}Privilege

Richard Sharpe realrichardsharpe at gmail.com
Tue May 1 17:42:10 MDT 2012


Hi folks,

Here is the patch that I have created for Samba 3.5.x to handle
FILE_OPEN_FOR_BACKUP_INTENT. It does not deal with the races that
Jeremy mentioned yesterday and might still have other flaws, but I am
sending it out for discussion.

I have attached it as well.

Briefly, I add a flag, backup_intent to smbd_check_access_rights and
remove any checking of SeBackupPrivilege from se_access_check. This
checking is now done in smbd_check_access_rights.

All the callers of smbd_check_access_rights either compute
backup_intent from create_options or pass in False (in the case of
those internal callers who are simply checking whether or not the user
has permission to do what they want.)

diff -ur -x '*.o' samba-3.5.14/source3.cpy/include/privileges.h
samba-3.5.14/source3/in
clude/privileges.h
--- samba-3.5.14/source3.cpy/include/privileges.h       2012-04-25
13:53:09.555197842 -
0700
+++ samba-3.5.14/source3/include/privileges.h   2012-04-25
14:29:50.361486308 -0700
@@ -72,6 +72,7 @@
 extern const SE_PRIV se_disk_operators;
 extern const SE_PRIV se_remote_shutdown;
 extern const SE_PRIV se_restore;
+extern const SE_PRIV se_backup;
 extern const SE_PRIV se_take_ownership;
 extern const SE_PRIV se_security;

diff -ur -x '*.o' samba-3.5.14/source3.cpy/include/proto.h
samba-3.5.14/source3/include
/proto.h
--- samba-3.5.14/source3.cpy/include/proto.h    2012-04-25
13:53:09.388651013 -0700
+++ samba-3.5.14/source3/include/proto.h        2012-04-25
14:26:01.391280836 -0700
@@ -6606,7 +6606,8 @@
                                uint32_t *access_mask_out);
 NTSTATUS smbd_check_access_rights(struct connection_struct *conn,
                                const struct smb_filename *smb_fname,
-                               uint32_t access_mask);
+                               uint32_t access_mask,
+                               bool backup_intent);
 NTSTATUS fd_close(files_struct *fsp);
 void change_file_owner_to_parent(connection_struct *conn,
                                 const char *inherit_from_dir,
diff -ur -x '*.o' samba-3.5.14/source3.cpy/lib/privileges_basic.c
samba-3.5.14/source3/
lib/privileges_basic.c
--- samba-3.5.14/source3.cpy/lib/privileges_basic.c     2012-04-25
13:52:53.682273764 -
0700
+++ samba-3.5.14/source3/lib/privileges_basic.c 2012-04-25
14:28:58.079567761 -0700
@@ -45,6 +45,7 @@
 const SE_PRIV se_disk_operators  = SE_DISK_OPERATOR;
 const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN;
 const SE_PRIV se_restore         = SE_RESTORE;
+const SE_PRIV se_backup                 = SE_BACKUP;
 const SE_PRIV se_take_ownership  = SE_TAKE_OWNERSHIP;
 const SE_PRIV se_security       = SE_SECURITY;

diff -ur -x '*.o' samba-3.5.14/source3.cpy/lib/util_seaccess.c
samba-3.5.14/source3/lib
/util_seaccess.c
--- samba-3.5.14/source3.cpy/lib/util_seaccess.c        2012-04-25
13:52:54.484805985 -
0700
+++ samba-3.5.14/source3/lib/util_seaccess.c    2012-04-25
14:55:05.215611345 -0700
@@ -233,11 +233,6 @@
                }
        }

-       if ((bits_remaining & SEC_STD_DELETE) &&
-           user_has_privileges(token, &se_restore)) {
-               bits_remaining &= ~SEC_STD_DELETE;
-       }
-
        if ((bits_remaining & SEC_STD_WRITE_OWNER) &&
            user_has_privileges(token, &se_take_ownership)) {
                bits_remaining &= ~SEC_STD_WRITE_OWNER;
diff -ur -x '*.o' samba-3.5.14/source3.cpy/smbd/file_access.c
samba-3.5.14/source3/smbd
/file_access.c
--- samba-3.5.14/source3.cpy/smbd/file_access.c 2012-04-25
13:53:02.348877139 -0700
+++ samba-3.5.14/source3/smbd/file_access.c     2012-04-25
14:43:52.876584480 -0700
@@ -124,7 +124,8 @@

        ret = NT_STATUS_IS_OK(smbd_check_access_rights(conn,
                                smb_fname_parent,
-                               FILE_DELETE_CHILD));
+                               FILE_DELETE_CHILD,
+                               False));
  out:
        TALLOC_FREE(dname);
        TALLOC_FREE(smb_fname_parent);
@@ -140,7 +141,8 @@
 {
        return NT_STATUS_IS_OK(smbd_check_access_rights(conn,
                                smb_fname,
-                               FILE_WRITE_DATA));
+                               FILE_WRITE_DATA,
+                               False));
 }

 /****************************************************************************
diff -ur -x '*.o' samba-3.5.14/source3.cpy/smbd/open.c
samba-3.5.14/source3/smbd/open.c
--- samba-3.5.14/source3.cpy/smbd/open.c        2012-04-25
13:53:01.989072703 -0700
+++ samba-3.5.14/source3/smbd/open.c    2012-04-25 14:38:41.064324895 -0700
@@ -71,7 +71,8 @@

 NTSTATUS smbd_check_access_rights(struct connection_struct *conn,
                                const struct smb_filename *smb_fname,
-                               uint32_t access_mask)
+                               uint32_t access_mask,
+                               bool backup_intent)
 {
        /* Check if we have rights to open. */
        NTSTATUS status;
@@ -147,10 +148,29 @@
                nt_errstr(status) ));

        if (!NT_STATUS_IS_OK(status)) {
-               if (DEBUGLEVEL >= 10) {
-                       DEBUG(10,("smbd_check_access_rights: acl for %s is:\n",
-                               smb_fname_str_dbg(smb_fname) ));
+               bool backup_intent_override = False;
+
+               /* Check for backup_intent and the access rights it grants */
+               if (backup_intent) {
+                       DEBUG(10, ("Checking if SeBackupPrivilege or "
+                               "SeRestorePrivilege applies\n"));
+                       if ((!(rejected_mask & ~(FILE_GENERIC_READ |
SEC_STD_READ_CONTR
OL) &&
+
user_has_privileges(conn->server_info->ptok, &se_backup
)) ||
+                           (!(rejected_mask & ~(FILE_GENERIC_WRITE |
SEC_STD_WRITE_DAC
 | SEC_STD_WRITE_OWNER)) &&
+
user_has_privileges(conn->server_info->ptok, &se_restor
e)))) {
+                               status = NT_STATUS_OK;
+                               backup_intent_override = True;
+                               DEBUG(10, ("SeBackupPrivilege or
SeRestorePrivilege use
d to override lack of access\n"));
+                       }
+
+               }
+
+               if (!backup_intent_override) {
+                       if (DEBUGLEVEL >= 10) {
+                               DEBUG(10,("smbd_check_access_rights:
acl for %s is:\n",
+                                       smb_fname_str_dbg(smb_fname) ));
+                               NDR_PRINT_DEBUG(security_descriptor, sd);
+                       }
                }
        }

@@ -512,7 +532,8 @@
                          int flags,
                          mode_t unx_mode,
                          uint32 access_mask, /* client requested
access mask. */
-                         uint32 open_access_mask) /* what we're
actually using in the
open. */
+                         uint32 open_access_mask, /* what we're
actually using in the
open. */
+                         bool backup_intent)
 {
        struct smb_filename *smb_fname = fsp->fsp_name;
        NTSTATUS status = NT_STATUS_OK;
@@ -615,7 +636,8 @@
                        if (file_existed) {
                                status = smbd_check_access_rights(conn,
                                                smb_fname,
-                                               access_mask);
+                                               access_mask,
+                                               backup_intent);
+                                               backup_intent);
                        } else if (local_flags & O_CREAT){
                                status = check_parent_access(conn,
                                                smb_fname,
@@ -660,7 +682,8 @@

                status = smbd_check_access_rights(conn,
                                smb_fname,
-                               access_mask);
+                               access_mask,
+                               backup_intent);

                if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
                                fsp->posix_open &&
@@ -1877,7 +1900,7 @@
                        if (((can_access_mask & FILE_WRITE_DATA) &&
                                !CAN_WRITE(conn)) ||
                            !NT_STATUS_IS_OK(smbd_check_access_rights(conn,
-                                               smb_fname, can_access_mask))) {
+                                               smb_fname,
can_access_mask, False))) {
                                can_access = False;
                        }

@@ -1965,7 +1988,8 @@

        fsp_open = open_file(fsp, conn, req, parent_dir,
                             flags|flags2, unx_mode, access_mask,
-                            open_access_mask);
+                            open_access_mask,
+                            create_options & FILE_OPEN_FOR_BACKUP_INTENT);

        if (!NT_STATUS_IS_OK(fsp_open)) {
                if (lck != NULL) {
@@ -2554,7 +2578,10 @@
        }

        if (info == FILE_WAS_OPENED) {
-               status = smbd_check_access_rights(conn, smb_dname, access_mask);
+               status = smbd_check_access_rights(conn,
+                                                 smb_dname,
+                                                 access_mask,
+                                                 create_options &
FILE_OPEN_FOR_BACKUP
_INTENT);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10, ("open_directory:
smbd_check_access_rights on "
                                "file %s failed with %s\n",
diff -ur -x '*.o' samba-3.5.14/source3.cpy/smbd/dir.c
samba-3.5.14/source3/smbd/dir.c
--- samba-3.5.14/source3.cpy/smbd/dir.c 2012-04-27 15:19:15.359465001 -0700
+++ samba-3.5.14/source3/smbd/dir.c     2012-04-27 15:19:44.794158117 -0700
@@ -454,7 +454,8 @@
        }
        status = smbd_check_access_rights(conn,
                                        smb_dname,
-                                       SEC_DIR_LIST);
+                                       SEC_DIR_LIST,
+                                       False);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -1158,7 +1159,8 @@

        return NT_STATUS_IS_OK(smbd_check_access_rights(conn,
                                smb_fname,
-                               FILE_READ_DATA));
+                               FILE_READ_DATA,
+                               False));
 }

 /*******************************************************************
diff -ur -x '*.o' samba-3.5.14/source3.cpy/smbd/trans2.c
samba-3.5.14/source3/smbd/tran
s2.c
--- samba-3.5.14/source3.cpy/smbd/trans2.c      2012-04-27
16:45:00.010797341 -0700
+++ samba-3.5.14/source3/smbd/trans2.c  2012-04-27 16:45:36.970964492 -0700
@@ -56,7 +56,8 @@
        } else {
                NTSTATUS status = smbd_check_access_rights(conn,
                                        smb_fname,
-                                       access_mask);
+                                       access_mask,
+                                       False);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }

-- 
Regards,
Richard Sharpe
(何以解憂?唯有杜康。--曹操)


More information about the samba-technical mailing list