From bde93d88378c6ef88264d16b05c2644038b640a8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke 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 81d4e693..9b36c6c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1338,7 +1338,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, @@ -1354,7 +1354,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. */ @@ -1429,7 +1429,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) { @@ -1454,7 +1454,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 7364479..55655c5 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -606,7 +606,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 c594a6b..4178f3f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1766,7 +1766,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)) { @@ -1941,7 +1941,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, @@ -6732,7 +6733,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 be3d5a6..114f688 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1083,7 +1083,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 4d0edad13cafdca8d57f63a148c5a57d8742ae34 Mon Sep 17 00:00:00 2001 From: Volker Lendecke 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 393dd77..e7d658f 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -705,6 +705,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 b4c91af..53ea0e0 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -2722,3 +2722,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 9b36c6c..1f90c62 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -697,23 +697,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 55655c5..6e81371 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -586,7 +586,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 e830cc8fe7e8094c041583eb7988091e2c391159 Mon Sep 17 00:00:00 2001 From: Volker Lendecke 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 e7d658f..8fdd77d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -706,6 +706,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 53ea0e0..d751c5b 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -28,6 +28,7 @@ #include "ctdbd_conn.h" #include "../lib/util/util_pw.h" #include "messages.h" +#include "libcli/security/security.h" extern char *global_clobber_region_function; extern unsigned int global_clobber_region_line; @@ -2739,3 +2740,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 1f90c62..1cab9ab 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1317,153 +1317,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 6e81371..b7bb063 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -605,13 +605,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 7bfa6a1173b2a1aafcf670926f7de26a32d9d856 Mon Sep 17 00:00:00 2001 From: Volker Lendecke 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 0de81b7..a710b57 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -2050,12 +2050,19 @@ NTSTATUS cli_ntcreate(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, @@ -2065,64 +2072,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); } @@ -2138,7 +2142,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); @@ -2179,14 +2184,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