[MAC Lion] smbclient "Open AndX Request->STATUS_NOT_SUPPORTED"

Volker Lendecke Volker.Lendecke at SerNet.DE
Fri Jul 29 08:45:30 MDT 2011


On Fri, Jul 29, 2011 at 01:51:58AM -0700, okmanoj wrote:
> Dear Volker-Sir,
> 
> Thank for your help. 
> I can understand, I will discuss with apple support about this and get back.
> 
> One more observation windows (at least windows 7) always used ntcreate&x for
> this purpose.
> Do samba has any plan to use ntcreate&x in future releases?
> 
> Thank you again for providing you helpful comment.

See the attached patchset that I've just pushed to master.
It will do a fallback to ntcreate&x if the open is replied
to with NT_STATUS_NOT_SUPPORTED.

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
-------------- next part --------------
>From eacbb89fa368a8865334213c80c42c1ec670af4c Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 29 Jul 2011 16:12:16 +0200
Subject: [PATCH 1/4] s3: We only need base_name in map_open_params_to_ntcreate

---
 source3/smbd/open.c   |    8 ++++----
 source3/smbd/proto.h  |    2 +-
 source3/smbd/reply.c  |    8 +++++---
 source3/smbd/trans2.c |    3 ++-
 4 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d81c278..8212583 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1339,7 +1339,7 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
  Open a file with a share mode - old openX method - map into NTCreate.
 ****************************************************************************/
 
-bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
+bool map_open_params_to_ntcreate(const char *smb_base_fname,
 				 int deny_mode, int open_func,
 				 uint32 *paccess_mask,
 				 uint32 *pshare_mode,
@@ -1355,7 +1355,7 @@ bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
 
 	DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
 		  "open_func = 0x%x\n",
-		  smb_fname_str_dbg(smb_fname), (unsigned int)deny_mode,
+		  smb_base_fname, (unsigned int)deny_mode,
 		  (unsigned int)open_func ));
 
 	/* Create the NT compatible access_mask. */
@@ -1430,7 +1430,7 @@ bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
 
 		case DENY_DOS:
 			private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
-	                if (is_executable(smb_fname->base_name)) {
+	                if (is_executable(smb_base_fname)) {
 				share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
 			} else {
 				if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
@@ -1455,7 +1455,7 @@ bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
 	DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
 		  "share_mode = 0x%x, create_disposition = 0x%x, "
 		  "create_options = 0x%x private_flags = 0x%x\n",
-		  smb_fname_str_dbg(smb_fname),
+		  smb_base_fname,
 		  (unsigned int)access_mask,
 		  (unsigned int)share_mode,
 		  (unsigned int)create_disposition,
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 1f414db..763a946 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -609,7 +609,7 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
 			 uint32 access_mask,
 			 uint32 share_access,
 			 uint32 create_options);
-bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
+bool map_open_params_to_ntcreate(const char *smb_base_fname,
 				 int deny_mode, int open_func,
 				 uint32 *paccess_mask,
 				 uint32 *pshare_mode,
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index e740fb4..59ec8f2 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1789,7 +1789,7 @@ void reply_open(struct smb_request *req)
 		goto out;
 	}
 
-	if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
+	if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
 					 OPENX_FILE_EXISTS_OPEN, &access_mask,
 					 &share_mode, &create_disposition,
 					 &create_options, &private_flags)) {
@@ -1964,7 +1964,8 @@ void reply_open_and_X(struct smb_request *req)
 		goto out;
 	}
 
-	if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
+	if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
+					 smb_ofun,
 					 &access_mask, &share_mode,
 					 &create_disposition,
 					 &create_options,
