s3: libsmb: Do a naive response to SMB2 "stopped on symlink". Assume the last compone...
authorJeremy Allison <jra@samba.org>
Tue, 28 Nov 2017 23:46:40 +0000 (15:46 -0800)
committerRalph Boehme <slow@samba.org>
Wed, 6 Dec 2017 14:02:16 +0000 (15:02 +0100)
Attempt re-open with FILE_OPEN_REPARSE_POINT. This matches the SMB1
behavior for smbclient.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13159

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>
source3/libsmb/cli_smb2_fnum.c

index f8861e53345c0ff2b027e6523468e1d57374e002..c40d6dd3a45476ec9aee4443c1b22ca4dbc8947f 100644 (file)
@@ -686,6 +686,27 @@ NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dname)
                        &fnum,
                        NULL);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
+               /*
+                * Naive option to match our SMB1 code. Assume the
+                * symlink path that tripped us up was the last
+                * component and try again. Eventually we will have to
+                * deal with the returned path unprocessed component. JRA.
+                */
+               status = cli_smb2_create_fnum(cli,
+                       dname,
+                       0,                      /* create_flags */
+                       DELETE_ACCESS,          /* desired_access */
+                       FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
+                       FILE_OPEN,              /* create_disposition */
+                       FILE_DIRECTORY_FILE|
+                               FILE_DELETE_ON_CLOSE|
+                               FILE_OPEN_REPARSE_POINT, /* create_options */
+                       &fnum,
+                       NULL);
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -724,6 +745,26 @@ NTSTATUS cli_smb2_unlink(struct cli_state *cli, const char *fname)
                        &fnum,
                        NULL);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
+               /*
+                * Naive option to match our SMB1 code. Assume the
+                * symlink path that tripped us up was the last
+                * component and try again. Eventually we will have to
+                * deal with the returned path unprocessed component. JRA.
+                */
+               status = cli_smb2_create_fnum(cli,
+                       fname,
+                       0,                      /* create_flags */
+                       DELETE_ACCESS,          /* desired_access */
+                       FILE_ATTRIBUTE_NORMAL, /* file attributes */
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
+                       FILE_OPEN,              /* create_disposition */
+                       FILE_DELETE_ON_CLOSE|
+                               FILE_OPEN_REPARSE_POINT, /* create_options */
+                       &fnum,
+                       NULL);
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -1157,6 +1198,7 @@ static NTSTATUS get_fnum_from_path(struct cli_state *cli,
        NTSTATUS status;
        size_t namelen = strlen(name);
        TALLOC_CTX *frame = talloc_stackframe();
+       uint32_t create_options = 0;
 
        /* SMB2 is pickier about pathnames. Ensure it doesn't
           end in a '\' */
@@ -1178,11 +1220,32 @@ static NTSTATUS get_fnum_from_path(struct cli_state *cli,
                        0, /* file attributes */
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
                        FILE_OPEN,              /* create_disposition */
-                       0,      /* create_options */
+                       create_options,
+                       pfnum,
+                       NULL);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
+               /*
+                * Naive option to match our SMB1 code. Assume the
+                * symlink path that tripped us up was the last
+                * component and try again. Eventually we will have to
+                * deal with the returned path unprocessed component. JRA.
+                */
+               create_options |= FILE_OPEN_REPARSE_POINT;
+               status = cli_smb2_create_fnum(cli,
+                       name,
+                       0,                      /* create_flags */
+                       desired_access,
+                       0, /* file attributes */
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
+                       FILE_OPEN,              /* create_disposition */
+                       create_options,
                        pfnum,
                        NULL);
+       }
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
+               create_options |= FILE_DIRECTORY_FILE;
                status = cli_smb2_create_fnum(cli,
                        name,
                        0,                      /* create_flags */