Add open_dir_with_privilege() to ensure we're opening the correct directory when...
authorJeremy Allison <jra@samba.org>
Thu, 1 Mar 2012 00:05:50 +0000 (16:05 -0800)
committerJeremy Allison <jra@samba.org>
Thu, 1 Mar 2012 02:50:40 +0000 (03:50 +0100)
Autobuild-User: Jeremy Allison <jra@samba.org>
Autobuild-Date: Thu Mar  1 03:50:40 CET 2012 on sn-devel-104

source3/smbd/dir.c
source3/smbd/proto.h
source3/smbd/reply.c
source3/smbd/smb2_find.c
source3/smbd/trans2.c

index c1a850ed3270a709aedd4e17c946fd9d29a3173b..103dbc8a339ce28e2944b91e6fd669a1a480eaf9 100644 (file)
@@ -412,6 +412,60 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn,
        }
 }
 
+/****************************************************************************
+ Safely do an OpenDir as root, ensuring we're in the right place.
+****************************************************************************/
+
+static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
+                                       struct smb_request *req,
+                                       const char *path,
+                                       const char *wcard,
+                                       uint32_t attr)
+{
+       NTSTATUS status;
+       struct smb_Dir *dir_hnd = NULL;
+       struct smb_filename *smb_fname_cwd = NULL;
+       char *saved_dir = vfs_GetWd(talloc_tos(), conn);
+       struct privilege_paths *priv_paths = req->priv_paths;
+       int ret;
+
+       if (saved_dir == NULL) {
+               return NULL;
+       }
+
+       if (vfs_ChDir(conn, path) == -1) {
+               return NULL;
+       }
+
+       /* Now check the stat value is the same. */
+       status = create_synthetic_smb_fname(talloc_tos(), ".",
+                                       NULL, NULL,
+                                       &smb_fname_cwd);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+       ret = SMB_VFS_STAT(conn, smb_fname_cwd);
+       if (ret != 0) {
+               goto out;
+       }
+
+       if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
+               DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
+                       "and %s\n",
+                       path,
+                       smb_fname_str_dbg(&priv_paths->parent_name)));
+               goto out;
+       }
+
+       dir_hnd = OpenDir(NULL, conn, ".", wcard, attr);
+
+  out:
+
+       vfs_ChDir(conn, saved_dir);
+       return dir_hnd;
+}
+
 /****************************************************************************
  Create a new dir ptr. If the flag old_handle is true then we must allocate
  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
@@ -421,7 +475,9 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn,
  wcard must not be zero.
 ****************************************************************************/
 
-NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
+NTSTATUS dptr_create(connection_struct *conn,
+               struct smb_request *req,
+               files_struct *fsp,
                const char *path, bool old_handle, bool expect_close,uint16 spid,
                const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
 {
@@ -480,7 +536,15 @@ NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
-               dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
+               if (req && req->priv_paths) {
+                       dir_hnd = open_dir_with_privilege(conn,
+                                               req,
+                                               path,
+                                               wcard,
+                                               attr);
+               } else {
+                       dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
+               }
        }
 
        if (!dir_hnd) {
index 9a1e9cd6839d35ae77a57228681464afc7d5a4b8..599180084ef591b5d8dce6e043f108379097bf43 100644 (file)
@@ -197,7 +197,9 @@ void dptr_closecnum(connection_struct *conn);
 void dptr_idlecnum(connection_struct *conn);
 void dptr_closepath(struct smbd_server_connection *sconn,
                    char *path,uint16 spid);
-NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
+NTSTATUS dptr_create(connection_struct *conn,
+               struct smb_request *req,
+               files_struct *fsp,
                const char *path, bool old_handle, bool expect_close,uint16 spid,
                const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret);
 void dptr_CloseDir(files_struct *fsp);
index eebd77d3efa7df7dbcca191e63c84045c2bf7325..0ab764c2d4a7606cbc86fd844736a2e511a0b476 100644 (file)
@@ -1497,6 +1497,7 @@ void reply_search(struct smb_request *req)
                SCVAL(status,0,(dirtype & 0x1F));
 
                nt_status = dptr_create(conn,
+                                       NULL, /* req */
                                        NULL, /* fsp */
                                        directory,
                                        True,
index 7c19d7538a87fa9e1755b3d6ce639b1668c4b659..99d3447860ad3c9af454ea6170607f5a65ecea05 100644 (file)
@@ -322,6 +322,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
                wcard_has_wild = ms_has_wild(in_file_name);
 
                status = dptr_create(conn,
+                                    NULL, /* req */
                                     fsp,
                                     fsp->fsp_name->base_name,
                                     false, /* old_handle */
index 21f31f17b37062336dafec07dee2a2bbabd0f919..24642cd8181760d67e98cdc43f7387b87078bb43 100644 (file)
@@ -2468,6 +2468,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                needed as lanman2 assumes these are being saved between calls */
 
        ntstatus = dptr_create(conn,
+                               req,
                                NULL, /* fsp */
                                directory,
                                False,