@@ -6755,7 +6756,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
 	if (!target_is_directory && count) {
 		new_create_disposition = FILE_OPEN;
 	} else {
-		if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
+		if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
+						 0, ofun,
 						 NULL, NULL,
 						 &new_create_disposition,
 						 NULL,
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 90eb40a..859d2ad 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1082,7 +1082,8 @@ static void call_trans2open(connection_struct *conn,
 		goto out;
 	}
 
-	if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
+	if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
+					 open_ofun,
 					 &access_mask, &share_mode,
 					 &create_disposition,
 					 &create_options,
-- 
1.7.4.1


>From 90a115e037800141c17e9bceb7eebda9e4bce179 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 29 Jul 2011 16:14:39 +0200
Subject: [PATCH 2/4] s3: Make is_executable() available in lib/

---
 source3/include/proto.h |    1 +
 source3/lib/util.c      |   17 +++++++++++++++++
 source3/smbd/open.c     |   17 -----------------
 source3/smbd/proto.h    |    1 -
 4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 35c26c2..9eff026 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -606,6 +606,7 @@ bool tevent_req_poll_ntstatus(struct tevent_req *req,
 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result);
 int timeval_to_msec(struct timeval t);
 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname);
+bool is_executable(const char *fname);
 
 /* The following definitions come from lib/util_cmdline.c  */
 
diff --git a/source3/lib/util.c b/source3/lib/util.c
index b8fc319..b320931 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2238,3 +2238,20 @@ char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
 
 	return ptr;
 }
+
+/*******************************************************************
+ Return True if the filename is one of the special executable types.
+********************************************************************/
+
+bool is_executable(const char *fname)
+{
+	if ((fname = strrchr_m(fname,'.'))) {
+		if (strequal(fname,".com") ||
+		    strequal(fname,".dll") ||
+		    strequal(fname,".exe") ||
+		    strequal(fname,".sym")) {
+			return True;
+		}
+	}
+	return False;
+}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 8212583..2529cbe 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -698,23 +698,6 @@ static NTSTATUS open_file(files_struct *fsp,
 	return NT_STATUS_OK;
 }
 
-/*******************************************************************
- Return True if the filename is one of the special executable types.
-********************************************************************/
-
-bool is_executable(const char *fname)
-{
-	if ((fname = strrchr_m(fname,'.'))) {
-		if (strequal(fname,".com") ||
-		    strequal(fname,".dll") ||
-		    strequal(fname,".exe") ||
-		    strequal(fname,".sym")) {
-			return True;
-		}
-	}
-	return False;
-}
-
 /****************************************************************************
  Check if we can open a file with a share mode.
  Returns True if conflict, False if not.
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 763a946..02c82f7 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -589,7 +589,6 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
 				    const char *inherit_from_dir,
 				    const char *fname,
 				    SMB_STRUCT_STAT *psbuf);
-bool is_executable(const char *fname);
 bool is_stat_open(uint32 access_mask);
 bool request_timed_out(struct timeval request_time,
 		       struct timeval timeout);
-- 
1.7.4.1


>From b26b2e1e685e6f31f3e91ed1c37994d2b7f01b07 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 29 Jul 2011 16:36:58 +0200
Subject: [PATCH 3/4] s3: Make map_open_params_to_ntcreate() available in lib/

---
 source3/include/proto.h |    7 ++
 source3/lib/util.c      |  148 +++++++++++++++++++++++++++++++++++++++++++++++
 source3/smbd/open.c     |  147 ----------------------------------------------
 source3/smbd/proto.h    |    7 --
 4 files changed, 155 insertions(+), 154 deletions(-)

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 9eff026..095c52c 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -607,6 +607,13 @@ bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result);
 int timeval_to_msec(struct timeval t);
 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname);
 bool is_executable(const char *fname);
+bool map_open_params_to_ntcreate(const char *smb_base_fname,
+				 int deny_mode, int open_func,
+				 uint32 *paccess_mask,
+				 uint32 *pshare_mode,
+				 uint32 *pcreate_disposition,
+				 uint32 *pcreate_options,
+				 uint32_t *pprivate_flags);
 
 /* The following definitions come from lib/util_cmdline.c  */
 
