The Samba-Bugzilla – Attachment 9123 Details for
Bug 9974
smbclient does not support SMB2
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
git-am fix for master and 4.1.0
smb2-client.patchset (text/plain), 135.46 KB, created by
Jeremy Allison
on 2013-08-09 21:22:17 UTC
(
hide
)
Description:
git-am fix for master and 4.1.0
Filename:
MIME Type:
Creator:
Jeremy Allison
Created:
2013-08-09 21:22:17 UTC
Size:
135.46 KB
patch
obsolete
>From 20da853d83971086065b6cf068acb0998778122e Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 13:48:55 -0700 >Subject: [PATCH 01/37] Factor read_ea_list_entry() and read_nttrans_ea_list() > out so they can be used by the SMB2 client code. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/lib/util_ea.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ > source3/lib/util_ea.h | 36 ++++++++++++++ > source3/smbd/nttrans.c | 44 +---------------- > source3/smbd/trans2.c | 62 +----------------------- > source3/wscript_build | 3 +- > 5 files changed, 166 insertions(+), 105 deletions(-) > create mode 100644 source3/lib/util_ea.c > create mode 100644 source3/lib/util_ea.h > >diff --git a/source3/lib/util_ea.c b/source3/lib/util_ea.c >new file mode 100644 >index 0000000..81684da >--- /dev/null >+++ b/source3/lib/util_ea.c >@@ -0,0 +1,126 @@ >+/* >+ Unix SMB/CIFS implementation. >+ SMB Extended attribute buffer handling >+ Copyright (C) Jeremy Allison 2005-2013 >+ Copyright (C) Tim Prouty 2008 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "includes.h" >+#include "lib/util_ea.h" >+ >+/**************************************************************************** >+ Read one EA list entry from the buffer. >+****************************************************************************/ >+ >+struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used) >+{ >+ struct ea_list *eal = talloc_zero(ctx, struct ea_list); >+ uint16 val_len; >+ unsigned int namelen; >+ size_t converted_size; >+ >+ if (!eal) { >+ return NULL; >+ } >+ >+ if (data_size < 6) { >+ return NULL; >+ } >+ >+ eal->ea.flags = CVAL(pdata,0); >+ namelen = CVAL(pdata,1); >+ val_len = SVAL(pdata,2); >+ >+ if (4 + namelen + 1 + val_len > data_size) { >+ return NULL; >+ } >+ >+ /* Ensure the name is null terminated. */ >+ if (pdata[namelen + 4] != '\0') { >+ return NULL; >+ } >+ if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) { >+ DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s", >+ strerror(errno))); >+ } >+ if (!eal->ea.name) { >+ return NULL; >+ } >+ >+ eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1); >+ if (!eal->ea.value.data) { >+ return NULL; >+ } >+ >+ memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len); >+ >+ /* Ensure we're null terminated just in case we print the value. */ >+ eal->ea.value.data[val_len] = '\0'; >+ /* But don't count the null. */ >+ eal->ea.value.length--; >+ >+ if (pbytes_used) { >+ *pbytes_used = 4 + namelen + 1 + val_len; >+ } >+ >+ DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); >+ dump_data(10, eal->ea.value.data, eal->ea.value.length); >+ >+ return eal; >+} >+ >+/**************************************************************************** >+ Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. >+****************************************************************************/ >+ >+struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) >+{ >+ struct ea_list *ea_list_head = NULL; >+ size_t offset = 0; >+ >+ if (data_size < 4) { >+ return NULL; >+ } >+ >+ while (offset + 4 <= data_size) { >+ size_t next_offset = IVAL(pdata,offset); >+ struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); >+ >+ if (!eal) { >+ return NULL; >+ } >+ >+ DLIST_ADD_END(ea_list_head, eal, struct ea_list *); >+ if (next_offset == 0) { >+ break; >+ } >+ >+ /* Integer wrap protection for the increment. */ >+ if (offset + next_offset < offset) { >+ break; >+ } >+ >+ offset += next_offset; >+ >+ /* Integer wrap protection for while loop. */ >+ if (offset + 4 < offset) { >+ break; >+ } >+ >+ } >+ >+ return ea_list_head; >+} >diff --git a/source3/lib/util_ea.h b/source3/lib/util_ea.h >new file mode 100644 >index 0000000..54423ac >--- /dev/null >+++ b/source3/lib/util_ea.h >@@ -0,0 +1,36 @@ >+/* >+ Unix SMB/CIFS implementation. >+ SMB Extended attribute buffer handling >+ Copyright (C) Jeremy Allison 2005-2013 >+ Copyright (C) Tim Prouty 2008 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#ifndef __LIB_UTIL_EA_H__ >+#define __LIB_UTIL_EA_H__ >+ >+/**************************************************************************** >+ Read one EA list entry from a buffer. >+****************************************************************************/ >+ >+struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used); >+ >+/**************************************************************************** >+ Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. >+****************************************************************************/ >+ >+struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size); >+ >+#endif /* __LIB_UTIL_EA_H__ */ >diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c >index bcba29a..94be9f6 100644 >--- a/source3/smbd/nttrans.c >+++ b/source3/smbd/nttrans.c >@@ -29,6 +29,7 @@ > #include "auth.h" > #include "smbprofile.h" > #include "libsmb/libsmb.h" >+#include "lib/util_ea.h" > > extern const struct generic_mapping file_generic_mapping; > >@@ -966,49 +967,6 @@ NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len, > } > > /**************************************************************************** >- Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. >-****************************************************************************/ >- >-struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) >-{ >- struct ea_list *ea_list_head = NULL; >- size_t offset = 0; >- >- if (data_size < 4) { >- return NULL; >- } >- >- while (offset + 4 <= data_size) { >- size_t next_offset = IVAL(pdata,offset); >- struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); >- >- if (!eal) { >- return NULL; >- } >- >- DLIST_ADD_END(ea_list_head, eal, struct ea_list *); >- if (next_offset == 0) { >- break; >- } >- >- /* Integer wrap protection for the increment. */ >- if (offset + next_offset < offset) { >- break; >- } >- >- offset += next_offset; >- >- /* Integer wrap protection for while loop. */ >- if (offset + 4 < offset) { >- break; >- } >- >- } >- >- return ea_list_head; >-} >- >-/**************************************************************************** > Reply to a NT_TRANSACT_CREATE call (needs to process SD's). > ****************************************************************************/ > >diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c >index da0b1ea..2bff483 100644 >--- a/source3/smbd/trans2.c >+++ b/source3/smbd/trans2.c >@@ -38,6 +38,7 @@ > #include "smbprofile.h" > #include "rpc_server/srv_pipe_hnd.h" > #include "printing.h" >+#include "lib/util_ea.h" > > #define DIR_ENTRY_SAFETY_MARGIN 4096 > >@@ -749,67 +750,6 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz > } > > /**************************************************************************** >- Read one EA list entry from the buffer. >-****************************************************************************/ >- >-struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used) >-{ >- struct ea_list *eal = talloc_zero(ctx, struct ea_list); >- uint16 val_len; >- unsigned int namelen; >- size_t converted_size; >- >- if (!eal) { >- return NULL; >- } >- >- if (data_size < 6) { >- return NULL; >- } >- >- eal->ea.flags = CVAL(pdata,0); >- namelen = CVAL(pdata,1); >- val_len = SVAL(pdata,2); >- >- if (4 + namelen + 1 + val_len > data_size) { >- return NULL; >- } >- >- /* Ensure the name is null terminated. */ >- if (pdata[namelen + 4] != '\0') { >- return NULL; >- } >- if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) { >- DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s", >- strerror(errno))); >- } >- if (!eal->ea.name) { >- return NULL; >- } >- >- eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1); >- if (!eal->ea.value.data) { >- return NULL; >- } >- >- memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len); >- >- /* Ensure we're null terminated just in case we print the value. */ >- eal->ea.value.data[val_len] = '\0'; >- /* But don't count the null. */ >- eal->ea.value.length--; >- >- if (pbytes_used) { >- *pbytes_used = 4 + namelen + 1 + val_len; >- } >- >- DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); >- dump_data(10, eal->ea.value.data, eal->ea.value.length); >- >- return eal; >-} >- >-/**************************************************************************** > Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. > ****************************************************************************/ > >diff --git a/source3/wscript_build b/source3/wscript_build >index f7988a6..e3605e3 100755 >--- a/source3/wscript_build >+++ b/source3/wscript_build >@@ -67,7 +67,8 @@ LIB_SRC = ''' > lib/fncall.c > libads/krb5_errs.c lib/system_smbd.c lib/audit.c > lib/tevent_wait.c >- lib/idmap_cache.c''' >+ lib/idmap_cache.c >+ lib/util_ea.c''' > > LIB_UTIL_SRC = ''' > lib/system.c >-- >1.8.3 > > >From c6d683737fd44f8f8ce8ca42b26c2e9eb8fdd885 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 14:23:02 -0700 >Subject: [PATCH 02/37] Change interpret_protocol() to use the same protocol > list in enum_protocol[] used by the server code. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > lib/param/param_table.c | 2 +- > source3/include/includes.h | 4 ++-- > source3/include/proto.h | 1 + > source3/lib/util.c | 25 +++++++++---------------- > source3/param/loadparm.c | 2 +- > 5 files changed, 14 insertions(+), 20 deletions(-) > >diff --git a/lib/param/param_table.c b/lib/param/param_table.c >index 1b1497c..3d6ddbb 100644 >--- a/lib/param/param_table.c >+++ b/lib/param/param_table.c >@@ -27,7 +27,7 @@ > along with this program. If not, see <http://www.gnu.org/licenses/>. > */ > >-static const struct enum_list enum_protocol[] = { >+const struct enum_list enum_protocol[] = { > {PROTOCOL_SMB2_10, "SMB2"}, /* for now keep PROTOCOL_SMB2_10 */ > {PROTOCOL_SMB3_00, "SMB3"}, /* for now keep PROTOCOL_SMB3_00 */ > {PROTOCOL_SMB3_00, "SMB3_00"}, >diff --git a/source3/include/includes.h b/source3/include/includes.h >index 1b22a57..cbb5dd9 100644 >--- a/source3/include/includes.h >+++ b/source3/include/includes.h >@@ -399,13 +399,13 @@ typedef char fstring[FSTRING_LEN]; > /* samba_setXXid functions. */ > #include "../lib/util/setid.h" > >+#include "lib/param/loadparm.h" >+ > /***** prototypes *****/ > #ifndef NO_PROTO_H > #include "proto.h" > #endif > >-#include "lib/param/loadparm.h" >- > /* String routines */ > > #include "srvstr.h" >diff --git a/source3/include/proto.h b/source3/include/proto.h >index a9270fc..1efb2ef 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -1360,6 +1360,7 @@ int lp_name_cache_timeout(void); > int lp_client_signing(void); > int lp_server_signing(void); > int lp_client_ldap_sasl_wrapping(void); >+int lp_enum(const char *s,const struct enum_list *); > char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def); > const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def); > struct loadparm_service; >diff --git a/source3/lib/util.c b/source3/lib/util.c >index 93aab3c..8138ae5 100644 >--- a/source3/lib/util.c >+++ b/source3/lib/util.c >@@ -565,22 +565,15 @@ char *get_mydnsdomname(TALLOC_CTX *ctx) > > int interpret_protocol(const char *str,int def) > { >- if (strequal(str,"NT1")) >- return(PROTOCOL_NT1); >- if (strequal(str,"LANMAN2")) >- return(PROTOCOL_LANMAN2); >- if (strequal(str,"LANMAN1")) >- return(PROTOCOL_LANMAN1); >- if (strequal(str,"CORE")) >- return(PROTOCOL_CORE); >- if (strequal(str,"COREPLUS")) >- return(PROTOCOL_COREPLUS); >- if (strequal(str,"CORE+")) >- return(PROTOCOL_COREPLUS); >- >- DEBUG(0,("Unrecognised protocol level %s\n",str)); >- >- return(def); >+ extern const struct enum_list enum_protocol[]; >+ int ret = lp_enum(str, enum_protocol); >+ >+ if (ret == -1) { >+ DEBUG(0,("Unrecognised protocol level %s\n",str)); >+ ret = def; >+ } >+ >+ return ret; > } > > >diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c >index fa2f9b6..acb2f77 100644 >--- a/source3/param/loadparm.c >+++ b/source3/param/loadparm.c >@@ -1328,7 +1328,7 @@ static bool lp_bool(const char *s) > /******************************************************************* > convenience routine to return enum parameters. > ********************************************************************/ >-static int lp_enum(const char *s,const struct enum_list *_enum) >+int lp_enum(const char *s,const struct enum_list *_enum) > { > int i; > >-- >1.8.3 > > >From f6a9b1d698ac6376def6dbe8cc40d5a3dcc88c40 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 14:41:24 -0700 >Subject: [PATCH 03/37] Fix smb2cli_write_recv() and smb2cli_write() to return > the bytes written. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > libcli/smb/smb2cli_write.c | 28 +++++++++++++++++++++++----- > libcli/smb/smbXcli_base.h | 6 ++++-- > source3/libsmb/cli_np_tstream.c | 7 +++++-- > source3/torture/test_smb2.c | 14 +++++++------- > 4 files changed, 39 insertions(+), 16 deletions(-) > >diff --git a/libcli/smb/smb2cli_write.c b/libcli/smb/smb2cli_write.c >index 8e65460..c42443f 100644 >--- a/libcli/smb/smb2cli_write.c >+++ b/libcli/smb/smb2cli_write.c >@@ -26,6 +26,7 @@ > struct smb2cli_write_state { > uint8_t fixed[48]; > uint8_t dyn_pad[1]; >+ uint32_t written; > }; > > static void smb2cli_write_done(struct tevent_req *subreq); >@@ -94,7 +95,11 @@ static void smb2cli_write_done(struct tevent_req *subreq) > struct tevent_req *req = > tevent_req_callback_data(subreq, > struct tevent_req); >+ struct smb2cli_write_state *state = >+ tevent_req_data(req, >+ struct smb2cli_write_state); > NTSTATUS status; >+ struct iovec *iov; > static const struct smb2cli_req_expected_response expected[] = { > { > .status = NT_STATUS_OK, >@@ -102,18 +107,30 @@ static void smb2cli_write_done(struct tevent_req *subreq) > } > }; > >- status = smb2cli_req_recv(subreq, NULL, NULL, >+ status = smb2cli_req_recv(subreq, state, &iov, > expected, ARRAY_SIZE(expected)); > TALLOC_FREE(subreq); > if (tevent_req_nterror(req, status)) { > return; > } >+ state->written = IVAL(iov[1].iov_base, 4); > tevent_req_done(req); > } > >-NTSTATUS smb2cli_write_recv(struct tevent_req *req) >+NTSTATUS smb2cli_write_recv(struct tevent_req *req, uint32_t *written) > { >- return tevent_req_simple_recv_ntstatus(req); >+ struct smb2cli_write_state *state = >+ tevent_req_data(req, >+ struct smb2cli_write_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ if (written) { >+ *written = state->written; >+ } >+ return NT_STATUS_OK; > } > > NTSTATUS smb2cli_write(struct smbXcli_conn *conn, >@@ -126,7 +143,8 @@ NTSTATUS smb2cli_write(struct smbXcli_conn *conn, > uint64_t fid_volatile, > uint32_t remaining_bytes, > uint32_t flags, >- const uint8_t *data) >+ const uint8_t *data, >+ uint32_t *written) > { > TALLOC_CTX *frame = talloc_stackframe(); > struct tevent_context *ev; >@@ -155,7 +173,7 @@ NTSTATUS smb2cli_write(struct smbXcli_conn *conn, > if (!tevent_req_poll_ntstatus(req, ev, &status)) { > goto fail; > } >- status = smb2cli_write_recv(req); >+ status = smb2cli_write_recv(req, written); > fail: > TALLOC_FREE(frame); > return status; >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index f7b60d3..997869b 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -429,7 +429,8 @@ struct tevent_req *smb2cli_write_send(TALLOC_CTX *mem_ctx, > uint32_t remaining_bytes, > uint32_t flags, > const uint8_t *data); >-NTSTATUS smb2cli_write_recv(struct tevent_req *req); >+NTSTATUS smb2cli_write_recv(struct tevent_req *req, >+ uint32_t *written); > NTSTATUS smb2cli_write(struct smbXcli_conn *conn, > uint32_t timeout_msec, > struct smbXcli_session *session, >@@ -440,7 +441,8 @@ NTSTATUS smb2cli_write(struct smbXcli_conn *conn, > uint64_t fid_volatile, > uint32_t remaining_bytes, > uint32_t flags, >- const uint8_t *data); >+ const uint8_t *data, >+ uint32_t *written); > > struct tevent_req *smb2cli_flush_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >diff --git a/source3/libsmb/cli_np_tstream.c b/source3/libsmb/cli_np_tstream.c >index c7ec664..07835a5 100644 >--- a/source3/libsmb/cli_np_tstream.c >+++ b/source3/libsmb/cli_np_tstream.c >@@ -527,8 +527,11 @@ static void tstream_cli_np_writev_write_done(struct tevent_req *subreq) > if (cli_nps->is_smb1) { > status = cli_write_andx_recv(subreq, &written); > } else { >- status = smb2cli_write_recv(subreq); >- written = cli_nps->write.ofs; // TODO: get the value from the server >+ uint32_t smb2_written; >+ status = smb2cli_write_recv(subreq, &smb2_written); >+ if (NT_STATUS_IS_OK(status)) { >+ written = smb2_written; >+ } > } > TALLOC_FREE(subreq); > if (!NT_STATUS_IS_OK(status)) { >diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c >index ec695da..7ca9f49 100644 >--- a/source3/torture/test_smb2.c >+++ b/source3/torture/test_smb2.c >@@ -91,7 +91,7 @@ bool run_smb2_basic(int dummy) > > status = smb2cli_write(cli->conn, cli->timeout, cli->smb2.session, > cli->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_write returned %s\n", nt_errstr(status)); > return false; >@@ -349,7 +349,7 @@ bool run_smb2_session_reconnect(int dummy) > > status = smb2cli_write(cli1->conn, cli1->timeout, cli1->smb2.session, > cli1->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_write returned %s\n", nt_errstr(status)); > return false; >@@ -545,7 +545,7 @@ bool run_smb2_session_reconnect(int dummy) > > status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session, > cli2->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) && > !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) > { >@@ -605,7 +605,7 @@ bool run_smb2_session_reconnect(int dummy) > > status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session, > cli1->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) && > !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) > { >@@ -670,7 +670,7 @@ bool run_smb2_session_reconnect(int dummy) > > status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session, > cli2->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_write returned %s\n", nt_errstr(status)); > return false; >@@ -765,7 +765,7 @@ bool run_smb2_tcon_dependence(int dummy) > > status = smb2cli_write(cli->conn, cli->timeout, cli->smb2.session, > cli->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_write returned %s\n", nt_errstr(status)); > return false; >@@ -1172,7 +1172,7 @@ bool run_smb2_multi_channel(int dummy) > > status = smb2cli_write(cli1->conn, cli1->timeout, cli1->smb2.session, > cli1->smb2.tcon, strlen(hello), 0, fid_persistent, >- fid_volatile, 0, 0, (const uint8_t *)hello); >+ fid_volatile, 0, 0, (const uint8_t *)hello, NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_write returned %s\n", nt_errstr(status)); > return false; >-- >1.8.3 > > >From a1fe1ab50ba1eb3e2467ab492b8dbd1bd4e320cc Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:01:50 -0700 >Subject: [PATCH 04/37] Change smb2cli_create() and smb2cli_create_recv() to > return a parameter blob of the newly opened/created file. > >Will use in the smb2 client code. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > libcli/smb/smb2_create_blob.h | 12 +++++++++++ > libcli/smb/smb2cli_create.c | 39 ++++++++++++++++----------------- > libcli/smb/smbXcli_base.h | 7 ++++-- > source3/libsmb/cli_np_tstream.c | 3 ++- > source3/torture/test_smb2.c | 48 +++++++++++++++++++++++++++-------------- > 5 files changed, 69 insertions(+), 40 deletions(-) > >diff --git a/libcli/smb/smb2_create_blob.h b/libcli/smb/smb2_create_blob.h >index 008befe..2f915b3 100644 >--- a/libcli/smb/smb2_create_blob.h >+++ b/libcli/smb/smb2_create_blob.h >@@ -33,6 +33,18 @@ struct smb2_create_blobs { > struct smb2_create_blob *blobs; > }; > >+struct smb2_create_returns { >+ uint8_t oplock_level; >+ uint32_t create_action; >+ NTTIME creation_time; >+ NTTIME last_access_time; >+ NTTIME last_write_time; >+ NTTIME change_time; >+ uint64_t allocation_size; >+ uint64_t end_of_file; >+ uint32_t file_attributes; >+}; >+ > /* > parse a set of SMB2 create blobs > */ >diff --git a/libcli/smb/smb2cli_create.c b/libcli/smb/smb2cli_create.c >index 627bdcb..020a468 100644 >--- a/libcli/smb/smb2cli_create.c >+++ b/libcli/smb/smb2cli_create.c >@@ -27,17 +27,9 @@ > struct smb2cli_create_state { > uint8_t fixed[56]; > >- uint8_t oplock_level; >- uint32_t create_action; >- NTTIME creation_time; >- NTTIME last_access_time; >- NTTIME last_write_time; >- NTTIME change_time; >- uint64_t allocation_size; >- uint64_t end_of_file; >- uint32_t file_attributes; > uint64_t fid_persistent; > uint64_t fid_volatile; >+ struct smb2_create_returns cr; > struct smb2_create_blobs blobs; > }; > >@@ -179,15 +171,15 @@ static void smb2cli_create_done(struct tevent_req *subreq) > > body = (uint8_t *)iov[1].iov_base; > >- state->oplock_level = CVAL(body, 2); >- state->create_action = IVAL(body, 4); >- state->creation_time = BVAL(body, 8); >- state->last_access_time = BVAL(body, 16); >- state->last_write_time = BVAL(body, 24); >- state->change_time = BVAL(body, 32); >- state->allocation_size = BVAL(body, 40); >- state->end_of_file = BVAL(body, 48); >- state->file_attributes = IVAL(body, 56); >+ state->cr.oplock_level = CVAL(body, 2); >+ state->cr.create_action = IVAL(body, 4); >+ state->cr.creation_time = BVAL(body, 8); >+ state->cr.last_access_time = BVAL(body, 16); >+ state->cr.last_write_time = BVAL(body, 24); >+ state->cr.change_time = BVAL(body, 32); >+ state->cr.allocation_size = BVAL(body, 40); >+ state->cr.end_of_file = BVAL(body, 48); >+ state->cr.file_attributes = IVAL(body, 56); > state->fid_persistent = BVAL(body, 64); > state->fid_volatile = BVAL(body, 72); > >@@ -213,7 +205,8 @@ static void smb2cli_create_done(struct tevent_req *subreq) > > NTSTATUS smb2cli_create_recv(struct tevent_req *req, > uint64_t *fid_persistent, >- uint64_t *fid_volatile) >+ uint64_t *fid_volatile, >+ struct smb2_create_returns *cr) > { > struct smb2cli_create_state *state = > tevent_req_data(req, >@@ -225,6 +218,9 @@ NTSTATUS smb2cli_create_recv(struct tevent_req *req, > } > *fid_persistent = state->fid_persistent; > *fid_volatile = state->fid_volatile; >+ if (cr) { >+ *cr = state->cr; >+ } > return NT_STATUS_OK; > } > >@@ -242,7 +238,8 @@ NTSTATUS smb2cli_create(struct smbXcli_conn *conn, > uint32_t create_options, > struct smb2_create_blobs *blobs, > uint64_t *fid_persistent, >- uint64_t *fid_volatile) >+ uint64_t *fid_volatile, >+ struct smb2_create_returns *cr) > { > TALLOC_CTX *frame = talloc_stackframe(); > struct tevent_context *ev; >@@ -273,7 +270,7 @@ NTSTATUS smb2cli_create(struct smbXcli_conn *conn, > if (!tevent_req_poll_ntstatus(req, ev, &status)) { > goto fail; > } >- status = smb2cli_create_recv(req, fid_persistent, fid_volatile); >+ status = smb2cli_create_recv(req, fid_persistent, fid_volatile, cr); > fail: > TALLOC_FREE(frame); > return status; >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index 997869b..a497e13 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -28,6 +28,7 @@ struct smb_trans_enc_state; > struct GUID; > struct iovec; > struct smb2_create_blobs; >+struct smb2_create_returns; > > struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx, > int fd, >@@ -353,7 +354,8 @@ struct tevent_req *smb2cli_create_send( > struct smb2_create_blobs *blobs); > NTSTATUS smb2cli_create_recv(struct tevent_req *req, > uint64_t *fid_persistent, >- uint64_t *fid_volatile); >+ uint64_t *fid_volatile, >+ struct smb2_create_returns *cr); > NTSTATUS smb2cli_create(struct smbXcli_conn *conn, > uint32_t timeout_msec, > struct smbXcli_session *session, >@@ -368,7 +370,8 @@ NTSTATUS smb2cli_create(struct smbXcli_conn *conn, > uint32_t create_options, > struct smb2_create_blobs *blobs, > uint64_t *fid_persistent, >- uint64_t *fid_volatile); >+ uint64_t *fid_volatile, >+ struct smb2_create_returns *cr); > > struct tevent_req *smb2cli_close_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >diff --git a/source3/libsmb/cli_np_tstream.c b/source3/libsmb/cli_np_tstream.c >index 07835a5..f3a9962 100644 >--- a/source3/libsmb/cli_np_tstream.c >+++ b/source3/libsmb/cli_np_tstream.c >@@ -208,7 +208,8 @@ static void tstream_cli_np_open_done(struct tevent_req *subreq) > } else { > status = smb2cli_create_recv(subreq, > &state->fid_persistent, >- &state->fid_volatile); >+ &state->fid_volatile, >+ NULL); > } > TALLOC_FREE(subreq); > if (!NT_STATUS_IS_OK(status)) { >diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c >index 7ca9f49..3bcd2ed 100644 >--- a/source3/torture/test_smb2.c >+++ b/source3/torture/test_smb2.c >@@ -83,7 +83,8 @@ bool run_smb2_basic(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create returned %s\n", nt_errstr(status)); > return false; >@@ -145,7 +146,8 @@ bool run_smb2_basic(int dummy) > FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create returned %s\n", nt_errstr(status)); > return false; >@@ -341,7 +343,8 @@ bool run_smb2_session_reconnect(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create on cli1 %s\n", nt_errstr(status)); > return false; >@@ -575,7 +578,8 @@ bool run_smb2_session_reconnect(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && > !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) { > printf("smb2cli_create on cli2 %s\n", nt_errstr(status)); >@@ -635,7 +639,8 @@ bool run_smb2_session_reconnect(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) && > !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) > { >@@ -662,7 +667,8 @@ bool run_smb2_session_reconnect(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create on cli2 %s\n", nt_errstr(status)); > return false; >@@ -757,7 +763,8 @@ bool run_smb2_tcon_dependence(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create on cli %s\n", nt_errstr(status)); > return false; >@@ -1164,7 +1171,8 @@ bool run_smb2_multi_channel(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create on cli2 %s\n", nt_errstr(status)); > return false; >@@ -1324,7 +1332,8 @@ bool run_smb2_multi_channel(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { > printf("smb2cli_create %s\n", nt_errstr(status)); > return false; >@@ -1341,7 +1350,8 @@ bool run_smb2_multi_channel(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { > printf("smb2cli_create %s\n", nt_errstr(status)); > return false; >@@ -1358,7 +1368,8 @@ bool run_smb2_multi_channel(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { > printf("smb2cli_create %s\n", nt_errstr(status)); > return false; >@@ -1489,7 +1500,8 @@ bool run_smb2_session_reauth(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create %s\n", nt_errstr(status)); > return false; >@@ -1508,7 +1520,8 @@ bool run_smb2_session_reauth(int dummy) > FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &dir_persistent, >- &dir_volatile); >+ &dir_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create returned %s\n", nt_errstr(status)); > return false; >@@ -1691,7 +1704,8 @@ bool run_smb2_session_reauth(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { > printf("smb2cli_create %s\n", nt_errstr(status)); > return false; >@@ -1710,7 +1724,8 @@ bool run_smb2_session_reauth(int dummy) > FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &dir_persistent, >- &dir_volatile); >+ &dir_volatile, >+ NULL); > if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { > printf("smb2cli_create returned %s\n", nt_errstr(status)); > return false; >@@ -1865,7 +1880,8 @@ bool run_smb2_session_reauth(int dummy) > FILE_DELETE_ON_CLOSE, /* create_options, */ > NULL, /* smb2_create_blobs *blobs */ > &fid_persistent, >- &fid_volatile); >+ &fid_volatile, >+ NULL); > if (!NT_STATUS_IS_OK(status)) { > printf("smb2cli_create %s\n", nt_errstr(status)); > return false; >-- >1.8.3 > > >From 640014d38b55180deb6738ef4a3584280cd75bf4 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:17:01 -0700 >Subject: [PATCH 05/37] Correctly set up cli_maxprotocol, cli_minprotocol in > our parameter block. Allow cli_maxprotocol to be changed. > >Set to PROTOCOL_NT1, PROTOCOL_CORE by default. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/include/proto.h | 3 +++ > source3/param/loadparm.c | 7 +++++++ > 2 files changed, 10 insertions(+) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index 1efb2ef..7713454 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -1190,6 +1190,8 @@ int lp_deadtime(void); > bool lp_getwd_cache(void); > int lp_srv_maxprotocol(void); > int lp_srv_minprotocol(void); >+int lp_cli_maxprotocol(void); >+int lp_cli_minprotocol(void); > int lp_security(void); > int lp__server_role(void); > int lp__security(void); >@@ -1486,6 +1488,7 @@ char* lp_perfcount_module(TALLOC_CTX *ctx); > void widelinks_warning(int snum); > const char *lp_ncalrpc_dir(void); > void _lp_set_server_role(int server_role); >+void lp_set_cli_maxprotocol(int max_protocol); > > /* The following definitions come from param/loadparm_ctx.c */ > >diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c >index acb2f77..078bea6 100644 >--- a/source3/param/loadparm.c >+++ b/source3/param/loadparm.c >@@ -828,6 +828,8 @@ static void init_globals(bool reinit_globals) > Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE; > Globals.srv_maxprotocol = PROTOCOL_SMB3_00; > Globals.srv_minprotocol = PROTOCOL_LANMAN1; >+ Globals.cli_maxprotocol = PROTOCOL_NT1; >+ Globals.cli_minprotocol = PROTOCOL_CORE; > Globals.security = SEC_USER; > Globals.bEncryptPasswords = true; > Globals.clientSchannel = Auto; >@@ -5538,3 +5540,8 @@ int lp_security(void) > return lp_find_security(lp__server_role(), > lp__security()); > } >+ >+void lp_set_cli_maxprotocol(int max_protocol) >+{ >+ Globals.cli_maxprotocol = max_protocol; >+} >-- >1.8.3 > > >From 1bef944961bd08cacff2df22706886cdad5d3832 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:54:05 -0700 >Subject: [PATCH 06/37] Add in the core of the libsmb client SMB2 functions. > >These create a synchronous smb2cli_XXX() style interface >designed to plug directly into the libsmb/cliXXXX.c code. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/include/client.h | 1 + > source3/libsmb/clirap.c | 7 +- > source3/libsmb/clirap.h | 4 + > source3/libsmb/smb2cli_fnum.c | 2235 +++++++++++++++++++++++++++++++++++++++++ > source3/libsmb/smb2cli_fnum.h | 146 +++ > source3/wscript_build | 3 +- > 6 files changed, 2389 insertions(+), 7 deletions(-) > create mode 100644 source3/libsmb/smb2cli_fnum.c > create mode 100644 source3/libsmb/smb2cli_fnum.h > >diff --git a/source3/include/client.h b/source3/include/client.h >index 52e2212..09f9660 100644 >--- a/source3/include/client.h >+++ b/source3/include/client.h >@@ -109,6 +109,7 @@ struct cli_state { > struct { > struct smbXcli_session *session; > struct smbXcli_tcon *tcon; >+ struct idr_context *open_handles; > } smb2; > }; > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 77e2fa3..12a340c 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -879,11 +879,6 @@ NTSTATUS cli_qpathinfo2(struct cli_state *cli, const char *fname, > Get the stream info > ****************************************************************************/ > >-static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *data, >- size_t data_len, >- unsigned int *pnum_streams, >- struct stream_struct **pstreams); >- > struct cli_qpathinfo_streams_state { > uint32_t num_data; > uint8_t *data; >@@ -986,7 +981,7 @@ NTSTATUS cli_qpathinfo_streams(struct cli_state *cli, const char *fname, > return status; > } > >-static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata, >+bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata, > size_t data_len, > unsigned int *pnum_streams, > struct stream_struct **pstreams) >diff --git a/source3/libsmb/clirap.h b/source3/libsmb/clirap.h >index 91628ea..e105182 100644 >--- a/source3/libsmb/clirap.h >+++ b/source3/libsmb/clirap.h >@@ -94,6 +94,10 @@ NTSTATUS cli_qpathinfo_streams(struct cli_state *cli, const char *fname, > TALLOC_CTX *mem_ctx, > unsigned int *pnum_streams, > struct stream_struct **pstreams); >+bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata, >+ size_t data_len, >+ unsigned int *pnum_streams, >+ struct stream_struct **pstreams); > NTSTATUS cli_qfilename(struct cli_state *cli, uint16_t fnum, > TALLOC_CTX *mem_ctx, char **name); > NTSTATUS cli_qfileinfo_basic(struct cli_state *cli, uint16_t fnum, >diff --git a/source3/libsmb/smb2cli_fnum.c b/source3/libsmb/smb2cli_fnum.c >new file mode 100644 >index 0000000..ddf1ed3 >--- /dev/null >+++ b/source3/libsmb/smb2cli_fnum.c >@@ -0,0 +1,2235 @@ >+/* >+ Unix SMB/CIFS implementation. >+ smb2 lib >+ Copyright (C) Jeremy Allison 2013 >+ Copyright (C) Volker Lendecke 2013 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+/* >+ This code is a thin wrapper around the existing >+ smb2cli_XXXX() functions in libcli/smb/smb2cli_XXXXX.c, >+ but allows the handles to be mapped to uint16_t fnums, >+ which are easier for smbclient to use. >+*/ >+ >+#include "includes.h" >+#include "client.h" >+#include "async_smb.h" >+#include "../libcli/smb/smbXcli_base.h" >+#include "smb2cli.h" >+#include "smb2cli_fnum.h" >+#include "trans2.h" >+#include "clirap.h" >+#include "../libcli/smb/smb2_create_blob.h" >+#include "libsmb/proto.h" >+#include "lib/util/tevent_ntstatus.h" >+#include "../libcli/security/security.h" >+#include "lib/util_ea.h" >+ >+struct smb2_hnd { >+ uint64_t fid_persistent; >+ uint64_t fid_volatile; >+}; >+ >+/* >+ * Handle mapping code. >+ */ >+ >+/*************************************************************** >+ Allocate a new fnum between 1 and 0xFFFE from an smb2_hnd. >+ Ensures handle is owned by cli struct. >+***************************************************************/ >+ >+static NTSTATUS map_smb2_handle_to_fnum(struct cli_state *cli, >+ const struct smb2_hnd *ph, /* In */ >+ uint16_t *pfnum) /* Out */ >+{ >+ int ret; >+ struct idr_context *idp = cli->smb2.open_handles; >+ struct smb2_hnd *owned_h = talloc_memdup(cli, >+ ph, >+ sizeof(struct smb2_hnd)); >+ >+ if (owned_h == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ if (idp == NULL) { >+ /* Lazy init */ >+ cli->smb2.open_handles = idr_init(cli); >+ if (cli->smb2.open_handles == NULL) { >+ TALLOC_FREE(owned_h); >+ return NT_STATUS_NO_MEMORY; >+ } >+ idp = cli->smb2.open_handles; >+ } >+ >+ ret = idr_get_new_above(idp, owned_h, 1, 0xFFFE); >+ if (ret == -1) { >+ TALLOC_FREE(owned_h); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ *pfnum = (uint16_t)ret; >+ return NT_STATUS_OK; >+} >+ >+/*************************************************************** >+ Return the smb2_hnd pointer associated with the given fnum. >+***************************************************************/ >+ >+static NTSTATUS map_fnum_to_smb2_handle(struct cli_state *cli, >+ uint16_t fnum, /* In */ >+ struct smb2_hnd **pph) /* Out */ >+{ >+ struct idr_context *idp = cli->smb2.open_handles; >+ >+ if (idp == NULL) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ *pph = (struct smb2_hnd *)idr_find(idp, fnum); >+ if (*pph == NULL) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ return NT_STATUS_OK; >+} >+ >+/*************************************************************** >+ Delete the fnum to smb2_hnd mapping. Zeros out handle on >+ successful return. >+***************************************************************/ >+ >+static NTSTATUS delete_smb2_handle_mapping(struct cli_state *cli, >+ struct smb2_hnd **pph, /* In */ >+ uint16_t fnum) /* In */ >+{ >+ struct idr_context *idp = cli->smb2.open_handles; >+ struct smb2_hnd *ph; >+ >+ if (idp == NULL) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ ph = (struct smb2_hnd *)idr_find(idp, fnum); >+ if (ph != *pph) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ idr_remove(idp, fnum); >+ TALLOC_FREE(*pph); >+ return NT_STATUS_OK; >+} >+ >+/*************************************************************** >+ Oplock mapping code. >+***************************************************************/ >+ >+static uint8_t flags_to_smb2_oplock(uint32_t create_flags) >+{ >+ if (create_flags & REQUEST_BATCH_OPLOCK) { >+ return SMB2_OPLOCK_LEVEL_BATCH; >+ } else if (create_flags & REQUEST_OPLOCK) { >+ return SMB2_OPLOCK_LEVEL_EXCLUSIVE; >+ } >+ >+ /* create_flags doesn't do a level2 request. */ >+ return SMB2_OPLOCK_LEVEL_NONE; >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 create to return a uint16_t fnum. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_create_fnum(struct cli_state *cli, >+ const char *fname, >+ uint32_t create_flags, >+ uint32_t desired_access, >+ uint32_t file_attributes, >+ uint32_t share_access, >+ uint32_t create_disposition, >+ uint32_t create_options, >+ uint16_t *pfid, >+ struct smb2_create_returns *cr) >+{ >+ NTSTATUS status; >+ struct smb2_hnd h; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (cli->backup_intent) { >+ create_options |= FILE_OPEN_FOR_BACKUP_INTENT; >+ } >+ >+ /* SMB2 is pickier about pathnames. Ensure it doesn't >+ start in a '\' */ >+ if (*fname == '\\') { >+ fname++; >+ } >+ >+ status = smb2cli_create(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ fname, >+ flags_to_smb2_oplock(create_flags), >+ SMB2_IMPERSONATION_IMPERSONATION, >+ desired_access, >+ file_attributes, >+ share_access, >+ create_disposition, >+ create_options, >+ NULL, >+ &h.fid_persistent, >+ &h.fid_volatile, >+ cr); >+ >+ if (NT_STATUS_IS_OK(status)) { >+ status = map_smb2_handle_to_fnum(cli, &h, pfid); >+ } >+ >+ return status; >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 close to use a uint16_t fnum. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_close_fnum(struct cli_state *cli, uint16_t fnum) >+{ >+ struct smb2_hnd *ph = NULL; >+ NTSTATUS status; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ status = smb2cli_close(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 0, >+ ph->fid_persistent, >+ ph->fid_volatile); >+ >+ /* Delete the fnum -> handle mapping. */ >+ if (NT_STATUS_IS_OK(status)) { >+ status = delete_smb2_handle_mapping(cli, &ph, fnum); >+ } >+ >+ return status; >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 to create a directory >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_mkdir(struct cli_state *cli, const char *dname) >+{ >+ NTSTATUS status; >+ uint16_t fnum; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ status = smb2cli_create_fnum(cli, >+ dname, >+ 0, /* create_flags */ >+ FILE_READ_ATTRIBUTES, /* desired_access */ >+ FILE_ATTRIBUTE_DIRECTORY, /* file attributes */ >+ FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ >+ FILE_CREATE, /* create_disposition */ >+ FILE_DIRECTORY_FILE, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ return smb2cli_close_fnum(cli, fnum); >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 to delete a directory >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_rmdir(struct cli_state *cli, const char *dname) >+{ >+ NTSTATUS status; >+ uint16_t fnum; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ status = smb2cli_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, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ return smb2cli_close_fnum(cli, fnum); >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 to unlink a pathname. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_unlink(struct cli_state *cli, const char *fname) >+{ >+ NTSTATUS status; >+ uint16_t fnum; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ status = smb2cli_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, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ return smb2cli_close_fnum(cli, fnum); >+} >+ >+/*************************************************************** >+ Utility function to parse a SMB2_FIND_ID_BOTH_DIRECTORY_INFO reply. >+***************************************************************/ >+ >+static NTSTATUS parse_finfo_id_both_directory_info(uint8_t *dir_data, >+ uint32_t dir_data_length, >+ struct file_info *finfo, >+ uint32_t *next_offset) >+{ >+ size_t namelen = 0; >+ size_t slen = 0; >+ size_t ret = 0; >+ >+ if (dir_data_length < 4) { >+ return NT_STATUS_INFO_LENGTH_MISMATCH; >+ } >+ >+ *next_offset = IVAL(dir_data, 0); >+ >+ if (*next_offset > dir_data_length) { >+ return NT_STATUS_INFO_LENGTH_MISMATCH; >+ } >+ >+ if (*next_offset != 0) { >+ /* Ensure we only read what in this record. */ >+ dir_data_length = *next_offset; >+ } >+ >+ if (dir_data_length < 105) { >+ return NT_STATUS_INFO_LENGTH_MISMATCH; >+ } >+ >+ finfo->atime_ts = interpret_long_date((const char *)dir_data + 16); >+ finfo->mtime_ts = interpret_long_date((const char *)dir_data + 24); >+ finfo->ctime_ts = interpret_long_date((const char *)dir_data + 32); >+ finfo->size = IVAL2_TO_SMB_BIG_UINT(dir_data + 40, 0); >+ finfo->mode = CVAL(dir_data + 56, 0); >+ namelen = IVAL(dir_data + 60,0); >+ if (namelen > (dir_data_length - 104)) { >+ return NT_STATUS_INFO_LENGTH_MISMATCH; >+ } >+ slen = SVAL(dir_data + 68, 0); >+ if (slen > 24) { >+ return NT_STATUS_INFO_LENGTH_MISMATCH; >+ } >+ ret = pull_string_talloc(finfo, >+ dir_data, >+ FLAGS2_UNICODE_STRINGS, >+ &finfo->short_name, >+ dir_data + 70, >+ slen, >+ STR_UNICODE); >+ if (ret == (size_t)-1) { >+ /* Bad conversion. */ >+ return NT_STATUS_INVALID_NETWORK_RESPONSE; >+ } >+ >+ ret = pull_string_talloc(finfo, >+ dir_data, >+ FLAGS2_UNICODE_STRINGS, >+ &finfo->name, >+ dir_data + 104, >+ namelen, >+ STR_UNICODE); >+ if (ret == (size_t)-1) { >+ /* Bad conversion. */ >+ return NT_STATUS_INVALID_NETWORK_RESPONSE; >+ } >+ return NT_STATUS_OK; >+} >+ >+/******************************************************************* >+ Given a filename - get its directory name >+********************************************************************/ >+ >+static bool windows_parent_dirname(TALLOC_CTX *mem_ctx, >+ const char *dir, >+ char **parent, >+ const char **name) >+{ >+ char *p; >+ ptrdiff_t len; >+ >+ p = strrchr_m(dir, '\\'); /* Find final '\\', if any */ >+ >+ if (p == NULL) { >+ if (!(*parent = talloc_strdup(mem_ctx, "\\"))) { >+ return false; >+ } >+ if (name) { >+ *name = dir; >+ } >+ return true; >+ } >+ >+ len = p-dir; >+ >+ if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) { >+ return false; >+ } >+ (*parent)[len] = '\0'; >+ >+ if (name) { >+ *name = p+1; >+ } >+ return true; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to list a directory. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_list(struct cli_state *cli, >+ const char *pathname, >+ NTSTATUS (*fn)(const char *, >+ struct file_info *, >+ const char *, >+ void *), >+ void *state) >+{ >+ NTSTATUS status; >+ uint16_t fnum = -1; >+ char *parent_dir = NULL; >+ const char *mask = NULL; >+ struct smb2_hnd *ph = NULL; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *subframe = NULL; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ /* Get the directory name. */ >+ if (!windows_parent_dirname(frame, >+ pathname, >+ &parent_dir, >+ &mask)) { >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; >+ } >+ >+ status = smb2cli_create_fnum(cli, >+ parent_dir, >+ 0, /* create_flags */ >+ SEC_DIR_LIST|SEC_DIR_READ_ATTRIBUTE,/* desired_access */ >+ FILE_ATTRIBUTE_DIRECTORY, /* file attributes */ >+ FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ >+ FILE_OPEN, /* create_disposition */ >+ FILE_DIRECTORY_FILE, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ do { >+ uint8_t *dir_data = NULL; >+ uint32_t dir_data_length = 0; >+ uint32_t next_offset = 0; >+ subframe = talloc_stackframe(); >+ >+ status = smb2cli_query_directory(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ SMB2_FIND_ID_BOTH_DIRECTORY_INFO, >+ 0, /* flags */ >+ 0, /* file_index */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ mask, >+ 0xffff, >+ subframe, >+ &dir_data, >+ &dir_data_length); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) { >+ break; >+ } >+ goto fail; >+ } >+ >+ do { >+ struct file_info *finfo = talloc_zero(subframe, >+ struct file_info); >+ >+ if (finfo == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; >+ } >+ >+ status = parse_finfo_id_both_directory_info(dir_data, >+ dir_data_length, >+ finfo, >+ &next_offset); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = fn(cli->dfs_mountpoint, >+ finfo, >+ pathname, >+ state); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ break; >+ } >+ >+ TALLOC_FREE(finfo); >+ >+ /* Move to next entry. */ >+ if (next_offset) { >+ dir_data += next_offset; >+ dir_data_length -= next_offset; >+ } >+ } while (next_offset != 0); >+ >+ TALLOC_FREE(subframe); >+ >+ } while (NT_STATUS_IS_OK(status)); >+ >+ if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) { >+ status = NT_STATUS_OK; >+ } >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ TALLOC_FREE(subframe); >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a path info (basic level). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_qpathinfo_basic(struct cli_state *cli, >+ const char *name, >+ SMB_STRUCT_STAT *sbuf, >+ uint32_t *attributes) >+{ >+ NTSTATUS status; >+ struct smb2_create_returns cr; >+ uint16_t fnum = -1; >+ size_t namelen = strlen(name); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ /* SMB2 is pickier about pathnames. Ensure it doesn't >+ end in a '\' */ >+ if (namelen > 0 && name[namelen-1] == '\\') { >+ char *modname = talloc_strdup(talloc_tos(), name); >+ modname[namelen-1] = '\0'; >+ name = modname; >+ } >+ >+ /* This is commonly used as a 'cd'. Try qpathinfo on >+ a directory handle first. */ >+ >+ status = smb2cli_create_fnum(cli, >+ name, >+ 0, /* create_flags */ >+ FILE_READ_ATTRIBUTES, /* 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, /* create_options */ >+ &fnum, >+ &cr); >+ >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) { >+ /* Maybe a file ? */ >+ status = smb2cli_create_fnum(cli, >+ name, >+ 0, /* create_flags */ >+ FILE_READ_ATTRIBUTES, /* desired_access */ >+ 0, /* file attributes */ >+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */ >+ FILE_OPEN, /* create_disposition */ >+ 0, /* create_options */ >+ &fnum, >+ &cr); >+ } >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ smb2cli_close_fnum(cli, fnum); >+ >+ ZERO_STRUCTP(sbuf); >+ >+ sbuf->st_ex_atime = nt_time_to_unix_timespec(&cr.last_access_time); >+ sbuf->st_ex_mtime = nt_time_to_unix_timespec(&cr.last_write_time); >+ sbuf->st_ex_ctime = nt_time_to_unix_timespec(&cr.change_time); >+ sbuf->st_ex_size = cr.end_of_file; >+ *attributes = cr.file_attributes; >+ >+ return NT_STATUS_OK; >+} >+ >+/*************************************************************** >+ Helper function for pathname operations. >+***************************************************************/ >+ >+static NTSTATUS get_fnum_from_path(struct cli_state *cli, >+ const char *name, >+ uint32_t desired_access, >+ uint16_t *pfnum) >+{ >+ NTSTATUS status; >+ size_t namelen = strlen(name); >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ /* SMB2 is pickier about pathnames. Ensure it doesn't >+ end in a '\' */ >+ if (namelen > 0 && name[namelen-1] == '\\') { >+ char *modname = talloc_strdup(frame, name); >+ if (modname == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; >+ } >+ modname[namelen-1] = '\0'; >+ name = modname; >+ } >+ >+ /* Try to open a file handle first. */ >+ status = smb2cli_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 */ >+ 0, /* create_options */ >+ pfnum, >+ NULL); >+ >+ if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { >+ status = smb2cli_create_fnum(cli, >+ name, >+ 0, /* create_flags */ >+ 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, /* create_options */ >+ pfnum, >+ NULL); >+ } >+ >+ fail: >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a path info (ALTNAME level). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_qpathinfo_alt_name(struct cli_state *cli, >+ const char *name, >+ fstring alt_name) >+{ >+ NTSTATUS status; >+ DATA_BLOB outbuf = data_blob_null; >+ uint16_t fnum = -1; >+ struct smb2_hnd *ph = NULL; >+ uint32_t altnamelen = 0; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ name, >+ FILE_READ_ATTRIBUTES, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1), >+ level SMB_FILE_ALTERNATE_NAME_INFORMATION (1021) == SMB2 21 */ >+ >+ status = smb2cli_query_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ (SMB_FILE_ALTERNATE_NAME_INFORMATION - 1000), /* in_file_info_class */ >+ 0xFFFF, /* in_max_output_length */ >+ NULL, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ 0, /* in_flags */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ frame, >+ &outbuf); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Parse the reply. */ >+ if (outbuf.length < 4) { >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ altnamelen = IVAL(outbuf.data, 0); >+ if (altnamelen > outbuf.length - 4) { >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ if (altnamelen > 0) { >+ size_t ret = 0; >+ char *short_name = NULL; >+ ret = pull_string_talloc(frame, >+ outbuf.data, >+ FLAGS2_UNICODE_STRINGS, >+ &short_name, >+ outbuf.data + 4, >+ altnamelen, >+ STR_UNICODE); >+ if (ret == (size_t)-1) { >+ /* Bad conversion. */ >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ fstrcpy(alt_name, short_name); >+ } else { >+ alt_name[0] = '\0'; >+ } >+ >+ status = NT_STATUS_OK; >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a fnum info (basic level). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_qfileinfo_basic(struct cli_state *cli, >+ uint16_t fnum, >+ uint16_t *mode, >+ off_t *size, >+ struct timespec *create_time, >+ struct timespec *access_time, >+ struct timespec *write_time, >+ struct timespec *change_time, >+ SMB_INO_T *ino) >+{ >+ NTSTATUS status; >+ DATA_BLOB outbuf = data_blob_null; >+ struct smb2_hnd *ph = NULL; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1), >+ level 0x12 (SMB2_FILE_ALL_INFORMATION). */ >+ >+ status = smb2cli_query_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ (SMB_FILE_ALL_INFORMATION - 1000), /* in_file_info_class */ >+ 0xFFFF, /* in_max_output_length */ >+ NULL, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ 0, /* in_flags */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ frame, >+ &outbuf); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Parse the reply. */ >+ if (outbuf.length < 0x60) { >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ if (create_time) { >+ *create_time = interpret_long_date((const char *)outbuf.data + 0x0); >+ } >+ if (access_time) { >+ *access_time = interpret_long_date((const char *)outbuf.data + 0x8); >+ } >+ if (write_time) { >+ *write_time = interpret_long_date((const char *)outbuf.data + 0x10); >+ } >+ if (change_time) { >+ *change_time = interpret_long_date((const char *)outbuf.data + 0x18); >+ } >+ if (mode) { >+ uint32_t attr = IVAL(outbuf.data, 0x20); >+ *mode = (uint16_t)attr; >+ } >+ if (size) { >+ uint64_t file_size = BVAL(outbuf.data, 0x30); >+ *size = (off_t)file_size; >+ } >+ if (ino) { >+ uint64_t file_index = BVAL(outbuf.data, 0x40); >+ *ino = (SMB_INO_T)file_index; >+ } >+ >+ fail: >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query an fnum. >+ Implement on top of smb2cli_qfileinfo_basic(). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_getattrE(struct cli_state *cli, >+ uint16_t fnum, >+ uint16_t *attr, >+ off_t *size, >+ time_t *change_time, >+ time_t *access_time, >+ time_t *write_time) >+{ >+ struct timespec access_time_ts; >+ struct timespec write_time_ts; >+ struct timespec change_time_ts; >+ NTSTATUS status = smb2cli_qfileinfo_basic(cli, >+ fnum, >+ attr, >+ size, >+ NULL, >+ &access_time_ts, >+ &write_time_ts, >+ &change_time_ts, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ if (change_time) { >+ *change_time = change_time_ts.tv_sec; >+ } >+ if (access_time) { >+ *access_time = access_time_ts.tv_sec; >+ } >+ if (write_time) { >+ *write_time = write_time_ts.tv_sec; >+ } >+ return NT_STATUS_OK; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a pathname info (basic level). >+ Implement on top of smb2cli_qfileinfo_basic(). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_qpathinfo2(struct cli_state *cli, >+ const char *name, >+ struct timespec *create_time, >+ struct timespec *access_time, >+ struct timespec *write_time, >+ struct timespec *change_time, >+ off_t *size, >+ uint16_t *mode, >+ SMB_INO_T *ino) >+{ >+ NTSTATUS status; >+ struct smb2_hnd *ph = NULL; >+ uint16_t fnum = -1; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ name, >+ FILE_READ_ATTRIBUTES, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = smb2cli_qfileinfo_basic(cli, >+ fnum, >+ mode, >+ size, >+ create_time, >+ access_time, >+ write_time, >+ change_time, >+ ino); >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query pathname streams. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_qpathinfo_streams(struct cli_state *cli, >+ const char *name, >+ TALLOC_CTX *mem_ctx, >+ unsigned int *pnum_streams, >+ struct stream_struct **pstreams) >+{ >+ NTSTATUS status; >+ struct smb2_hnd *ph = NULL; >+ uint16_t fnum = -1; >+ DATA_BLOB outbuf = data_blob_null; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ name, >+ FILE_READ_ATTRIBUTES, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1), >+ level 22 (SMB2_FILE_STREAM_INFORMATION). */ >+ >+ status = smb2cli_query_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ (SMB_FILE_STREAM_INFORMATION - 1000), /* in_file_info_class */ >+ 0xFFFF, /* in_max_output_length */ >+ NULL, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ 0, /* in_flags */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ frame, >+ &outbuf); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Parse the reply. */ >+ if (!parse_streams_blob(mem_ctx, >+ outbuf.data, >+ outbuf.length, >+ pnum_streams, >+ pstreams)) { >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set pathname attributes. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_setatr(struct cli_state *cli, >+ const char *name, >+ uint16_t attr, >+ time_t mtime) >+{ >+ NTSTATUS status; >+ uint16_t fnum = -1; >+ struct smb2_hnd *ph = NULL; >+ uint8_t inbuf_store[36]; >+ DATA_BLOB inbuf = data_blob_null; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ name, >+ FILE_WRITE_ATTRIBUTES, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1), >+ level 4 (SMB_FILE_BASIC_INFORMATION - 1000). */ >+ >+ inbuf.data = inbuf_store; >+ inbuf.length = sizeof(inbuf_store); >+ data_blob_clear(&inbuf); >+ >+ SIVAL(inbuf.data,32,attr); >+ if (mtime != 0) { >+ put_long_date((char *)inbuf.data + 16,mtime); >+ } >+ >+ status = smb2cli_set_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ SMB_FILE_BASIC_INFORMATION - 1000, /* in_file_info_class */ >+ &inbuf, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ ph->fid_persistent, >+ ph->fid_volatile); >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set file handle times. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_setattrE(struct cli_state *cli, >+ uint16_t fnum, >+ time_t change_time, >+ time_t access_time, >+ time_t write_time) >+{ >+ NTSTATUS status; >+ struct smb2_hnd *ph = NULL; >+ uint8_t inbuf_store[36]; >+ DATA_BLOB inbuf = data_blob_null; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1), >+ level 4 (SMB_FILE_BASIC_INFORMATION - 1000). */ >+ >+ inbuf.data = inbuf_store; >+ inbuf.length = sizeof(inbuf_store); >+ data_blob_clear(&inbuf); >+ >+ if (change_time != 0) { >+ put_long_date((char *)inbuf.data + 24, change_time); >+ } >+ if (access_time != 0) { >+ put_long_date((char *)inbuf.data + 8, access_time); >+ } >+ if (write_time != 0) { >+ put_long_date((char *)inbuf.data + 16, write_time); >+ } >+ >+ return smb2cli_set_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ SMB_FILE_BASIC_INFORMATION - 1000, /* in_file_info_class */ >+ &inbuf, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ ph->fid_persistent, >+ ph->fid_volatile); >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query disk attributes (size). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) >+{ >+ NTSTATUS status; >+ uint16_t fnum = -1; >+ DATA_BLOB outbuf = data_blob_null; >+ struct smb2_hnd *ph = NULL; >+ uint32_t sectors_per_unit = 0; >+ uint32_t bytes_per_sector = 0; >+ uint64_t total_size = 0; >+ uint64_t size_free = 0; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ /* First open the top level directory. */ >+ status = smb2cli_create_fnum(cli, >+ "", >+ 0, /* create_flags */ >+ FILE_READ_ATTRIBUTES, /* 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, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* getinfo on the returned handle with info_type SMB2_GETINFO_FS (2), >+ level 3 (SMB_FS_SIZE_INFORMATION). */ >+ >+ status = smb2cli_query_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 2, /* in_info_type */ >+ 3, /* in_file_info_class */ >+ 0xFFFF, /* in_max_output_length */ >+ NULL, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ 0, /* in_flags */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ frame, >+ &outbuf); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Parse the reply. */ >+ if (outbuf.length != 24) { >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ total_size = BVAL(outbuf.data, 0); >+ size_free = BVAL(outbuf.data, 8); >+ sectors_per_unit = IVAL(outbuf.data, 16); >+ bytes_per_sector = IVAL(outbuf.data, 20); >+ >+ if (bsize) { >+ *bsize = (int)(sectors_per_unit * bytes_per_sector); >+ } >+ if (total) { >+ *total = (int)total_size; >+ } >+ if (avail) { >+ *avail = (int)size_free; >+ } >+ >+ status = NT_STATUS_OK; >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a security descriptor. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_query_security_descriptor(struct cli_state *cli, >+ uint16_t fnum, >+ uint32_t sec_info, >+ TALLOC_CTX *mem_ctx, >+ struct security_descriptor **ppsd) >+{ >+ NTSTATUS status; >+ DATA_BLOB outbuf = data_blob_null; >+ struct smb2_hnd *ph = NULL; >+ struct security_descriptor *lsd = NULL; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* getinfo on the returned handle with info_type SMB2_GETINFO_SEC (3) */ >+ >+ status = smb2cli_query_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 3, /* in_info_type */ >+ 0, /* in_file_info_class */ >+ 0xFFFF, /* in_max_output_length */ >+ NULL, /* in_input_buffer */ >+ sec_info, /* in_additional_info */ >+ 0, /* in_flags */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ frame, >+ &outbuf); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Parse the reply. */ >+ status = unmarshall_sec_desc(mem_ctx, >+ outbuf.data, >+ outbuf.length, >+ &lsd); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ if (ppsd != NULL) { >+ *ppsd = lsd; >+ } else { >+ TALLOC_FREE(lsd); >+ } >+ >+ fail: >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set a security descriptor. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_set_security_descriptor(struct cli_state *cli, >+ uint16_t fnum, >+ uint32_t sec_info, >+ const struct security_descriptor *sd) >+{ >+ NTSTATUS status; >+ DATA_BLOB inbuf = data_blob_null; >+ struct smb2_hnd *ph = NULL; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = marshall_sec_desc(frame, >+ sd, >+ &inbuf.data, >+ &inbuf.length); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* setinfo on the returned handle with info_type SMB2_SETINFO_SEC (3) */ >+ >+ status = smb2cli_set_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 3, /* in_info_type */ >+ 0, /* in_file_info_class */ >+ &inbuf, /* in_input_buffer */ >+ sec_info, /* in_additional_info */ >+ ph->fid_persistent, >+ ph->fid_volatile); >+ >+ fail: >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to rename a file. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_rename(struct cli_state *cli, >+ const char *fname_src, >+ const char *fname_dst) >+{ >+ NTSTATUS status; >+ DATA_BLOB inbuf = data_blob_null; >+ uint16_t fnum = -1; >+ struct smb2_hnd *ph = NULL; >+ smb_ucs2_t *converted_str = NULL; >+ size_t converted_size_bytes = 0; >+ size_t namelen = 0; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ fname_src, >+ DELETE_ACCESS, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* SMB2 is pickier about pathnames. Ensure it doesn't >+ start in a '\' */ >+ if (*fname_dst == '\\') { >+ fname_dst++; >+ } >+ >+ /* SMB2 is pickier about pathnames. Ensure it doesn't >+ end in a '\' */ >+ namelen = strlen(fname_dst); >+ if (namelen > 0 && fname_dst[namelen-1] == '\\') { >+ char *modname = talloc_strdup(frame, fname_dst); >+ modname[namelen-1] = '\0'; >+ fname_dst = modname; >+ } >+ >+ if (!push_ucs2_talloc(frame, >+ &converted_str, >+ fname_dst, >+ &converted_size_bytes)) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ /* W2K8 insists the dest name is not null >+ terminated. Remove the last 2 zero bytes >+ and reduce the name length. */ >+ >+ if (converted_size_bytes < 2) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ converted_size_bytes -= 2; >+ >+ inbuf = data_blob_talloc_zero(frame, >+ 20 + converted_size_bytes); >+ if (inbuf.data == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; >+ } >+ >+ SIVAL(inbuf.data, 16, converted_size_bytes); >+ memcpy(inbuf.data + 20, converted_str, converted_size_bytes); >+ >+ /* setinfo on the returned handle with info_type SMB2_GETINFO_FILE (1), >+ level SMB2_FILE_RENAME_INFORMATION (SMB_FILE_RENAME_INFORMATION - 1000) */ >+ >+ status = smb2cli_set_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ SMB_FILE_RENAME_INFORMATION - 1000, /* in_file_info_class */ >+ &inbuf, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ ph->fid_persistent, >+ ph->fid_volatile); >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set an EA on a fnum. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_set_ea_fnum(struct cli_state *cli, >+ uint16_t fnum, >+ const char *ea_name, >+ const char *ea_val, >+ size_t ea_len) >+{ >+ NTSTATUS status; >+ DATA_BLOB inbuf = data_blob_null; >+ size_t bloblen = 0; >+ char *ea_name_ascii = NULL; >+ size_t namelen = 0; >+ struct smb2_hnd *ph = NULL; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Marshall the SMB2 EA data. */ >+ if (ea_len > 0xFFFF) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (!push_ascii_talloc(frame, >+ &ea_name_ascii, >+ ea_name, >+ &namelen)) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (namelen < 2 || namelen > 0xFF) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ bloblen = 8 + ea_len + namelen; >+ /* Round up to a 4 byte boundary. */ >+ bloblen = ((bloblen + 3)&~3); >+ >+ inbuf = data_blob_talloc_zero(frame, bloblen); >+ if (inbuf.data == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; >+ } >+ /* namelen doesn't include the NULL byte. */ >+ SCVAL(inbuf.data, 5, namelen - 1); >+ SSVAL(inbuf.data, 6, ea_len); >+ memcpy(inbuf.data + 8, ea_name_ascii, namelen); >+ memcpy(inbuf.data + 8 + namelen, ea_val, ea_len); >+ >+ /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1), >+ level 15 (SMB_FILE_FULL_EA_INFORMATION - 1000). */ >+ >+ status = smb2cli_set_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ SMB_FILE_FULL_EA_INFORMATION - 1000, /* in_file_info_class */ >+ &inbuf, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ ph->fid_persistent, >+ ph->fid_volatile); >+ >+ fail: >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set an EA on a pathname. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_set_ea_path(struct cli_state *cli, >+ const char *name, >+ const char *ea_name, >+ const char *ea_val, >+ size_t ea_len) >+{ >+ NTSTATUS status; >+ uint16_t fnum = -1; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ name, >+ FILE_WRITE_EA, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = cli_set_ea_fnum(cli, >+ fnum, >+ ea_name, >+ ea_val, >+ ea_len); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ fail: >+ >+ if (fnum != -1) { >+ smb2cli_close_fnum(cli, fnum); >+ } >+ >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to get an EA list on a pathname. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS smb2cli_get_ea_list_path(struct cli_state *cli, >+ const char *name, >+ TALLOC_CTX *ctx, >+ size_t *pnum_eas, >+ struct ea_struct **pea_array) >+{ >+ NTSTATUS status; >+ uint16_t fnum = -1; >+ DATA_BLOB outbuf = data_blob_null; >+ struct smb2_hnd *ph = NULL; >+ struct ea_list *ea_list = NULL; >+ struct ea_list *eal = NULL; >+ size_t ea_count = 0; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ *pnum_eas = 0; >+ *pea_array = NULL; >+ >+ if (smbXcli_conn_has_async_calls(cli->conn)) { >+ /* >+ * Can't use sync call while an async call is in flight >+ */ >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { >+ status = NT_STATUS_INVALID_PARAMETER; >+ goto fail; >+ } >+ >+ status = get_fnum_from_path(cli, >+ name, >+ FILE_READ_EA, >+ &fnum); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1), >+ level 15 (SMB_FILE_FULL_EA_INFORMATION - 1000). */ >+ >+ status = smb2cli_query_info(cli->conn, >+ cli->timeout, >+ cli->smb2.session, >+ cli->smb2.tcon, >+ 1, /* in_info_type */ >+ SMB_FILE_FULL_EA_INFORMATION - 1000, /* in_file_info_class */ >+ 0xFFFF, /* in_max_output_length */ >+ NULL, /* in_input_buffer */ >+ 0, /* in_additional_info */ >+ 0, /* in_flags */ >+ ph->fid_persistent, >+ ph->fid_volatile, >+ frame, >+ &outbuf); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ /* Parse the reply. */ >+ ea_list = read_nttrans_ea_list(ctx, >+ (const char *)outbuf.data, >+ outbuf.length); >+ if (ea_list == NULL) { >+ status = NT_STATUS_INVALID_NETWORK_RESPONSE; >+ goto fail; >+ } >+ >+ /* Convert to an array. */ >+ for (eal = ea_list; eal; eal = eal->next) { >+ ea_count++; >+ } >+ >+ if (ea_count) { >+ *pea_array = talloc_array(ctx, struct ea_struct, ea_count); >+ if (*pea_array == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; >+ } >+ ea_count = 0; >+ for (eal = ea_list; eal; eal = eal->next) { >+ (*pea_array)[ea_count++] = ea_list->ea; >+ } >+ *pnum_eas = ea_count; >+ } >+ >+ fail: >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 async read using an fnum. >+ This is mostly cut-and-paste from Volker's code inside >+ source3/libsmb/clireadwrite.c, adapted for SMB2. >+ >+ Done this way so I can reuse all the logic inside cli_pull() >+ for free :-). >+***************************************************************/ >+ >+struct smb2cli_readall_state { >+ struct tevent_context *ev; >+ struct cli_state *cli; >+ struct smb2_hnd *ph; >+ uint64_t start_offset; >+ uint32_t size; >+ uint32_t received; >+ uint8_t *buf; >+}; >+ >+static void smb2cli_readall_fnum_done(struct tevent_req *subreq); >+ >+struct tevent_req *smb2cli_readall_fnum_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cli_state *cli, >+ uint16_t fnum, >+ off_t offset, >+ size_t size) >+{ >+ NTSTATUS status; >+ struct tevent_req *req, *subreq; >+ struct smb2cli_readall_state *state; >+ >+ req = tevent_req_create(mem_ctx, &state, struct smb2cli_readall_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->cli = cli; >+ state->start_offset = (uint64_t)offset; >+ state->size = (uint32_t)size; >+ state->received = 0; >+ state->buf = NULL; >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &state->ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ return NULL; >+ } >+ >+ subreq = smb2cli_read_send(state, >+ state->ev, >+ state->cli->conn, >+ state->cli->timeout, >+ state->cli->smb2.session, >+ state->cli->smb2.tcon, >+ state->size, >+ state->start_offset, >+ state->ph->fid_persistent, >+ state->ph->fid_volatile, >+ 0, /* minimum_count */ >+ 0); /* remaining_bytes */ >+ >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, smb2cli_readall_fnum_done, req); >+ return req; >+} >+ >+static void smb2cli_readall_fnum_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct smb2cli_readall_state *state = tevent_req_data( >+ req, struct smb2cli_readall_state); >+ uint32_t received = 0; >+ uint8_t *buf = NULL; >+ NTSTATUS status; >+ >+ status = smb2cli_read_recv(subreq, state, &buf, &received); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ if (received == 0) { >+ /* EOF */ >+ tevent_req_done(req); >+ return; >+ } >+ >+ if (received > state->size) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); >+ return; >+ } >+ >+ if ((state->received == 0) && (received == state->size)) { >+ /* Ideal case: Got it all in one run */ >+ state->buf = buf; >+ state->received += received; >+ tevent_req_done(req); >+ return; >+ } >+ /* >+ * We got a short read, issue a read for the >+ * rest. Unfortunately we have to allocate the buffer >+ * ourselves now, as our caller expects to receive a single >+ * buffer. smb2cli_read does it from the buffer received from >+ * the net, but with a short read we have to put it together >+ * from several reads. >+ */ >+ >+ if (state->buf == NULL) { >+ state->buf = talloc_array(state, uint8_t, state->size); >+ if (tevent_req_nomem(state->buf, req)) { >+ return; >+ } >+ } >+ memcpy(state->buf + state->received, buf, received); >+ state->received += received; >+ >+ TALLOC_FREE(subreq); >+ >+ if (state->received >= state->size) { >+ tevent_req_done(req); >+ return; >+ } >+ >+ subreq = smb2cli_read_send(state, >+ state->ev, >+ state->cli->conn, >+ state->cli->timeout, >+ state->cli->smb2.session, >+ state->cli->smb2.tcon, >+ state->size - state->received, >+ state->start_offset + state->received, >+ state->ph->fid_persistent, >+ state->ph->fid_volatile, >+ 0, /* minimum_count */ >+ 0); /* remaining_bytes */ >+ >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, smb2cli_readall_fnum_done, req); >+} >+ >+NTSTATUS smb2cli_readall_fnum_recv(struct tevent_req *req, >+ ssize_t *received, >+ uint8_t **rcvbuf) >+{ >+ NTSTATUS status; >+ struct smb2cli_readall_state *state = tevent_req_data( >+ req, struct smb2cli_readall_state); >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ *received = (ssize_t)state->received; >+ *rcvbuf = state->buf; >+ return NT_STATUS_OK; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 async write using an fnum. >+ This is mostly cut-and-paste from Volker's code inside >+ source3/libsmb/clireadwrite.c, adapted for SMB2. >+ >+ Done this way so I can reuse all the logic inside cli_push() >+ for free :-). >+***************************************************************/ >+ >+struct smb2cli_writeall_state { >+ struct tevent_context *ev; >+ struct cli_state *cli; >+ struct smb2_hnd *ph; >+ uint32_t flags; >+ const uint8_t *buf; >+ uint64_t offset; >+ uint32_t size; >+ uint32_t written; >+}; >+ >+static void smb2cli_writeall_written(struct tevent_req *req); >+ >+struct tevent_req *smb2cli_writeall_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cli_state *cli, >+ uint16_t fnum, >+ uint16_t mode, >+ const uint8_t *buf, >+ off_t offset, >+ size_t size) >+{ >+ NTSTATUS status; >+ struct tevent_req *req, *subreq = NULL; >+ struct smb2cli_writeall_state *state = NULL; >+ >+ req = tevent_req_create(mem_ctx, &state, struct smb2cli_writeall_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->cli = cli; >+ /* Both SMB1 and SMB2 use 1 in the following meaning write-through. */ >+ state->flags = (uint32_t)mode; >+ state->buf = buf; >+ state->offset = (uint64_t)offset; >+ state->size = (uint32_t)size; >+ state->written = 0; >+ >+ status = map_fnum_to_smb2_handle(cli, >+ fnum, >+ &state->ph); >+ if (!NT_STATUS_IS_OK(status)) { >+ return NULL; >+ } >+ >+ subreq = smb2cli_write_send(state, >+ state->ev, >+ state->cli->conn, >+ state->cli->timeout, >+ state->cli->smb2.session, >+ state->cli->smb2.tcon, >+ state->size, >+ state->offset, >+ state->ph->fid_persistent, >+ state->ph->fid_volatile, >+ 0, /* remaining_bytes */ >+ state->flags, /* flags */ >+ state->buf); >+ >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, smb2cli_writeall_written, req); >+ return req; >+} >+ >+static void smb2cli_writeall_written(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct smb2cli_writeall_state *state = tevent_req_data( >+ req, struct smb2cli_writeall_state); >+ NTSTATUS status; >+ uint32_t written, to_write; >+ >+ status = smb2cli_write_recv(subreq, &written); >+ TALLOC_FREE(subreq); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ state->written += written; >+ >+ if (state->written > state->size) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); >+ return; >+ } >+ >+ to_write = state->size - state->written; >+ >+ if (to_write == 0) { >+ tevent_req_done(req); >+ return; >+ } >+ >+ subreq = smb2cli_write_send(state, >+ state->ev, >+ state->cli->conn, >+ state->cli->timeout, >+ state->cli->smb2.session, >+ state->cli->smb2.tcon, >+ to_write, >+ state->offset + state->written, >+ state->ph->fid_persistent, >+ state->ph->fid_volatile, >+ 0, /* remaining_bytes */ >+ state->flags, /* flags */ >+ state->buf + state->written); >+ >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, smb2cli_writeall_written, req); >+} >+ >+NTSTATUS smb2cli_writeall_recv(struct tevent_req *req, >+ size_t *pwritten) >+{ >+ struct smb2cli_writeall_state *state = tevent_req_data( >+ req, struct smb2cli_writeall_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ if (pwritten != NULL) { >+ *pwritten = (size_t)state->written; >+ } >+ return NT_STATUS_OK; >+} >diff --git a/source3/libsmb/smb2cli_fnum.h b/source3/libsmb/smb2cli_fnum.h >new file mode 100644 >index 0000000..8933afd >--- /dev/null >+++ b/source3/libsmb/smb2cli_fnum.h >@@ -0,0 +1,146 @@ >+/* >+ Unix SMB/CIFS implementation. >+ smb2 wrapper client routines >+ Copyright (C) Jeremy Allison 2013 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#ifndef __SMB2CLI_FNUM_H__ >+#define __SMB2CLI_FNUM_H__ >+ >+struct smbXcli_conn; >+struct smbXcli_session; >+struct cli_state; >+struct file_info; >+ >+NTSTATUS smb2cli_create_fnum(struct cli_state *cli, >+ const char *fname, >+ uint32_t create_flags, >+ uint32_t desired_access, >+ uint32_t file_attributes, >+ uint32_t share_access, >+ uint32_t create_disposition, >+ uint32_t create_options, >+ uint16_t *pfid, >+ struct smb2_create_returns *cr); >+ >+NTSTATUS smb2cli_close_fnum(struct cli_state *cli, uint16_t fnum); >+NTSTATUS smb2cli_mkdir(struct cli_state *cli, const char *dirname); >+NTSTATUS smb2cli_rmdir(struct cli_state *cli, const char *dirname); >+NTSTATUS smb2cli_unlink(struct cli_state *cli,const char *fname); >+NTSTATUS smb2cli_list(struct cli_state *cli, >+ const char *pathname, >+ NTSTATUS (*fn)(const char *, >+ struct file_info *, >+ const char *, >+ void *), >+ void *state); >+NTSTATUS smb2cli_qpathinfo_basic(struct cli_state *cli, >+ const char *name, >+ SMB_STRUCT_STAT *sbuf, >+ uint32_t *attributes); >+NTSTATUS smb2cli_qpathinfo_alt_name(struct cli_state *cli, >+ const char *name, >+ fstring alt_name); >+NTSTATUS smb2cli_qfileinfo_basic(struct cli_state *cli, >+ uint16_t fnum, >+ uint16_t *mode, >+ off_t *size, >+ struct timespec *create_time, >+ struct timespec *access_time, >+ struct timespec *write_time, >+ struct timespec *change_time, >+ SMB_INO_T *ino); >+NTSTATUS smb2cli_getattrE(struct cli_state *cli, >+ uint16_t fnum, >+ uint16_t *attr, >+ off_t *size, >+ time_t *change_time, >+ time_t *access_time, >+ time_t *write_time); >+NTSTATUS smb2cli_qpathinfo2(struct cli_state *cli, >+ const char *fname, >+ struct timespec *create_time, >+ struct timespec *access_time, >+ struct timespec *write_time, >+ struct timespec *change_time, >+ off_t *size, >+ uint16_t *mode, >+ SMB_INO_T *ino); >+NTSTATUS smb2cli_qpathinfo_streams(struct cli_state *cli, >+ const char *name, >+ TALLOC_CTX *mem_ctx, >+ unsigned int *pnum_streams, >+ struct stream_struct **pstreams); >+NTSTATUS smb2cli_setatr(struct cli_state *cli, >+ const char *fname, >+ uint16_t attr, >+ time_t mtime); >+NTSTATUS smb2cli_setattrE(struct cli_state *cli, >+ uint16_t fnum, >+ time_t change_time, >+ time_t access_time, >+ time_t write_time); >+NTSTATUS smb2cli_dskattr(struct cli_state *cli, >+ int *bsize, >+ int *total, >+ int *avail); >+NTSTATUS smb2cli_query_security_descriptor(struct cli_state *cli, >+ uint16_t fnum, >+ uint32_t sec_info, >+ TALLOC_CTX *mem_ctx, >+ struct security_descriptor **ppsd); >+NTSTATUS smb2cli_set_security_descriptor(struct cli_state *cli, >+ uint16_t fnum, >+ uint32_t sec_info, >+ const struct security_descriptor *sd); >+NTSTATUS smb2cli_rename(struct cli_state *cli, >+ const char *fname_src, >+ const char *fname_dst); >+NTSTATUS smb2cli_set_ea_fnum(struct cli_state *cli, >+ uint16_t fnum, >+ const char *ea_name, >+ const char *ea_val, >+ size_t ea_len); >+NTSTATUS smb2cli_get_ea_list_path(struct cli_state *cli, >+ const char *name, >+ TALLOC_CTX *ctx, >+ size_t *pnum_eas, >+ struct ea_struct **pea_list); >+NTSTATUS smb2cli_set_ea_path(struct cli_state *cli, >+ const char *name, >+ const char *ea_name, >+ const char *ea_val, >+ size_t ea_len); >+struct tevent_req *smb2cli_readall_fnum_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cli_state *cli, >+ uint16_t fnum, >+ off_t offset, >+ size_t size); >+NTSTATUS smb2cli_readall_fnum_recv(struct tevent_req *req, >+ ssize_t *received, >+ uint8_t **rcvbuf); >+struct tevent_req *smb2cli_writeall_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cli_state *cli, >+ uint16_t fnum, >+ uint16_t mode, >+ const uint8_t *buf, >+ off_t offset, >+ size_t size); >+NTSTATUS smb2cli_writeall_recv(struct tevent_req *req, >+ size_t *pwritten); >+#endif /* __SMB2CLI_FNUM_H__ */ >diff --git a/source3/wscript_build b/source3/wscript_build >index e3605e3..0e0be74 100755 >--- a/source3/wscript_build >+++ b/source3/wscript_build >@@ -135,7 +135,8 @@ LIBSMB_SRC = '''libsmb/clientgen.c libsmb/cliconnect.c libsmb/clifile.c > libsmb/cli_np_tstream.c > libsmb/reparse_symlink.c > libsmb/clisymlink.c >- libsmb/smbsock_connect.c''' >+ libsmb/smbsock_connect.c >+ libsmb/smb2cli_fnum.c''' > > LIBMSRPC_SRC = ''' > rpc_client/cli_pipe.c >-- >1.8.3 > > >From 070a3781338d1bdc2df53b7789754ca2ea7c64e2 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:59:13 -0700 >Subject: [PATCH 07/37] Plumb smb2cli_rename() inside cli_rename(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 4b4e1a0..ee19feb 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -21,6 +21,8 @@ > #include "includes.h" > #include "system/filesys.h" > #include "libsmb/libsmb.h" >+#include "libsmb/smb2cli.h" >+#include "libsmb/smb2cli_fnum.h" > #include "../lib/util/tevent_ntstatus.h" > #include "async_smb.h" > #include "libsmb/clirap.h" >@@ -1097,11 +1099,19 @@ NTSTATUS cli_rename_recv(struct tevent_req *req) > > NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_rename(cli, >+ fname_src, >+ fname_dst); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From b91a2aa338da41189b84bd708c646d8bd23bf351 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:00:40 -0700 >Subject: [PATCH 08/37] Plumb smb2cli_unlink() inside cli_unlink(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index ee19feb..9a06bf3 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1417,11 +1417,17 @@ NTSTATUS cli_unlink_recv(struct tevent_req *req) > > NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_unlink(cli, fname); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 8fccd610be1ab812d287867b554cd5acc13f1b24 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:01:49 -0700 >Subject: [PATCH 09/37] Plumb smb2cli_mkdir() inside cli_mkdir(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 9a06bf3..75d0c42 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1527,11 +1527,17 @@ NTSTATUS cli_mkdir_recv(struct tevent_req *req) > > NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_mkdir(cli, dname); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From bb9d21fb37aa47697dc77056097d39a85fc4bb9f Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:03:00 -0700 >Subject: [PATCH 10/37] Plumb smb2cli_rmdir() inside cli_rmdir(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 75d0c42..ba32b9e 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1637,11 +1637,17 @@ NTSTATUS cli_rmdir_recv(struct tevent_req *req) > > NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_rmdir(cli, dname); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 3caf3183d7074ad3f900726b86a44c8572a7ebe6 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:06:19 -0700 >Subject: [PATCH 11/37] Plumb smb2cli_create_fnum() inside cli_ntcreate(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 17 ++++++++++++++++- > 1 file changed, 16 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index ba32b9e..42698dc 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1916,11 +1916,26 @@ NTSTATUS cli_ntcreate(struct cli_state *cli, > uint8_t SecurityFlags, > uint16_t *pfid) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_create_fnum(cli, >+ fname, >+ CreatFlags, >+ DesiredAccess, >+ FileAttributes, >+ ShareAccess, >+ CreateDisposition, >+ CreateOptions, >+ pfid, >+ NULL); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From fa2d06451fd4a47dc5537a6a6034d23a4aa63083 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:10:34 -0700 >Subject: [PATCH 12/37] Plumb smb2cli_close_fnum() inside cli_close(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 42698dc..bdf4677 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -2538,11 +2538,17 @@ NTSTATUS cli_close_recv(struct tevent_req *req) > > NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_close_fnum(cli, fnum); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From eb90104d0287b80fb6200e37c940999cc8bcc71b Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:11:59 -0700 >Subject: [PATCH 13/37] Plumb smb2cli_getattrE() inside cli_getattrE(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 14 +++++++++++++- > 1 file changed, 13 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index bdf4677..f3e89fc 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3381,11 +3381,23 @@ NTSTATUS cli_getattrE(struct cli_state *cli, > time_t *access_time, > time_t *write_time) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev = NULL; > struct tevent_req *req = NULL; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_getattrE(cli, >+ fnum, >+ attr, >+ size, >+ change_time, >+ access_time, >+ write_time); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 02788945fbbcb394377a54c256ccbd46f4de7195 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:14:47 -0700 >Subject: [PATCH 14/37] Plumb smb2cli_setattrE() inside cli_setattrE(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index f3e89fc..5cb6b9c 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3649,11 +3649,21 @@ NTSTATUS cli_setattrE(struct cli_state *cli, > time_t access_time, > time_t write_time) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev = NULL; > struct tevent_req *req = NULL; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_setattrE(cli, >+ fnum, >+ change_time, >+ access_time, >+ write_time); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 77eab36f9e8e32b050931a88bbac1284f1f672d3 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:16:03 -0700 >Subject: [PATCH 15/37] Plumb smb2cli_setatr() inside cli_setatr(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 5cb6b9c..5b19597 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3788,11 +3788,20 @@ NTSTATUS cli_setatr(struct cli_state *cli, > uint16_t attr, > time_t mtime) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev = NULL; > struct tevent_req *req = NULL; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_setatr(cli, >+ fname, >+ attr, >+ mtime); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 68c4737d0d72bc481bcefda340836d457c2db7b3 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:17:12 -0700 >Subject: [PATCH 16/37] Plumb smb2cli_dskattr() inside cli_dskattr(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 5b19597..5ffa571 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4026,11 +4026,17 @@ NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *a > > NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev = NULL; > struct tevent_req *req = NULL; > NTSTATUS status = NT_STATUS_OK; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_dskattr(cli, bsize, total, avail); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 44d2c91e791cf29f3c4f4b20182124f0442bdc04 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:19:06 -0700 >Subject: [PATCH 17/37] Fix cli_set_ea_path() to use frame instead of > talloc_tos(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 10 +++++++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 5ffa571..0a5cfdc 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4314,9 +4314,10 @@ NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path, > NTSTATUS status; > TALLOC_CTX *frame = talloc_stackframe(); > >- param = talloc_array(talloc_tos(), uint8_t, 6); >+ param = talloc_array(frame, uint8_t, 6); > if (!param) { >- return NT_STATUS_NO_MEMORY; >+ status = NT_STATUS_NO_MEMORY; >+ goto fail; > } > SSVAL(param,0,SMB_INFO_SET_EA); > SSVAL(param,2,0); >@@ -4329,7 +4330,10 @@ NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path, > > status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len, > ea_name, ea_val, ea_len); >- talloc_free(frame); >+ >+ fail: >+ >+ TALLOC_FREE(frame); > return status; > } > >-- >1.8.3 > > >From 1f686e21e995b998d7cc99b2edd7b622605daf61 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:21:48 -0700 >Subject: [PATCH 18/37] Plumb smb2cli_set_ea_path() inside cli_set_ea_path(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 0a5cfdc..e95778c 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4312,7 +4312,17 @@ NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path, > unsigned int param_len = 0; > uint8_t *param; > NTSTATUS status; >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; >+ >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_set_ea_path(cli, >+ path, >+ ea_name, >+ ea_val, >+ ea_len); >+ } >+ >+ frame = talloc_stackframe(); > > param = talloc_array(frame, uint8_t, 6); > if (!param) { >-- >1.8.3 > > >From 9d63158d35c2dca5cd661288197b6a3641908c4a Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:32:55 -0700 >Subject: [PATCH 19/37] Plumb smb2cli_set_ea_fnum() inside cli_set_ea_fnum(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index e95778c..0eb3995 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4357,6 +4357,14 @@ NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum, > { > uint8_t param[6]; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_set_ea_fnum(cli, >+ fnum, >+ ea_name, >+ ea_val, >+ ea_len); >+ } >+ > memset(param, 0, 6); > SSVAL(param,0,fnum); > SSVAL(param,2,SMB_INFO_SET_EA); >-- >1.8.3 > > >From 9c31eb4edf57a2841274aebed7d6969d20d31ea9 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:42:02 -0700 >Subject: [PATCH 20/37] Plumb smb2cli_get_ea_list_path() inside > cli_get_ea_list_path(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clifile.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 0eb3995..e47f49e 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4546,11 +4546,21 @@ NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path, > size_t *pnum_eas, > struct ea_struct **pea_list) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev = NULL; > struct tevent_req *req = NULL; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_get_ea_list_path(cli, >+ path, >+ ctx, >+ pnum_eas, >+ pea_list); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 66121c00ce788b1f34c3faad5d955f6ca704b94d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:43:33 -0700 >Subject: [PATCH 21/37] Plumb smb2cli_list() inside cli_list(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clilist.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c >index b0d3a4e..51e6f9f 100644 >--- a/source3/libsmb/clilist.c >+++ b/source3/libsmb/clilist.c >@@ -19,6 +19,8 @@ > > #include "includes.h" > #include "libsmb/libsmb.h" >+#include "libsmb/smb2cli.h" >+#include "libsmb/smb2cli_fnum.h" > #include "../lib/util/tevent_ntstatus.h" > #include "async_smb.h" > #include "trans2.h" >@@ -933,7 +935,7 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute, > NTSTATUS (*fn)(const char *, struct file_info *, const char *, > void *), void *state) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; >@@ -941,6 +943,12 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute, > size_t i, num_finfo; > uint16_t info_level; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_list(cli, mask, fn, state); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From 70fe6acfff4b98591bf879ad269832c74b8b016e Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:45:05 -0700 >Subject: [PATCH 22/37] Plumb smb2cli_qpathinfo2() inside cli_qpathinfo2(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clirap.c | 18 +++++++++++++++++- > 1 file changed, 17 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 12a340c..06e3258 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -26,6 +26,8 @@ > #include "../lib/util/tevent_ntstatus.h" > #include "async_smb.h" > #include "libsmb/libsmb.h" >+#include "libsmb/smb2cli.h" >+#include "libsmb/smb2cli_fnum.h" > #include "libsmb/clirap.h" > #include "trans2.h" > #include "../libcli/smb/smbXcli_base.h" >@@ -845,11 +847,25 @@ NTSTATUS cli_qpathinfo2(struct cli_state *cli, const char *fname, > off_t *size, uint16 *mode, > SMB_INO_T *ino) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_qpathinfo2(cli, >+ fname, >+ create_time, >+ access_time, >+ write_time, >+ change_time, >+ size, >+ mode, >+ ino); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From ff5d714f5c094b6d8dd3cf0e94af7f9a58c6a6b1 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:46:05 -0700 >Subject: [PATCH 23/37] Plumb smb2cli_qpathinfo_streams() inside > cli_qpathinfo_streams(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clirap.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 06e3258..02b015a 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -967,11 +967,21 @@ NTSTATUS cli_qpathinfo_streams(struct cli_state *cli, const char *fname, > unsigned int *pnum_streams, > struct stream_struct **pstreams) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_qpathinfo_streams(cli, >+ fname, >+ mem_ctx, >+ pnum_streams, >+ pstreams); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From eb8e03420117a85d22cf379631649efeab7e014c Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:47:21 -0700 >Subject: [PATCH 24/37] Plumb smb2cli_qfileinfo_basic() inside > cli_qfileinfo_basic(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clirap.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 02b015a..d621dca 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -1151,6 +1151,18 @@ NTSTATUS cli_qfileinfo_basic(struct cli_state *cli, uint16_t fnum, > uint32_t num_rdata; > NTSTATUS status; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_qfileinfo_basic(cli, >+ fnum, >+ mode, >+ size, >+ create_time, >+ access_time, >+ write_time, >+ change_time, >+ ino); >+ } >+ > /* if its a win95 server then fail this - win95 totally screws it > up */ > if (cli->win95) { >-- >1.8.3 > > >From 799cf995e103b7911b170a0564914ed23b0b1821 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 10:52:02 -0700 >Subject: [PATCH 25/37] Plumb smb2cli_qpathinfo_basic() inside > cli_qpathinfo_basic(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clirap.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index d621dca..8fcedd8 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -1277,11 +1277,20 @@ NTSTATUS cli_qpathinfo_basic_recv(struct tevent_req *req, > NTSTATUS cli_qpathinfo_basic(struct cli_state *cli, const char *name, > SMB_STRUCT_STAT *sbuf, uint32 *attributes) > { >- TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *frame = NULL; > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_qpathinfo_basic(cli, >+ name, >+ sbuf, >+ attributes); >+ } >+ >+ frame = talloc_stackframe(); >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > /* > * Can't use sync call while an async call is in flight >-- >1.8.3 > > >From f65087103d1f06f200130ef7ca37d6e37e6d9f45 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:50:03 -0700 >Subject: [PATCH 26/37] Plumb smb2cli_qpathinfo_alt_name() inside > cli_qpathinfo_alt_name(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clirap.c | 6 ++++++ > 1 file changed, 6 insertions(+) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 8fcedd8..f1255ef 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -1328,6 +1328,12 @@ NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstrin > size_t converted_size = 0; > NTSTATUS status; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_qpathinfo_alt_name(cli, >+ fname, >+ alt_name); >+ } >+ > status = cli_qpathinfo(talloc_tos(), cli, fname, > SMB_QUERY_FILE_ALT_NAME_INFO, > 4, CLI_BUFFER_SIZE, &rdata, &num_rdata); >-- >1.8.3 > > >From 9d76847e697a43bdb2e2bd67fb4640c7685bad6f Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:00:08 -0700 >Subject: [PATCH 27/37] Plumb smb2cli_query_security_descriptor() inside > cli_query_security_descriptor(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clisecdesc.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > >diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c >index 24da39d..14834cd 100644 >--- a/source3/libsmb/clisecdesc.c >+++ b/source3/libsmb/clisecdesc.c >@@ -19,7 +19,10 @@ > > #include "includes.h" > #include "libsmb/libsmb.h" >+#include "libsmb/smb2cli.h" >+#include "libsmb/smb2cli_fnum.h" > #include "../libcli/security/secdesc.h" >+#include "../libcli/smb/smbXcli_base.h" > > NTSTATUS cli_query_security_descriptor(struct cli_state *cli, > uint16_t fnum, >@@ -33,6 +36,14 @@ NTSTATUS cli_query_security_descriptor(struct cli_state *cli, > NTSTATUS status; > struct security_descriptor *lsd; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_query_security_descriptor(cli, >+ fnum, >+ sec_info, >+ mem_ctx, >+ sd); >+ } >+ > SIVAL(param, 0, fnum); > SIVAL(param, 4, sec_info); > >-- >1.8.3 > > >From 15f1d6415f518b4a6eeb495ec88271db4a376bb5 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:00:49 -0700 >Subject: [PATCH 28/37] Plumb smb2cli_set_security_descriptor() inside > cli_set_security_descriptor(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clisecdesc.c | 7 +++++++ > 1 file changed, 7 insertions(+) > >diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c >index 14834cd..e46928e 100644 >--- a/source3/libsmb/clisecdesc.c >+++ b/source3/libsmb/clisecdesc.c >@@ -106,6 +106,13 @@ NTSTATUS cli_set_security_descriptor(struct cli_state *cli, > size_t len; > NTSTATUS status; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_set_security_descriptor(cli, >+ fnum, >+ sec_info, >+ sd); >+ } >+ > status = marshall_sec_desc(talloc_tos(), sd, &data, &len); > if (!NT_STATUS_IS_OK(status)) { > DEBUG(10, ("marshall_sec_desc failed: %s\n", >-- >1.8.3 > > >From 2e78411833ee349a7b5dd56a5794ed54122e77a6 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:16:58 -0700 >Subject: [PATCH 29/37] Add an SMB2 version of the underlying engine behind > async cli_pull. > >Adds smb2cli_readall_fnum_send() and smb2cli_readall_fnum_recv(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clireadwrite.c | 45 ++++++++++++++++++++++++++++++++----------- > 1 file changed, 34 insertions(+), 11 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index 47e7f1b..d947b01 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -19,6 +19,8 @@ > > #include "includes.h" > #include "libsmb/libsmb.h" >+#include "libsmb/smb2cli.h" >+#include "libsmb/smb2cli_fnum.h" > #include "../lib/util/tevent_ntstatus.h" > #include "async_smb.h" > #include "trans2.h" >@@ -533,10 +535,17 @@ struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, > size_left = size - state->requested; > request_thistime = MIN(size_left, state->chunk_size); > >- subreq->req = cli_readall_send( >- state->reqs, ev, cli, fnum, >- state->start_offset + state->requested, >- request_thistime); >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ subreq->req = smb2cli_readall_fnum_send( >+ state->reqs, ev, cli, fnum, >+ state->start_offset + state->requested, >+ request_thistime); >+ } else { >+ subreq->req = cli_readall_send( >+ state->reqs, ev, cli, fnum, >+ state->start_offset + state->requested, >+ request_thistime); >+ } > > if (subreq->req == NULL) { > goto failed; >@@ -578,8 +587,14 @@ static void cli_pull_read_done(struct tevent_req *subreq) > return; > } > >- status = cli_readall_recv(subreq, &pull_subreq->received, >- &pull_subreq->buf); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ status = smb2cli_readall_fnum_recv(subreq, &pull_subreq->received, >+ &pull_subreq->buf); >+ } else { >+ status = cli_readall_recv(subreq, &pull_subreq->received, >+ &pull_subreq->buf); >+ } >+ > if (!NT_STATUS_IS_OK(status)) { > tevent_req_nterror(state->req, status); > return; >@@ -636,11 +651,19 @@ static void cli_pull_read_done(struct tevent_req *subreq) > + state->requested), > state->top_req)); > >- new_req = cli_readall_send( >- state->reqs, state->ev, state->cli, >- state->fnum, >- state->start_offset + state->requested, >- request_thistime); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ new_req = smb2cli_readall_fnum_send( >+ state->reqs, state->ev, state->cli, >+ state->fnum, >+ state->start_offset + state->requested, >+ request_thistime); >+ } else { >+ new_req = cli_readall_send( >+ state->reqs, state->ev, state->cli, >+ state->fnum, >+ state->start_offset + state->requested, >+ request_thistime); >+ } > > if (tevent_req_nomem(new_req, state->req)) { > return; >-- >1.8.3 > > >From 9887f8d6a62ad976790cd32e237af062e4c600dc Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:22:56 -0700 >Subject: [PATCH 30/37] Add an SMB2 version of the underlying engine behind > async cli_push. > >Adds smb2cli_writeall_send() and smb2cli_writeall_recv(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clireadwrite.c | 31 +++++++++++++++++++++++++++---- > 1 file changed, 27 insertions(+), 4 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index d947b01..ab86301 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -1101,7 +1101,11 @@ NTSTATUS cli_writeall(struct cli_state *cli, uint16_t fnum, uint16_t mode, > if (ev == NULL) { > goto fail; > } >- req = cli_writeall_send(frame, ev, cli, fnum, mode, buf, offset, size); >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ req = smb2cli_writeall_send(frame, ev, cli, fnum, mode, buf, offset, size); >+ } else { >+ req = cli_writeall_send(frame, ev, cli, fnum, mode, buf, offset, size); >+ } > if (req == NULL) { > goto fail; > } >@@ -1109,7 +1113,11 @@ NTSTATUS cli_writeall(struct cli_state *cli, uint16_t fnum, uint16_t mode, > status = map_nt_error_from_unix(errno); > goto fail; > } >- status = cli_writeall_recv(req, pwritten); >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ status = smb2cli_writeall_recv(req, pwritten); >+ } else { >+ status = cli_writeall_recv(req, pwritten); >+ } > fail: > TALLOC_FREE(frame); > return status; >@@ -1179,12 +1187,23 @@ static bool cli_push_write_setup(struct tevent_req *req, > return true; > } > >- subreq = cli_writeall_send(substate, >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ subreq = smb2cli_writeall_send(substate, >+ state->ev, >+ state->cli, >+ state->fnum, >+ state->mode, >+ substate->buf, >+ substate->ofs, >+ substate->size); >+ } else { >+ subreq = cli_writeall_send(substate, > state->ev, state->cli, > state->fnum, state->mode, > substate->buf, > substate->ofs, > substate->size); >+ } > if (!subreq) { > talloc_free(substate); > return false; >@@ -1284,7 +1303,11 @@ static void cli_push_written(struct tevent_req *subreq) > state->reqs[idx] = NULL; > state->pending -= 1; > >- status = cli_writeall_recv(subreq, NULL); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ status = smb2cli_writeall_recv(subreq, NULL); >+ } else { >+ status = cli_writeall_recv(subreq, NULL); >+ } > TALLOC_FREE(subreq); > TALLOC_FREE(substate); > if (tevent_req_nterror(req, status)) { >-- >1.8.3 > > >From d62bedbc62243cff88b1f5f8c33b1f9ad9869288 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:35:44 -0700 >Subject: [PATCH 31/37] Modify cli_start_connection_connected() to use > lp_cli_minprotocol()/lp_cli_maxprotocol() instead of hard coding > PROTOCOL_CORE, PROTOCOL_NT1. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/cliconnect.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index 7179c4f..fa9d99f 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -3123,7 +3123,8 @@ static void cli_start_connection_connected(struct tevent_req *subreq) > > subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn, > state->cli->timeout, >- PROTOCOL_CORE, PROTOCOL_NT1); >+ lp_cli_minprotocol(), >+ lp_cli_maxprotocol()); > if (tevent_req_nomem(subreq, req)) { > return; > } >-- >1.8.3 > > >From 64ebe855274eb2cecfa6499c5dce82858f2a822d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:43:16 -0700 >Subject: [PATCH 32/37] Add -m<MAX PROTOCOL> option to smbcacls. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/utils/smbcacls.c | 4 ++++ > 1 file changed, 4 insertions(+) > >diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c >index d3d60bc..4423d35 100644 >--- a/source3/utils/smbcacls.c >+++ b/source3/utils/smbcacls.c >@@ -1385,6 +1385,7 @@ static struct cli_state *connect_one(struct user_auth_info *auth_info, > }, > { "test-args", 't', POPT_ARG_NONE, &test_args, 1, "Test arguments"}, > { "domain-sid", 0, POPT_ARG_STRING, &domain_sid, 0, "Domain SID for sddl", "SID"}, >+ { "max-protocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set the max protocol level", "LEVEL" }, > POPT_COMMON_SAMBA > POPT_COMMON_CONNECTION > POPT_COMMON_CREDENTIALS >@@ -1455,6 +1456,9 @@ static struct cli_state *connect_one(struct user_auth_info *auth_info, > owner_username = poptGetOptArg(pc); > change_mode = REQUEST_INHERIT; > break; >+ case 'm': >+ lp_set_cli_maxprotocol(interpret_protocol(poptGetOptArg(pc), PROTOCOL_NT1)); >+ break; > } > } > >-- >1.8.3 > > >From 89e8d12622f0cbbb87710464c96132fdc01f00be Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 9 Aug 2013 09:04:44 -0700 >Subject: [PATCH 33/37] Fix smb2cli_req_create() to set the credit charge > correctly on large-MTU read requests. > >If we don't do this right, W2K12 returns INVALID_PARAMETER on SMB2_READ. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > libcli/smb/smbXcli_base.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index 5a5828a..98851bc 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -2639,6 +2639,18 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx, > */ > SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX); > break; >+ case SMB2_OP_READ: >+ /* >+ * For reads we set the credit charge >+ * based on what we asked for, not what >+ * we send. If we don't set this correctly >+ * W2K12 responds with INVALID_PARAMETER for >+ * a large MTU read. >+ */ >+ if (conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) { >+ uint32_t len = IVAL(fixed, 4); >+ state->smb2.credit_charge = (MAX(len, 1) - 1)/ 65536 + 1; >+ } > } > > if (timeout_msec > 0) { >-- >1.8.3 > > >From a66457b4d758911a3c6e19a2e098e97b04a8fce3 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 9 Aug 2013 09:06:34 -0700 >Subject: [PATCH 34/37] Add utility function smb2cli_conn_available_credits() > returns current available credits. > >Needed to calculate max buffer size for an MTU SMB2_READ. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > libcli/smb/smbXcli_base.c | 5 +++++ > libcli/smb/smbXcli_base.h | 1 + > 2 files changed, 6 insertions(+) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index 98851bc..f81841b 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -2461,6 +2461,11 @@ void smb2cli_conn_set_max_credits(struct smbXcli_conn *conn, > conn->smb2.max_credits = max_credits; > } > >+uint16_t smb2cli_conn_available_credits(struct smbXcli_conn *conn) >+{ >+ return conn->smb2.cur_credits; >+} >+ > static void smb2cli_req_cancel_done(struct tevent_req *subreq); > > static bool smb2cli_req_cancel(struct tevent_req *req) >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index a497e13..96f4d9f 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -205,6 +205,7 @@ uint32_t smb2cli_conn_max_read_size(struct smbXcli_conn *conn); > uint32_t smb2cli_conn_max_write_size(struct smbXcli_conn *conn); > void smb2cli_conn_set_max_credits(struct smbXcli_conn *conn, > uint16_t max_credits); >+uint16_t smb2cli_conn_available_credits(struct smbXcli_conn *conn); > > struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >-- >1.8.3 > > >From 4b2f3a6614297435626c45c870b400b2c18a4efb Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 9 Aug 2013 10:36:57 -0700 >Subject: [PATCH 35/37] Fix cli_read_max_bufsize() to cope with available > credits in the large MTU case. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/clireadwrite.c | 13 +++++++++++++ > 1 file changed, 13 insertions(+) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index ab86301..bc893ea 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -36,6 +36,19 @@ static size_t cli_read_max_bufsize(struct cli_state *cli) > uint32_t data_offset; > uint32_t useable_space = 0; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ if (smb2cli_conn_server_capabilities(cli->conn) & SMB2_CAP_LARGE_MTU) { >+ size_t bufsize = smb2cli_conn_max_read_size(cli->conn); >+ uint16_t cur_credits = smb2cli_conn_available_credits(cli->conn); >+ /* >+ * Modify to fit within the available credits. >+ */ >+ return MIN(bufsize, (cur_credits * 65536)); >+ } else { >+ return 65536; >+ } >+ } >+ > data_offset = HDR_VWV; > data_offset += wct * sizeof(uint16_t); > data_offset += sizeof(uint16_t); /* byte count */ >-- >1.8.3 > > >From a354ae1c395b2e32fd7e487c4c59dbcd1102be2e Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 9 Aug 2013 11:15:48 -0700 >Subject: [PATCH 36/37] Ensure we ask for lp_smb2_max_credits() on successful > negprot. Should this be a separate client parameter ? > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/libsmb/cliconnect.c | 6 ++++++ > source3/libsmb/clidfs.c | 6 ++++++ > 2 files changed, 12 insertions(+) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index fa9d99f..0afb5e4 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -3156,6 +3156,12 @@ static NTSTATUS cli_start_connection_recv(struct tevent_req *req, > return status; > } > *output_cli = state->cli; >+ >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ /* Ensure we ask for some initial credits. */ >+ smb2cli_conn_set_max_credits(state->cli->conn, >+ lp_smb2_max_credits()); >+ } > return NT_STATUS_OK; > } > >diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c >index 95f8817..3a30dda 100644 >--- a/source3/libsmb/clidfs.c >+++ b/source3/libsmb/clidfs.c >@@ -160,6 +160,12 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, > return status; > } > >+ if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) { >+ /* Ensure we ask for some initial credits. */ >+ smb2cli_conn_set_max_credits(c->conn, >+ lp_smb2_max_credits()); >+ } >+ > username = get_cmdline_auth_info_username(auth_info); > password = get_cmdline_auth_info_password(auth_info); > >-- >1.8.3 > > >From 067accf75bfe0e1ce4b07a2827adf7ee3a8caa7b Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 9 Aug 2013 13:03:57 -0700 >Subject: [PATCH 37/37] Correctly size smbXcli_conn_max_requests() based off > the available credits and the server max iosize. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > libcli/smb/smbXcli_base.c | 20 ++++++++++++++++---- > 1 file changed, 16 insertions(+), 4 deletions(-) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index f81841b..004ddaa 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -447,10 +447,22 @@ const char *smbXcli_conn_remote_name(struct smbXcli_conn *conn) > uint16_t smbXcli_conn_max_requests(struct smbXcli_conn *conn) > { > if (conn->protocol >= PROTOCOL_SMB2_02) { >- /* >- * TODO... >- */ >- return 1; >+ uint16_t avail_creds = smb2cli_conn_available_credits(conn); >+ if (conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) { >+ /* >+ * Each available credit is 65536 bytes. Take >+ * the larger of the max_read_size and max_write >+ * size and work out how many we can issue given >+ * the available credits. >+ */ >+ uint32_t max_size = MAX(conn->smb2.server.max_read_size, >+ conn->smb2.server.max_write_size); >+ >+ /* Convert max_size into credit units. */ >+ max_size = ((max_size - 1)/65536) + 1; >+ avail_creds = avail_creds / max_size; >+ } >+ return MAX(avail_creds, 1); > } > > return conn->smb1.server.max_mux; >-- >1.8.3 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 9974
:
9014
|
9123
|
9135
|
9136
|
9139
|
9148
|
9159