summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/filename.c30
-rw-r--r--source3/smbd/open.c54
-rw-r--r--source3/smbd/reply.c34
3 files changed, 88 insertions, 30 deletions
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index d240ecfa64..003cb0ffd4 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -126,7 +126,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
char *stream = NULL;
bool component_was_mangled = False;
bool name_has_wildcard = False;
+ bool posix_pathnames = false;
NTSTATUS result;
+ int ret = -1;
SET_STAT_INVALID(*pst);
*pp_conv_path = NULL;
@@ -225,7 +227,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
}
}
- if (!lp_posix_pathnames()) {
+ posix_pathnames = lp_posix_pathnames();
+
+ if (!posix_pathnames) {
stream = strchr_m(name, ':');
if (stream != NULL) {
@@ -268,7 +272,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* stat the name - if it exists then we are all done!
*/
- if (SMB_VFS_STAT(conn,name,&st) == 0) {
+ if (posix_pathnames) {
+ ret = SMB_VFS_LSTAT(conn,name,&st);
+ } else {
+ ret = SMB_VFS_STAT(conn,name,&st);
+ }
+
+ if (ret == 0) {
/* Ensure we catch all names with in "/."
this is disallowed under Windows. */
const char *p = strstr(name, "/."); /* mb safe. */
@@ -380,7 +390,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* Check if the name exists up to this point.
*/
- if (SMB_VFS_STAT(conn,name, &st) == 0) {
+ if (posix_pathnames) {
+ ret = SMB_VFS_LSTAT(conn,name, &st);
+ } else {
+ ret = SMB_VFS_STAT(conn,name, &st);
+ }
+
+ if (ret == 0) {
/*
* It exists. it must either be a directory or this must
* be the last part of the path for it to be OK.
@@ -598,7 +614,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* if it exists. JRA.
*/
- if (SMB_VFS_STAT(conn,name, &st) == 0) {
+ if (posix_pathnames) {
+ ret = SMB_VFS_LSTAT(conn,name, &st);
+ } else {
+ ret = SMB_VFS_STAT(conn,name, &st);
+ }
+
+ if (ret == 0) {
*pst = st;
} else {
SET_STAT_INVALID(st);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index bc5107447f..f7a52d7bd2 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -432,28 +432,42 @@ static NTSTATUS open_file(files_struct *fsp,
access_mask,
&access_granted);
if (!NT_STATUS_IS_OK(status)) {
-
- /* Were we trying to do a stat open
- * for delete and didn't get DELETE
- * access (only) ? Check if the
- * directory allows DELETE_CHILD.
- * See here:
- * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx
- * for details. */
-
- if (!(NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
- (access_mask & DELETE_ACCESS) &&
- (access_granted == DELETE_ACCESS) &&
- can_delete_file_in_directory(conn, path))) {
- DEBUG(10, ("open_file: Access denied on "
- "file %s\n",
- path));
+ if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ if ((access_mask & DELETE_ACCESS) &&
+ (access_granted == DELETE_ACCESS) &&
+ can_delete_file_in_directory(conn, path)) {
+ /* Were we trying to do a stat open
+ * for delete and didn't get DELETE
+ * access (only) ? Check if the
+ * directory allows DELETE_CHILD.
+ * See here:
+ * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx
+ * for details. */
+
+ DEBUG(10,("open_file: overrode ACCESS_DENIED "
+ "on file %s\n",
+ path ));
+ } else {
+ DEBUG(10, ("open_file: Access denied on "
+ "file %s\n",
+ path));
+ return status;
+ }
+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
+ fsp->posix_open &&
+ S_ISLNK(psbuf->st_mode)) {
+ /* This is a POSIX stat open for delete
+ * or rename on a symlink that points
+ * nowhere. Allow. */
+ DEBUG(10, ("open_file: allowing POSIX open "
+ "on bad symlink %s\n",
+ path ));
+ } else {
+ DEBUG(10, ("open_file: check_open_rights "
+ "on file %s returned %s\n",
+ path, nt_errstr(status) ));
return status;
}
-
- DEBUG(10,("open_file: overrode ACCESS_DENIED "
- "on file %s\n",
- path ));
}
}
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index f2d4ff78a7..bb5fadd465 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5616,7 +5616,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
return map_nt_error_from_unix(errno);
}
} else {
- if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
+ int ret = -1;
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+ }
+ if (ret == -1) {
return map_nt_error_from_unix(errno);
}
}
@@ -5721,6 +5727,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
const char *dname;
long offset = 0;
int create_options = 0;
+ bool posix_pathnames = lp_posix_pathnames();
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
@@ -5832,7 +5839,11 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
}
ZERO_STRUCT(sbuf1);
- SMB_VFS_STAT(conn, directory, &sbuf1);
+ if (posix_pathnames) {
+ SMB_VFS_LSTAT(conn, directory, &sbuf1);
+ } else {
+ SMB_VFS_STAT(conn, directory, &sbuf1);
+ }
if (S_ISDIR(sbuf1.st_mode)) {
create_options |= FILE_DIRECTORY_FILE;
@@ -5849,7 +5860,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
FILE_SHARE_WRITE),
FILE_OPEN, /* create_disposition*/
create_options, /* create_options */
- 0, /* file_attributes */
+ posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
0, /* oplock_request */
0, /* allocation_size */
NULL, /* sd */
@@ -5948,7 +5959,11 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
}
ZERO_STRUCT(sbuf1);
- SMB_VFS_STAT(conn, fname, &sbuf1);
+ if (posix_pathnames) {
+ SMB_VFS_LSTAT(conn, fname, &sbuf1);
+ } else {
+ SMB_VFS_STAT(conn, fname, &sbuf1);
+ }
create_options = 0;
@@ -5967,7 +5982,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
FILE_SHARE_WRITE),
FILE_OPEN, /* create_disposition*/
create_options, /* create_options */
- 0, /* file_attributes */
+ posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
0, /* oplock_request */
0, /* allocation_size */
NULL, /* sd */
@@ -7167,7 +7182,14 @@ void reply_setattrE(struct smb_request *req)
return;
}
} else {
- if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
+ int ret = -1;
+
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
+ }
+ if (ret == -1) {
status = map_nt_error_from_unix(errno);
reply_nterror(req, status);
END_PROFILE(SMBsetattrE);