diff --git a/source3/lib/util.c b/source3/lib/util.c
index b320931..689d41e 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -29,6 +29,7 @@
 #include "../lib/util/util_pw.h"
 #include "messages.h"
 #include <ccan/hash/hash.h>
+#include "libcli/security/security.h"
 
 /* Max allowable allococation - 256mb - 0x10000000 */
 #define MAX_ALLOC_SIZE (1024*1024*256)
@@ -2255,3 +2256,150 @@ bool is_executable(const char *fname)
 	}
 	return False;
 }
+
+/****************************************************************************
+ Open a file with a share mode - old openX method - map into NTCreate.
+****************************************************************************/
+
+bool map_open_params_to_ntcreate(const char *smb_base_fname,
+				 int deny_mode, int open_func,
+				 uint32 *paccess_mask,
+				 uint32 *pshare_mode,
+				 uint32 *pcreate_disposition,
+				 uint32 *pcreate_options,
+				 uint32_t *pprivate_flags)
+{
+	uint32 access_mask;
+	uint32 share_mode;
+	uint32 create_disposition;
+	uint32 create_options = FILE_NON_DIRECTORY_FILE;
+	uint32_t private_flags = 0;
+
+	DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
+		  "open_func = 0x%x\n",
+		  smb_base_fname, (unsigned int)deny_mode,
+		  (unsigned int)open_func ));
+
+	/* Create the NT compatible access_mask. */
+	switch (GET_OPENX_MODE(deny_mode)) {
+		case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
+		case DOS_OPEN_RDONLY:
+			access_mask = FILE_GENERIC_READ;
+			break;
+		case DOS_OPEN_WRONLY:
+			access_mask = FILE_GENERIC_WRITE;
+			break;
+		case DOS_OPEN_RDWR:
+		case DOS_OPEN_FCB:
+			access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
+			break;
+		default:
+			DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
+				  (unsigned int)GET_OPENX_MODE(deny_mode)));
+			return False;
+	}
+
+	/* Create the NT compatible create_disposition. */
+	switch (open_func) {
+		case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
+			create_disposition = FILE_CREATE;
+			break;
+
+		case OPENX_FILE_EXISTS_OPEN:
+			create_disposition = FILE_OPEN;
+			break;
+
+		case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
+			create_disposition = FILE_OPEN_IF;
+			break;
+
+		case OPENX_FILE_EXISTS_TRUNCATE:
+			create_disposition = FILE_OVERWRITE;
+			break;
+
+		case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
+			create_disposition = FILE_OVERWRITE_IF;
+			break;
+
+		default:
+			/* From samba4 - to be confirmed. */
+			if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
+				create_disposition = FILE_CREATE;
+				break;
+			}
+			DEBUG(10,("map_open_params_to_ntcreate: bad "
+				  "open_func 0x%x\n", (unsigned int)open_func));
+			return False;
+	}
+
+	/* Create the NT compatible share modes. */
+	switch (GET_DENY_MODE(deny_mode)) {
+		case DENY_ALL:
+			share_mode = FILE_SHARE_NONE;
+			break;
+
+		case DENY_WRITE:
+			share_mode = FILE_SHARE_READ;
+			break;
+
+		case DENY_READ:
+			share_mode = FILE_SHARE_WRITE;
+			break;
+
+		case DENY_NONE:
+			share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+			break;
+
+		case DENY_DOS:
+			private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
+	                if (is_executable(smb_base_fname)) {
+				share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+			} else {
+				if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
+					share_mode = FILE_SHARE_READ;
+				} else {
+					share_mode = FILE_SHARE_NONE;
+				}
+			}
+			break;
+
+		case DENY_FCB:
+			private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
+			share_mode = FILE_SHARE_NONE;
+			break;
+
+		default:
+			DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
+				(unsigned int)GET_DENY_MODE(deny_mode) ));
+			return False;
+	}
+
+	DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
+		  "share_mode = 0x%x, create_disposition = 0x%x, "
+		  "create_options = 0x%x private_flags = 0x%x\n",
+		  smb_base_fname,
+		  (unsigned int)access_mask,
+		  (unsigned int)share_mode,
+		  (unsigned int)create_disposition,
+		  (unsigned int)create_options,
+		  (unsigned int)private_flags));
+
+	if (paccess_mask) {
+		*paccess_mask = access_mask;
+	}
+	if (pshare_mode) {
+		*pshare_mode = share_mode;
+	}
+	if (pcreate_disposition) {
+		*pcreate_disposition = create_disposition;
+	}
+	if (pcreate_options) {
+		*pcreate_options = create_options;
+	}
+	if (pprivate_flags) {
+		*pprivate_flags = private_flags;
+	}
+
+	return True;
+
+}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 2529cbe..510dfe0 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1318,153 +1318,6 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
 			    create_options, fsp_to_dup_into);
 }
 
-/****************************************************************************
- Open a file with a share mode - old openX method - map into NTCreate.
-****************************************************************************/
-
-bool map_open_params_to_ntcreate(const char *smb_base_fname,
-				 int deny_mode, int open_func,
-				 uint32 *paccess_mask,
-				 uint32 *pshare_mode,
-				 uint32 *pcreate_disposition,
-				 uint32 *pcreate_options,
-				 uint32_t *pprivate_flags)
-{
-	uint32 access_mask;
-	uint32 share_mode;
-	uint32 create_disposition;
-	uint32 create_options = FILE_NON_DIRECTORY_FILE;
-	uint32_t private_flags = 0;
-
-	DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
-		  "open_func = 0x%x\n",
-		  smb_base_fname, (unsigned int)deny_mode,
-		  (unsigned int)open_func ));
-
-	/* Create the NT compatible access_mask. */
-	switch (GET_OPENX_MODE(deny_mode)) {
-		case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
-		case DOS_OPEN_RDONLY:
-			access_mask = FILE_GENERIC_READ;
-			break;
-		case DOS_OPEN_WRONLY:
-			access_mask = FILE_GENERIC_WRITE;
-			break;
-		case DOS_OPEN_RDWR:
-		case DOS_OPEN_FCB:
-			access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
-			break;
-		default:
-			DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
-				  (unsigned int)GET_OPENX_MODE(deny_mode)));
-			return False;
-	}
-
-	/* Create the NT compatible create_disposition. */
-	switch (open_func) {
-		case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
-			create_disposition = FILE_CREATE;
-			break;
-
-		case OPENX_FILE_EXISTS_OPEN:
-			create_disposition = FILE_OPEN;
-			break;
-
-		case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
-			create_disposition = FILE_OPEN_IF;
-			break;
-
-		case OPENX_FILE_EXISTS_TRUNCATE:
-			create_disposition = FILE_OVERWRITE;
-			break;
-
-		case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
-			create_disposition = FILE_OVERWRITE_IF;
-			break;
-
-		default:
-			/* From samba4 - to be confirmed. */
-			if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
-				create_disposition = FILE_CREATE;
-				break;
-			}
-			DEBUG(10,("map_open_params_to_ntcreate: bad "
-				  "open_func 0x%x\n", (unsigned int)open_func));
-			return False;
-	}
-
-	/* Create the NT compatible share modes. */
-	switch (GET_DENY_MODE(deny_mode)) {
-		case DENY_ALL:
-			share_mode = FILE_SHARE_NONE;
-			break;
-
-		case DENY_WRITE:
-			share_mode = FILE_SHARE_READ;
-			break;
-
-		case DENY_READ:
-			share_mode = FILE_SHARE_WRITE;
-			break;
-
-		case DENY_NONE:
-			share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
-			break;
-
-		case DENY_DOS:
-			private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
-	                if (is_executable(smb_base_fname)) {
-				share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
-			} else {
-				if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
-					share_mode = FILE_SHARE_READ;
-				} else {
-					share_mode = FILE_SHARE_NONE;
-				}
-			}
-			break;
-
-		case DENY_FCB:
-			private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
-			share_mode = FILE_SHARE_NONE;
-			break;
-
-		default:
-			DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
-				(unsigned int)GET_DENY_MODE(deny_mode) ));
-			return False;
-	}
-
-	DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
-		  "share_mode = 0x%x, create_disposition = 0x%x, "
-		  "create_options = 0x%x private_flags = 0x%x\n",
-		  smb_base_fname,
-		  (unsigned int)access_mask,
-		  (unsigned int)share_mode,
-		  (unsigned int)create_disposition,
-		  (unsigned int)create_options,
-		  (unsigned int)private_flags));
-
-	if (paccess_mask) {
-		*paccess_mask = access_mask;
-	}
-	if (pshare_mode) {
-		*pshare_mode = share_mode;
-	}
-	if (pcreate_disposition) {
-		*pcreate_disposition = create_disposition;
-	}
-	if (pcreate_options) {
-		*pcreate_options = create_options;
-	}
-	if (pprivate_flags) {
-		*pprivate_flags = private_flags;
-	}
-
-	return True;
-
-}
-
 static void schedule_defer_open(struct share_mode_lock *lck,
 				struct timeval request_time,
 				struct smb_request *req)
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 02c82f7..b2acaa0 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -608,13 +608,6 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
 			 uint32 access_mask,
 			 uint32 share_access,
 			 uint32 create_options);
-bool map_open_params_to_ntcreate(const char *smb_base_fname,
-				 int deny_mode, int open_func,
-				 uint32 *paccess_mask,
-				 uint32 *pshare_mode,
-				 uint32 *pcreate_disposition,
-				 uint32 *pcreate_options,
-				 uint32_t *pprivate_flags);
 void remove_deferred_open_entry(struct file_id id, uint64_t mid,
 				struct server_id pid);
 NTSTATUS open_file_fchmod(connection_struct *conn,
-- 
1.7.4.1


>From e59f343745c123e5b770a9ce9af094084f373427 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 29 Jul 2011 16:37:18 +0200
Subject: [PATCH 4/4] s3: Add a fallback for missing open&x support in OS/X Lion

---
 source3/libsmb/clifile.c |   87 ++++++++++++++++++++++++++++++++++++----------
 1 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 6503e23..3590350 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -2110,12 +2110,19 @@ NTSTATUS cli_nttrans_create(struct cli_state *cli,
 ****************************************************************************/
 
 struct cli_open_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+	const char *fname;
 	uint16_t vwv[15];
 	uint16_t fnum;
+	unsigned openfn;
+	unsigned dos_deny;
+	uint8_t additional_flags;
 	struct iovec bytes;
 };
 
 static void cli_open_done(struct tevent_req *subreq);
+static void cli_open_ntcreate_done(struct tevent_req *subreq);
 
 struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
 				   struct event_context *ev,
@@ -2125,64 +2132,61 @@ struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req, *subreq;
 	struct cli_open_state *state;
-	unsigned openfn;
-	unsigned accessmode;
-	uint8_t additional_flags;
 	uint8_t *bytes;
 
 	req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
 	if (req == NULL) {
 		return NULL;
 	}
+	state->ev = ev;
+	state->cli = cli;
+	state->fname = fname;
 
-	openfn = 0;
 	if (flags & O_CREAT) {
-		openfn |= (1<<4);
+		state->openfn |= (1<<4);
 	}
 	if (!(flags & O_EXCL)) {
 		if (flags & O_TRUNC)
-			openfn |= (1<<1);
+			state->openfn |= (1<<1);
 		else
-			openfn |= (1<<0);
+			state->openfn |= (1<<0);
 	}
 
-	accessmode = (share_mode<<4);
+	state->dos_deny = (share_mode<<4);
 
 	if ((flags & O_ACCMODE) == O_RDWR) {
-		accessmode |= 2;
+		state->dos_deny |= 2;
 	} else if ((flags & O_ACCMODE) == O_WRONLY) {
-		accessmode |= 1;
+		state->dos_deny |= 1;
 	}
 
 #if defined(O_SYNC)
 	if ((flags & O_SYNC) == O_SYNC) {
-		accessmode |= (1<<14);
+		state->dos_deny |= (1<<14);
 	}
 #endif /* O_SYNC */
 
 	if (share_mode == DENY_FCB) {
-		accessmode = 0xFF;
+		state->dos_deny = 0xFF;
 	}
 
 	SCVAL(state->vwv + 0, 0, 0xFF);
 	SCVAL(state->vwv + 0, 1, 0);
 	SSVAL(state->vwv + 1, 0, 0);
 	SSVAL(state->vwv + 2, 0, 0);  /* no additional info */
-	SSVAL(state->vwv + 3, 0, accessmode);
+	SSVAL(state->vwv + 3, 0, state->dos_deny);
 	SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 	SSVAL(state->vwv + 5, 0, 0);
 	SIVAL(state->vwv + 6, 0, 0);
-	SSVAL(state->vwv + 8, 0, openfn);
+	SSVAL(state->vwv + 8, 0, state->openfn);
 	SIVAL(state->vwv + 9, 0, 0);
 	SIVAL(state->vwv + 11, 0, 0);
 	SIVAL(state->vwv + 13, 0, 0);
 
-	additional_flags = 0;
-
 	if (cli->use_oplocks) {
 		/* if using oplocks then ask for a batch oplock via
                    core and extended methods */
-		additional_flags =
+		state->additional_flags =
 			FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
 		SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
 	}
@@ -2198,7 +2202,8 @@ struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
 	state->bytes.iov_base = (void *)bytes;
 	state->bytes.iov_len = talloc_get_size(bytes);
 
-	subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
+	subreq = cli_smb_req_create(state, ev, cli, SMBopenX,
+				    state->additional_flags,
 				    15, state->vwv, 1, &state->bytes);
 	if (subreq == NULL) {
 		TALLOC_FREE(req);
@@ -2239,14 +2244,58 @@ static void cli_open_done(struct tevent_req *subreq)
 	uint16_t *vwv;
 	uint8_t *inbuf;
 	NTSTATUS status;
+	uint32_t access_mask, share_mode, create_disposition, create_options;
 
 	status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv, NULL,
 			      NULL);
 	TALLOC_FREE(subreq);
+
+	if (NT_STATUS_IS_OK(status)) {
+		state->fnum = SVAL(vwv+2, 0);
+		tevent_req_done(req);
+	}
+
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+
+	/*
+	 * For the new shiny OS/X Lion SMB server, try a ntcreate
+	 * fallback.
+	 */
+
+	if (!map_open_params_to_ntcreate(state->fname, state->dos_deny,
+					 state->openfn, &access_mask,
+					 &share_mode, &create_disposition,
+					 &create_options, NULL)) {
+		tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
+		return;
+	}
+
+	subreq = cli_ntcreate_send(state, state->ev, state->cli,
+				   state->fname, 0, access_mask,
+				   0, share_mode, create_disposition,
+				   create_options, 0);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, cli_open_ntcreate_done, req);
+}
+
+static void cli_open_ntcreate_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_open_state *state = tevent_req_data(
+		req, struct cli_open_state);
+	NTSTATUS status;
+
+	status = cli_ntcreate_recv(subreq, &state->fnum);
+	TALLOC_FREE(subreq);
 	if (tevent_req_nterror(req, status)) {
 		return;
 	}
-	state->fnum = SVAL(vwv+2, 0);
 	tevent_req_done(req);
 }
 
-- 
1.7.4.1



More information about the samba-technical mailing list