The Samba-Bugzilla – Attachment 9136 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]
Patches for v4-1-test
tmp41.diff (text/plain), 204.24 KB, created by
Stefan Metzmacher
on 2013-08-15 10:32:30 UTC
(
hide
)
Description:
Patches for v4-1-test
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2013-08-15 10:32:30 UTC
Size:
204.24 KB
patch
obsolete
>From 71c9021747cf111d55b1b919c65397f75e81e1f6 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:17:01 -0700 >Subject: [PATCH 01/57] s3:param: Correctly set up cli_maxprotocol, > cli_minprotocol in our parameter block. > >Set to PROTOCOL_NT1, PROTOCOL_CORE by default. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=9829 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f2fb829cee81996c62ff91cb8d1e9997008ffb42) >--- > source3/include/proto.h | 2 ++ > source3/param/loadparm.c | 2 ++ > 2 files changed, 4 insertions(+) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index a9270fc..e3d2006 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); >diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c >index fa2f9b6..229ebd8 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; >-- >1.7.9.5 > > >From f192428849e67a71b4d2c76d101b54fff5cdb49a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 13:08:49 +0200 >Subject: [PATCH 02/57] s3:client: avoid interpret_protocol() > >lp_set_cmdline("client max protocol",...) and >lp_cli_maxprotocol() are the more generic solution. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 861ee9319f3cce8f104fd30c7139323ac3d3319d) >--- > source3/client/client.c | 6 ++++-- > 1 file changed, 4 insertions(+), 2 deletions(-) > >diff --git a/source3/client/client.c b/source3/client/client.c >index d03d1a4..d09d012 100644 >--- a/source3/client/client.c >+++ b/source3/client/client.c >@@ -58,7 +58,7 @@ const char *cmd_ptr = NULL; > static int io_bufsize = 524288; > > static int name_type = 0x20; >-static int max_protocol = PROTOCOL_NT1; >+static int max_protocol = -1; > > static int process_tok(char *tok); > static int cmd_help(void); >@@ -5456,7 +5456,7 @@ static int do_message_op(struct user_auth_info *a_info) > } > break; > case 'm': >- max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol); >+ lp_set_cmdline("client max protocol", poptGetOptArg(pc)); > break; > case 'T': > /* We must use old option processing for this. Find the >@@ -5574,6 +5574,8 @@ static int do_message_op(struct user_auth_info *a_info) > /* Ensure we have a password (or equivalent). */ > set_cmdline_auth_info_getpass(auth_info); > >+ max_protocol = lp_cli_maxprotocol(); >+ > if (tar_type) { > if (cmdstr) > process_command_string(cmdstr); >-- >1.7.9.5 > > >From 75c3c045a1658d105fcca5eff77125b5d5eaf3e6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 13:10:13 +0200 >Subject: [PATCH 03/57] s3:torture: avoid interpret_protocol() > >lp_set_cmdline("client max protocol",...) and >lp_cli_maxprotocol() are the more generic solution. > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 2c3c8caa0cc7b085231b2edc100ce2332e1e0085) >--- > source3/torture/masktest.c | 5 +++-- > source3/torture/torture.c | 3 +-- > 2 files changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source3/torture/masktest.c b/source3/torture/masktest.c >index 8332e80..bca35aa 100644 >--- a/source3/torture/masktest.c >+++ b/source3/torture/masktest.c >@@ -27,7 +27,7 @@ > static fstring password; > static fstring username; > static int got_pass; >-static int max_protocol = PROTOCOL_NT1; >+static int max_protocol = -1; > static bool showall = False; > static bool old_list = False; > static const char *maskchars = "<>\"?*abc."; >@@ -510,7 +510,7 @@ static void usage(void) > verbose++; > break; > case 'M': >- max_protocol = interpret_protocol(optarg, max_protocol); >+ lp_set_cmdline("client max protocol", optarg); > break; > case 'U': > fstrcpy(username,optarg); >@@ -548,6 +548,7 @@ static void usage(void) > argc -= optind; > argv += optind; > >+ max_protocol = lp_cli_maxprotocol(); > > cli = connect_one(share); > if (!cli) { >diff --git a/source3/torture/torture.c b/source3/torture/torture.c >index 3c6db30..c6c5322 100644 >--- a/source3/torture/torture.c >+++ b/source3/torture/torture.c >@@ -46,7 +46,6 @@ extern char *optarg; > extern int optind; > > fstring host, workgroup, share, password, username, myname; >-static int max_protocol = PROTOCOL_NT1; > static const char *sockops="TCP_NODELAY"; > int torture_nprocs=1; > static int port_to_use=0; >@@ -9713,7 +9712,7 @@ static void usage(void) > fstrcpy(workgroup,optarg); > break; > case 'm': >- max_protocol = interpret_protocol(optarg, max_protocol); >+ lp_set_cmdline("client max protocol", optarg); > break; > case 'N': > torture_nprocs = atoi(optarg); >-- >1.7.9.5 > > >From ceb1d91a273e820c6657556d6323e98d8f101451 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 13:11:41 +0200 >Subject: [PATCH 04/57] s3:lib: remove unused interpret_protocol() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 9188ee4ab195a18b1bd697bced8613f98a6a91d9) >--- > source3/include/proto.h | 1 - > source3/lib/util.c | 25 ------------------------- > 2 files changed, 26 deletions(-) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index e3d2006..493d1da 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -401,7 +401,6 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, > ssize_t *array_size); > char *get_myname(TALLOC_CTX *ctx); > char *get_mydnsdomname(TALLOC_CTX *ctx); >-int interpret_protocol(const char *str,int def); > char *automount_lookup(TALLOC_CTX *ctx, const char *user_name); > char *automount_lookup(TALLOC_CTX *ctx, const char *user_name); > bool process_exists(const struct server_id pid); >diff --git a/source3/lib/util.c b/source3/lib/util.c >index 93aab3c..bf6c8c5 100644 >--- a/source3/lib/util.c >+++ b/source3/lib/util.c >@@ -559,31 +559,6 @@ char *get_mydnsdomname(TALLOC_CTX *ctx) > } > } > >-/**************************************************************************** >- Interpret a protocol description string, with a default. >-****************************************************************************/ >- >-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); >-} >- >- > #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT)) > /****************************************************************** > Remove any mount options such as -rsize=2048,wsize=2048 etc. >-- >1.7.9.5 > > >From 8d233fcb63cad58e368933b6f90a87383ee842b2 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:35:44 -0700 >Subject: [PATCH 05/57] s3:libsmb: Modify cli_start_connection_connected() to > use lp_cli_minprotocol()/lp_cli_maxprotocol() instead > of hard coding PROTOCOL_CORE, PROTOCOL_NT1. > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 42f510c155b98f3df5106aebd1de54d1749b9b1c) >--- > 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.7.9.5 > > >From 87d8832eabac562d748f5a1b44de9fbe5fd6f059 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 9 Aug 2013 11:15:48 -0700 >Subject: [PATCH 06/57] s3:libsmb: Ensure we ask for DEFAULT_SMB2_MAX_CREDITS > on successful negprot. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 14421323d1dd3744cb8553f0e6a5a7436554bf2d) >--- > source3/libsmb/cliconnect.c | 10 ++++++++++ > source3/libsmb/clidfs.c | 5 +++++ > 2 files changed, 15 insertions(+) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index fa9d99f..d74ea0e 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -3135,6 +3135,8 @@ static void cli_start_connection_done(struct tevent_req *subreq) > { > struct tevent_req *req = tevent_req_callback_data( > subreq, struct tevent_req); >+ struct cli_start_connection_state *state = tevent_req_data( >+ req, struct cli_start_connection_state); > NTSTATUS status; > > status = smbXcli_negprot_recv(subreq); >@@ -3142,6 +3144,13 @@ static void cli_start_connection_done(struct tevent_req *subreq) > if (tevent_req_nterror(req, status)) { > return; > } >+ >+ 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, >+ DEFAULT_SMB2_MAX_CREDITS); >+ } >+ > tevent_req_done(req); > } > >@@ -3156,6 +3165,7 @@ static NTSTATUS cli_start_connection_recv(struct tevent_req *req, > return status; > } > *output_cli = state->cli; >+ > return NT_STATUS_OK; > } > >diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c >index 95f8817..1ed6ac5 100644 >--- a/source3/libsmb/clidfs.c >+++ b/source3/libsmb/clidfs.c >@@ -160,6 +160,11 @@ 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, DEFAULT_SMB2_MAX_CREDITS); >+ } >+ > username = get_cmdline_auth_info_username(auth_info); > password = get_cmdline_auth_info_password(auth_info); > >-- >1.7.9.5 > > >From f43056ba600325786b7a8b0d51a2a65d6b1bd766 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 13:46:34 +0200 >Subject: [PATCH 07/57] s3:lib/netapi: make use of lp_cli_maxprotocol() > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 7e455e9ed2b298df6b735a89abdd75564375ef34) >--- > source3/lib/netapi/cm.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c >index 36e8731..da3d2e1 100644 >--- a/source3/lib/netapi/cm.c >+++ b/source3/lib/netapi/cm.c >@@ -111,7 +111,7 @@ static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx, > server_name, "IPC$", > auth_info, > false, false, >- PROTOCOL_NT1, >+ lp_cli_maxprotocol(), > 0, 0x20, &cli_ipc); > if (NT_STATUS_IS_OK(status)) { > cli_set_username(cli_ipc, ctx->username); >-- >1.7.9.5 > > >From 355fdb2c83d041cabc29873bee3001db43c0aae6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 13:48:31 +0200 >Subject: [PATCH 08/57] s3:winbindd: make use of lp_cli_{min,max}protocol() > >This changes winbindd back to use NT1 as defeault. > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit dd9155a7ec7f1989cb18e79907d0fa1c9ee845a4) >--- > source3/winbindd/winbindd_cm.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > >diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c >index 48322cb..85139d0 100644 >--- a/source3/winbindd/winbindd_cm.c >+++ b/source3/winbindd/winbindd_cm.c >@@ -841,8 +841,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, > > cli_set_timeout(*cli, 10000); /* 10 seconds */ > >- result = smbXcli_negprot((*cli)->conn, (*cli)->timeout, PROTOCOL_CORE, >- PROTOCOL_LATEST); >+ result = smbXcli_negprot((*cli)->conn, (*cli)->timeout, >+ lp_cli_minprotocol(), >+ lp_cli_maxprotocol()); > > if (!NT_STATUS_IS_OK(result)) { > DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result))); >-- >1.7.9.5 > > >From 364809db913fc7da3b19794153d3c2797788c210 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 14:00:45 +0200 >Subject: [PATCH 09/57] s3:libsmb: use lp_cli_minprotocol() in do_connect() > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 42a493dff0e4ade04b6e94caf0b7ae14b6cf60eb) >--- > source3/libsmb/clidfs.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c >index 1ed6ac5..1d92843 100644 >--- a/source3/libsmb/clidfs.c >+++ b/source3/libsmb/clidfs.c >@@ -150,7 +150,8 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, > } > DEBUG(4,(" session request ok\n")); > >- status = smbXcli_negprot(c->conn, c->timeout, PROTOCOL_CORE, >+ status = smbXcli_negprot(c->conn, c->timeout, >+ lp_cli_minprotocol(), > max_protocol); > > if (!NT_STATUS_IS_OK(status)) { >-- >1.7.9.5 > > >From 3dbf95925cb561f5c794cfd733f9dfd6a1710bae Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sun, 11 Aug 2013 14:01:36 +0200 >Subject: [PATCH 10/57] s3:libsmb: make use of lp_cli_{min,max}protocol() in > SMBC_server_internal() > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit daeb0bdfc49ace6151bbca34cbbf55486d66abb6) >--- > source3/libsmb/libsmb_server.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > >diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c >index fc3977e..7a20c30 100644 >--- a/source3/libsmb/libsmb_server.c >+++ b/source3/libsmb/libsmb_server.c >@@ -449,9 +449,9 @@ SMBC_server_internal(TALLOC_CTX *ctx, > > cli_set_timeout(c, smbc_getTimeout(context)); > >- status = smbXcli_negprot(c->conn, c->timeout, PROTOCOL_CORE, >- PROTOCOL_NT1); >- >+ status = smbXcli_negprot(c->conn, c->timeout, >+ lp_cli_minprotocol(), >+ lp_cli_maxprotocol()); > if (!NT_STATUS_IS_OK(status)) { > cli_shutdown(c); > errno = ETIMEDOUT; >-- >1.7.9.5 > > >From da5c0d40de6bfb26f3dfbce3d7d5011bd676b6b2 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:43:16 -0700 >Subject: [PATCH 11/57] s3:smbcacls: Add -m<MAX PROTOCOL> option to smbcacls. > >https://bugzilla.samba.org/show_bug.cgi?id=9514 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f6ce50a8aca9eb024af4eb5e3dd620fe5e04e913) >--- > source3/utils/smbcacls.c | 4 ++++ > 1 file changed, 4 insertions(+) > >diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c >index 39400c8..3ee7034 100644 >--- a/source3/utils/smbcacls.c >+++ b/source3/utils/smbcacls.c >@@ -1386,6 +1386,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 >@@ -1456,6 +1457,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_cmdline("client max protocol", poptGetOptArg(pc)); >+ break; > } > } > >-- >1.7.9.5 > > >From ba687032e530ecc55a845f12faa2b6bfe6a5a4c2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 08:12:08 +0200 >Subject: [PATCH 12/57] libcli/smb: fix the credit handling on a SMB1 => SMB2 > negotiate > >Our cur_credit value had 1 credit too many in the case of >an SMB1 => SMB2 upgrade. When we max out the credits the server >disconnected the connection. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 97288b7f1048c1bf712463293a1e62737738292c) >--- > libcli/smb/smbXcli_base.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index 5a5828a..b950900 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -4404,9 +4404,14 @@ static NTSTATUS smbXcli_negprot_dispatch_incoming(struct smbXcli_conn *conn, > > /* > * we got an SMB2 answer, which consumed sequence number 0 >- * so we need to use 1 as the next one >+ * so we need to use 1 as the next one. >+ * >+ * we also need to set the current credits to 0 >+ * as we consumed the initial one. The SMB2 answer >+ * hopefully grant us a new credit. > */ > conn->smb2.mid = 1; >+ conn->smb2.cur_credits = 0; > tevent_req_set_callback(subreq, smbXcli_negprot_smb2_done, req); > conn->dispatch_incoming = smb2cli_conn_dispatch_incoming; > return smb2cli_conn_dispatch_incoming(conn, tmp_mem, inbuf); >-- >1.7.9.5 > > >From dfd3b4d836f692b5e9906f5c5f7dfa495090a4dd Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 14:41:24 -0700 >Subject: [PATCH 13/57] libcli/smb: Fix smb2cli_write_recv() and > smb2cli_write() to return the bytes written. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 00f784ec91d2cfa95b20327ac20f5bc3fa1f400e) >--- > libcli/smb/smb2cli_write.c | 30 +++++++++++++++++++++++++----- > libcli/smb/smbXcli_base.h | 6 ++++-- > source3/libsmb/cli_np_tstream.c | 7 +++++-- > source3/torture/test_smb2.c | 14 +++++++------- > 4 files changed, 41 insertions(+), 16 deletions(-) > >diff --git a/libcli/smb/smb2cli_write.c b/libcli/smb/smb2cli_write.c >index 8e65460..89137bd 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,32 @@ 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)) { >+ tevent_req_received(req); >+ return status; >+ } >+ if (written) { >+ *written = state->written; >+ } >+ tevent_req_received(req); >+ return NT_STATUS_OK; > } > > NTSTATUS smb2cli_write(struct smbXcli_conn *conn, >@@ -126,7 +145,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 +175,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.7.9.5 > > >From 002cbda4cfdb912d819a1a3f052df124df34e0af Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:01:50 -0700 >Subject: [PATCH 14/57] libcli/smb: 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> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 1229881df6bd22d4b5055ad283061332ba1c9bc8) >--- > 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.7.9.5 > > >From 00346dc14e5ade6c25e01ea31d7c811dc7ba0abf Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 09:50:29 +0200 >Subject: [PATCH 15/57] libcli/smb: calculate the credit charge on the input > and output dyn_len > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 318735fd5e15c5fd7010c0f657c86d27b45279ac) >--- > libcli/smb/smbXcli_base.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index b950900..ef9d82a 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -246,6 +246,11 @@ struct smbXcli_req_state { > */ > struct iovec *recv_iov; > >+ /* >+ * the expected max for the response dyn_len >+ */ >+ uint32_t max_dyn_len; >+ > uint16_t credit_charge; > > bool should_sign; >@@ -2787,7 +2792,12 @@ NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs, > } > > if (state->conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) { >- charge = (MAX(state->smb2.dyn_len, 1) - 1)/ 65536 + 1; >+ uint32_t max_dyn_len = 1; >+ >+ max_dyn_len = MAX(max_dyn_len, state->smb2.dyn_len); >+ max_dyn_len = MAX(max_dyn_len, state->smb2.max_dyn_len); >+ >+ charge = (max_dyn_len - 1)/ 65536 + 1; > } else { > charge = 1; > } >-- >1.7.9.5 > > >From d8a1d009fa7dbe7e1d3b12a17c3542c16c9a673d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 09:54:42 +0200 >Subject: [PATCH 16/57] libcli/smb: pass max_dyn_len to smb2cli_req_create() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 4a3352020db962ef40728d8a754da8a9418ca8a7) >--- > libcli/smb/smbXcli_base.c | 11 ++++++++--- > libcli/smb/smbXcli_base.h | 3 ++- > 2 files changed, 10 insertions(+), 4 deletions(-) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index ef9d82a..60c1c9f 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -2494,7 +2494,7 @@ static bool smb2cli_req_cancel(struct tevent_req *req) > 0, /* timeout */ > tcon, session, > fixed, fixed_len, >- NULL, 0); >+ NULL, 0, 0); > if (subreq == NULL) { > return false; > } >@@ -2543,7 +2543,8 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx, > const uint8_t *fixed, > uint16_t fixed_len, > const uint8_t *dyn, >- uint32_t dyn_len) >+ uint32_t dyn_len, >+ uint32_t max_dyn_len) > { > struct tevent_req *req; > struct smbXcli_req_state *state; >@@ -2616,6 +2617,7 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx, > state->smb2.fixed_len = fixed_len; > state->smb2.dyn = dyn; > state->smb2.dyn_len = dyn_len; >+ state->smb2.max_dyn_len = max_dyn_len; > > if (state->smb2.should_encrypt) { > SIVAL(state->smb2.transform, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC); >@@ -2985,12 +2987,15 @@ struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx, > { > struct tevent_req *req; > NTSTATUS status; >+ uint32_t max_dyn_len = 0; > > req = smb2cli_req_create(mem_ctx, ev, conn, cmd, > additional_flags, clear_flags, > timeout_msec, > tcon, session, >- fixed, fixed_len, dyn, dyn_len); >+ fixed, fixed_len, >+ dyn, dyn_len, >+ max_dyn_len); > if (req == NULL) { > return NULL; > } >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index a497e13..017c0f0 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -218,7 +218,8 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx, > const uint8_t *fixed, > uint16_t fixed_len, > const uint8_t *dyn, >- uint32_t dyn_len); >+ uint32_t dyn_len, >+ uint32_t max_dyn_len); > void smb2cli_req_set_notify_async(struct tevent_req *req); > NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs, > int num_reqs); >-- >1.7.9.5 > > >From 78b6029c63cc31dcbcdb81226225f9ba1d56bd15 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 10:25:52 +0200 >Subject: [PATCH 17/57] libcli/smb: pass max_dyn_len to smb2cli_req_send() > >This way we can calculate the correct credit charge >for requests with large output buffers. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 44b53937d59842a63e2cbfa92219f4f519530b0a) >--- > libcli/smb/smb2cli_close.c | 3 ++- > libcli/smb/smb2cli_create.c | 13 ++++++++++++- > libcli/smb/smb2cli_echo.c | 3 ++- > libcli/smb/smb2cli_flush.c | 3 ++- > libcli/smb/smb2cli_ioctl.c | 13 ++++++++++++- > libcli/smb/smb2cli_query_directory.c | 3 ++- > libcli/smb/smb2cli_query_info.c | 3 ++- > libcli/smb/smb2cli_read.c | 3 ++- > libcli/smb/smb2cli_session.c | 6 ++++-- > libcli/smb/smb2cli_set_info.c | 3 ++- > libcli/smb/smb2cli_write.c | 3 ++- > libcli/smb/smbXcli_base.c | 7 ++++--- > libcli/smb/smbXcli_base.h | 3 ++- > source3/libsmb/smb2cli_tcon.c | 6 ++++-- > source4/libcli/smb2/transport.c | 9 ++++++--- > 15 files changed, 60 insertions(+), 21 deletions(-) > >diff --git a/libcli/smb/smb2cli_close.c b/libcli/smb/smb2cli_close.c >index ed15a20..5e31056 100644 >--- a/libcli/smb/smb2cli_close.c >+++ b/libcli/smb/smb2cli_close.c >@@ -60,7 +60,8 @@ struct tevent_req *smb2cli_close_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- NULL, 0); >+ NULL, 0, /* dyn* */ >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_create.c b/libcli/smb/smb2cli_create.c >index 020a468..3f8d672 100644 >--- a/libcli/smb/smb2cli_create.c >+++ b/libcli/smb/smb2cli_create.c >@@ -62,6 +62,7 @@ struct tevent_req *smb2cli_create_send( > size_t blobs_offset; > uint8_t *dyn; > size_t dyn_len; >+ size_t max_dyn_len; > > req = tevent_req_create(mem_ctx, &state, > struct smb2cli_create_state); >@@ -129,13 +130,23 @@ struct tevent_req *smb2cli_create_send( > data_blob_free(&blob); > } > >+ /* >+ * We use max_dyn_len = 0 >+ * as we don't explicitly ask for any output length. >+ * >+ * But it's still possible for the server to return >+ * large create blobs. >+ */ >+ max_dyn_len = 0; >+ > subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_CREATE, > 0, 0, /* flags */ > timeout_msec, > tcon, > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ max_dyn_len); > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_echo.c b/libcli/smb/smb2cli_echo.c >index 29cbf26..39c592c 100644 >--- a/libcli/smb/smb2cli_echo.c >+++ b/libcli/smb/smb2cli_echo.c >@@ -53,7 +53,8 @@ struct tevent_req *smb2cli_echo_send(TALLOC_CTX *mem_ctx, > NULL, /* tcon */ > NULL, /* session */ > state->fixed, sizeof(state->fixed), >- NULL, 0); >+ NULL, 0, /* dyn* */ >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_flush.c b/libcli/smb/smb2cli_flush.c >index 0ca2699..f014720 100644 >--- a/libcli/smb/smb2cli_flush.c >+++ b/libcli/smb/smb2cli_flush.c >@@ -58,7 +58,8 @@ struct tevent_req *smb2cli_flush_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- NULL, 0); >+ NULL, 0, /* dyn* */ >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_ioctl.c b/libcli/smb/smb2cli_ioctl.c >index 15a990c..8de7635 100644 >--- a/libcli/smb/smb2cli_ioctl.c >+++ b/libcli/smb/smb2cli_ioctl.c >@@ -61,6 +61,8 @@ struct tevent_req *smb2cli_ioctl_send(TALLOC_CTX *mem_ctx, > uint32_t output_buffer_offset = 0; > uint32_t output_buffer_length = 0; > uint32_t pad_length = 0; >+ uint64_t tmp64; >+ uint32_t max_dyn_len = 0; > > req = tevent_req_create(mem_ctx, &state, > struct smb2cli_ioctl_state); >@@ -70,6 +72,14 @@ struct tevent_req *smb2cli_ioctl_send(TALLOC_CTX *mem_ctx, > state->max_input_length = in_max_input_length; > state->max_output_length = in_max_output_length; > >+ tmp64 = in_max_input_length; >+ tmp64 += in_max_output_length; >+ if (tmp64 > UINT32_MAX) { >+ max_dyn_len = UINT32_MAX; >+ } else { >+ max_dyn_len = tmp64; >+ } >+ > if (in_input_buffer) { > input_buffer_offset = SMB2_HDR_BODY+0x38; > input_buffer_length = in_input_buffer->length; >@@ -139,7 +149,8 @@ struct tevent_req *smb2cli_ioctl_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ max_dyn_len); > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_query_directory.c b/libcli/smb/smb2cli_query_directory.c >index 32f5bee..bccc529 100644 >--- a/libcli/smb/smb2cli_query_directory.c >+++ b/libcli/smb/smb2cli_query_directory.c >@@ -93,7 +93,8 @@ struct tevent_req *smb2cli_query_directory_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ outbuf_len); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_query_info.c b/libcli/smb/smb2cli_query_info.c >index 9ec16b5..454f25a 100644 >--- a/libcli/smb/smb2cli_query_info.c >+++ b/libcli/smb/smb2cli_query_info.c >@@ -96,7 +96,8 @@ struct tevent_req *smb2cli_query_info_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ in_max_output_length); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_read.c b/libcli/smb/smb2cli_read.c >index 0adb403..4a31622 100644 >--- a/libcli/smb/smb2cli_read.c >+++ b/libcli/smb/smb2cli_read.c >@@ -72,7 +72,8 @@ struct tevent_req *smb2cli_read_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- state->dyn_pad, sizeof(state->dyn_pad)); >+ state->dyn_pad, sizeof(state->dyn_pad), >+ length); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_session.c b/libcli/smb/smb2cli_session.c >index 537c171..4418a0d 100644 >--- a/libcli/smb/smb2cli_session.c >+++ b/libcli/smb/smb2cli_session.c >@@ -102,7 +102,8 @@ struct tevent_req *smb2cli_session_setup_send(TALLOC_CTX *mem_ctx, > NULL, /* tcon */ > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ UINT16_MAX); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >@@ -258,7 +259,8 @@ struct tevent_req *smb2cli_logoff_send(TALLOC_CTX *mem_ctx, > NULL, /* tcon */ > session, > state->fixed, sizeof(state->fixed), >- NULL, 0); >+ NULL, 0, /* dyn* */ >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_set_info.c b/libcli/smb/smb2cli_set_info.c >index d5c7e58..6871370 100644 >--- a/libcli/smb/smb2cli_set_info.c >+++ b/libcli/smb/smb2cli_set_info.c >@@ -88,7 +88,8 @@ struct tevent_req *smb2cli_set_info_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smb2cli_write.c b/libcli/smb/smb2cli_write.c >index 89137bd..6d0a0aa 100644 >--- a/libcli/smb/smb2cli_write.c >+++ b/libcli/smb/smb2cli_write.c >@@ -82,7 +82,8 @@ struct tevent_req *smb2cli_write_send(TALLOC_CTX *mem_ctx, > tcon, > session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index 60c1c9f..f64852b 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -2983,11 +2983,11 @@ struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx, > const uint8_t *fixed, > uint16_t fixed_len, > const uint8_t *dyn, >- uint32_t dyn_len) >+ uint32_t dyn_len, >+ uint32_t max_dyn_len) > { > struct tevent_req *req; > NTSTATUS status; >- uint32_t max_dyn_len = 0; > > req = smb2cli_req_create(mem_ctx, ev, conn, cmd, > additional_flags, clear_flags, >@@ -4259,7 +4259,8 @@ static struct tevent_req *smbXcli_negprot_smb2_subreq(struct smbXcli_negprot_sta > state->timeout_msec, > NULL, NULL, /* tcon, session */ > state->smb2.fixed, sizeof(state->smb2.fixed), >- state->smb2.dyn, dialect_count*2); >+ state->smb2.dyn, dialect_count*2, >+ UINT16_MAX); /* max_dyn_len */ > } > > static void smbXcli_negprot_smb2_done(struct tevent_req *subreq) >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index 017c0f0..4ce39c0 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -242,7 +242,8 @@ struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx, > const uint8_t *fixed, > uint16_t fixed_len, > const uint8_t *dyn, >- uint32_t dyn_len); >+ uint32_t dyn_len, >+ uint32_t max_dyn_len); > NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, > struct iovec **piov, > const struct smb2cli_req_expected_response *expected, >diff --git a/source3/libsmb/smb2cli_tcon.c b/source3/libsmb/smb2cli_tcon.c >index ab97f8d..b3136fa 100644 >--- a/source3/libsmb/smb2cli_tcon.c >+++ b/source3/libsmb/smb2cli_tcon.c >@@ -85,7 +85,8 @@ struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx, > NULL, /* tcon */ > cli->smb2.session, > state->fixed, sizeof(state->fixed), >- dyn, dyn_len); >+ dyn, dyn_len, >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >@@ -211,7 +212,8 @@ struct tevent_req *smb2cli_tdis_send(TALLOC_CTX *mem_ctx, > cli->smb2.tcon, > cli->smb2.session, > state->fixed, sizeof(state->fixed), >- NULL, 0); >+ NULL, 0, /* dyn* */ >+ 0); /* max_dyn_len */ > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c >index bdab523..2ad16a9 100644 >--- a/source4/libcli/smb2/transport.c >+++ b/source4/libcli/smb2/transport.c >@@ -151,7 +151,8 @@ void smb2_transport_send(struct smb2_request *req) > NULL, /* body */ > 0, /* body_fixed */ > NULL, /* dyn */ >- 0); /* dyn_len */ >+ 0, /* dyn_len */ >+ 0); /* max_dyn_len */ > if (subreq != NULL) { > smbXcli_req_set_pending(subreq); > tevent_req_set_callback(subreq, >@@ -190,7 +191,8 @@ void smb2_transport_send(struct smb2_request *req) > tcon, > session, > body.data, body.length, >- dyn.data, dyn.length); >+ dyn.data, dyn.length, >+ 0); /* max_dyn_len */ > if (req->subreq == NULL) { > req->state = SMB2_REQUEST_ERROR; > req->status = NT_STATUS_NO_MEMORY; >@@ -347,7 +349,8 @@ static void smb2_transport_break_handler(struct tevent_req *subreq) > NULL, /* body */ > 0, /* body_fixed */ > NULL, /* dyn */ >- 0); /* dyn_len */ >+ 0, /* dyn_len */ >+ 0); /* max_dyn_len */ > if (subreq != NULL) { > smbXcli_req_set_pending(subreq); > tevent_req_set_callback(subreq, >-- >1.7.9.5 > > >From d0ed01a5cf3ebfbbc62aeeb0e16e97c5ead6442f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 14:05:05 +0200 >Subject: [PATCH 18/57] libcli/smb: add smb1cli_conn_req_possible() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 111f529a2a5832b822445bb4f63b142d8ccb2cb7) >--- > libcli/smb/smbXcli_base.c | 17 +++++++++++++++++ > libcli/smb/smbXcli_base.h | 1 + > 2 files changed, 18 insertions(+) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index f64852b..028f152 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -595,6 +595,23 @@ uint32_t smb1cli_conn_max_xmit(struct smbXcli_conn *conn) > return conn->smb1.max_xmit; > } > >+bool smb1cli_conn_req_possible(struct smbXcli_conn *conn) >+{ >+ size_t pending; >+ uint16_t possible = conn->smb1.server.max_mux; >+ >+ pending = tevent_queue_length(conn->outgoing); >+ if (pending >= possible) { >+ return false; >+ } >+ pending += talloc_array_length(conn->pending); >+ if (pending >= possible) { >+ return false; >+ } >+ >+ return true; >+} >+ > uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn) > { > return conn->smb1.server.session_key; >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index 4ce39c0..6b3156f 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -69,6 +69,7 @@ bool smbXcli_req_set_pending(struct tevent_req *req); > > uint32_t smb1cli_conn_capabilities(struct smbXcli_conn *conn); > uint32_t smb1cli_conn_max_xmit(struct smbXcli_conn *conn); >+bool smb1cli_conn_req_possible(struct smbXcli_conn *conn); > uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn); > const uint8_t *smb1cli_conn_server_challenge(struct smbXcli_conn *conn); > uint16_t smb1cli_conn_server_security_mode(struct smbXcli_conn *conn); >-- >1.7.9.5 > > >From b6e81741c37e0d9c0bdb6b27a561a71ca20ea1b7 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 15:49:19 +0200 >Subject: [PATCH 19/57] libcli/smb: add smb2cli_conn_req_possible() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 7efdc323d1a1abdae70bcafefe07b3cffcdb2521) >--- > libcli/smb/smbXcli_base.c | 22 ++++++++++++++++++++++ > libcli/smb/smbXcli_base.h | 1 + > 2 files changed, 23 insertions(+) > >diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c >index 028f152..b502f4f 100644 >--- a/libcli/smb/smbXcli_base.c >+++ b/libcli/smb/smbXcli_base.c >@@ -2452,6 +2452,28 @@ bool smbXcli_conn_has_async_calls(struct smbXcli_conn *conn) > || (talloc_array_length(conn->pending) != 0)); > } > >+bool smb2cli_conn_req_possible(struct smbXcli_conn *conn, uint32_t *max_dyn_len) >+{ >+ uint16_t credits = 1; >+ >+ if (conn->smb2.cur_credits == 0) { >+ if (max_dyn_len != NULL) { >+ *max_dyn_len = 0; >+ } >+ return false; >+ } >+ >+ if (conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) { >+ credits = conn->smb2.cur_credits; >+ } >+ >+ if (max_dyn_len != NULL) { >+ *max_dyn_len = credits * 65536; >+ } >+ >+ return true; >+} >+ > uint32_t smb2cli_conn_server_capabilities(struct smbXcli_conn *conn) > { > return conn->smb2.server.capabilities; >diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h >index 6b3156f..a7cfcc3 100644 >--- a/libcli/smb/smbXcli_base.h >+++ b/libcli/smb/smbXcli_base.h >@@ -199,6 +199,7 @@ NTSTATUS smb1cli_echo_recv(struct tevent_req *req); > NTSTATUS smb1cli_echo(struct smbXcli_conn *conn, uint32_t timeout_msec, > uint16_t num_echos, DATA_BLOB data); > >+bool smb2cli_conn_req_possible(struct smbXcli_conn *conn, uint32_t *max_dyn_len); > uint32_t smb2cli_conn_server_capabilities(struct smbXcli_conn *conn); > uint16_t smb2cli_conn_server_security_mode(struct smbXcli_conn *conn); > uint32_t smb2cli_conn_max_trans_size(struct smbXcli_conn *conn); >-- >1.7.9.5 > > >From 5c38ce6c450683b5b7c26744a3e8ea890f383de4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 14:10:59 +0200 >Subject: [PATCH 20/57] s3:libsmb: rewrite cli_push* to use > smb1cli_conn_req_possible() > >This works out if it's possible to ship the next request dynamically >instead of relying on fixed values. > >The default window size is 16 MByte. > >We limit the number of outstanding chunks/requests to 256. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit b846b3acd2b217a0d67c1e8fcb039e03498c4e47) >--- > source3/libsmb/clireadwrite.c | 288 ++++++++++++++++++++++++++--------------- > 1 file changed, 187 insertions(+), 101 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index 47e7f1b..550c52b 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -1092,13 +1092,7 @@ NTSTATUS cli_writeall(struct cli_state *cli, uint16_t fnum, uint16_t mode, > return status; > } > >-struct cli_push_write_state { >- struct tevent_req *req;/* This is the main request! Not the subreq */ >- uint32_t idx; >- off_t ofs; >- uint8_t *buf; >- size_t size; >-}; >+struct cli_push_chunk; > > struct cli_push_state { > struct tevent_context *ev; >@@ -1106,7 +1100,6 @@ struct cli_push_state { > uint16_t fnum; > uint16_t mode; > off_t start_offset; >- size_t window_size; > > size_t (*source)(uint8_t *buf, size_t n, void *priv); > void *priv; >@@ -1118,62 +1111,32 @@ struct cli_push_state { > > /* > * Outstanding requests >+ * >+ * The maximum is 256: >+ * - which would be a window of 256 MByte >+ * for SMB2 with multi-credit >+ * or smb1 unix extentions. > */ >- uint32_t pending; >- uint16_t max_reqs; >- uint32_t num_reqs; >- struct cli_push_write_state **reqs; >+ uint16_t max_chunks; >+ uint16_t num_chunks; >+ uint16_t num_waiting; >+ struct cli_push_chunk *chunks; > }; > >-static void cli_push_written(struct tevent_req *req); >- >-static bool cli_push_write_setup(struct tevent_req *req, >- struct cli_push_state *state, >- uint32_t idx) >-{ >- struct cli_push_write_state *substate; >+struct cli_push_chunk { >+ struct cli_push_chunk *prev, *next; >+ struct tevent_req *req;/* This is the main request! Not the subreq */ > struct tevent_req *subreq; >+ off_t ofs; >+ uint8_t *buf; >+ size_t total_size; >+ size_t tmp_size; >+ bool done; >+}; > >- substate = talloc(state->reqs, struct cli_push_write_state); >- if (!substate) { >- return false; >- } >- substate->req = req; >- substate->idx = idx; >- substate->ofs = state->next_offset; >- substate->buf = talloc_array(substate, uint8_t, state->chunk_size); >- if (!substate->buf) { >- talloc_free(substate); >- return false; >- } >- substate->size = state->source(substate->buf, >- state->chunk_size, >- state->priv); >- if (substate->size == 0) { >- state->eof = true; >- /* nothing to send */ >- talloc_free(substate); >- return true; >- } >- >- 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; >- } >- tevent_req_set_callback(subreq, cli_push_written, substate); >- >- state->reqs[idx] = substate; >- state->pending += 1; >- state->next_offset += substate->size; >- >- return true; >-} >+static void cli_push_setup_chunks(struct tevent_req *req); >+static void cli_push_chunk_ship(struct cli_push_chunk *chunk); >+static void cli_push_chunk_done(struct tevent_req *subreq); > > struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, > struct cli_state *cli, >@@ -1185,8 +1148,8 @@ struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, > { > struct tevent_req *req; > struct cli_push_state *state; >- uint32_t i; > size_t page_size = 1024; >+ uint64_t tmp64; > > req = tevent_req_create(mem_ctx, &state, struct cli_push_state); > if (req == NULL) { >@@ -1199,8 +1162,6 @@ struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, > state->mode = mode; > state->source = source; > state->priv = priv; >- state->eof = false; >- state->pending = 0; > state->next_offset = start_offset; > > state->chunk_size = cli_write_max_bufsize(cli, mode, 14); >@@ -1208,77 +1169,202 @@ struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, > state->chunk_size &= ~(page_size - 1); > } > >- state->max_reqs = smbXcli_conn_max_requests(cli->conn); >- > if (window_size == 0) { >- window_size = state->max_reqs * state->chunk_size; >+ /* >+ * We use 16 MByte as default window size. >+ */ >+ window_size = 16 * 1024 * 1024; > } >- state->num_reqs = window_size/state->chunk_size; >+ >+ tmp64 = window_size/state->chunk_size; > if ((window_size % state->chunk_size) > 0) { >- state->num_reqs += 1; >+ tmp64 += 1; > } >- state->num_reqs = MIN(state->num_reqs, state->max_reqs); >- state->num_reqs = MAX(state->num_reqs, 1); >+ tmp64 = MAX(tmp64, 1); >+ tmp64 = MIN(tmp64, 256); >+ state->max_chunks = tmp64; > >- state->reqs = talloc_zero_array(state, struct cli_push_write_state *, >- state->num_reqs); >- if (state->reqs == NULL) { >- goto failed; >+ /* >+ * We defer the callback because of the complex >+ * substate/subfunction logic >+ */ >+ tevent_req_defer_callback(req, ev); >+ >+ cli_push_setup_chunks(req); >+ if (!tevent_req_is_in_progress(req)) { >+ return tevent_req_post(req, ev); > } > >- for (i=0; i<state->num_reqs; i++) { >- if (!cli_push_write_setup(req, state, i)) { >- goto failed; >+ return req; >+} >+ >+static void cli_push_setup_chunks(struct tevent_req *req) >+{ >+ struct cli_push_state *state = >+ tevent_req_data(req, >+ struct cli_push_state); >+ struct cli_push_chunk *chunk, *next = NULL; >+ size_t i; >+ >+ for (chunk = state->chunks; chunk; chunk = next) { >+ /* >+ * Note that chunk might be removed from this call. >+ */ >+ next = chunk->next; >+ cli_push_chunk_ship(chunk); >+ if (!tevent_req_is_in_progress(req)) { >+ return; >+ } >+ } >+ >+ for (i = state->num_chunks; i < state->max_chunks; i++) { >+ >+ if (state->num_waiting > 0) { >+ return; > } > > if (state->eof) { > break; > } >+ >+ chunk = talloc_zero(state, struct cli_push_chunk); >+ if (tevent_req_nomem(chunk, req)) { >+ return; >+ } >+ chunk->req = req; >+ chunk->ofs = state->next_offset; >+ chunk->buf = talloc_array(chunk, >+ uint8_t, >+ state->chunk_size); >+ if (tevent_req_nomem(chunk->buf, req)) { >+ return; >+ } >+ chunk->total_size = state->source(chunk->buf, >+ state->chunk_size, >+ state->priv); >+ if (chunk->total_size == 0) { >+ /* nothing to send */ >+ talloc_free(chunk); >+ state->eof = true; >+ break; >+ } >+ state->next_offset += chunk->total_size; >+ >+ DLIST_ADD_END(state->chunks, chunk, NULL); >+ state->num_chunks++; >+ state->num_waiting++; >+ >+ cli_push_chunk_ship(chunk); >+ if (!tevent_req_is_in_progress(req)) { >+ return; >+ } > } > >- if (state->pending == 0) { >- tevent_req_done(req); >- return tevent_req_post(req, ev); >+ if (!state->eof) { >+ return; > } > >- return req; >+ if (state->num_chunks > 0) { >+ return; >+ } >+ >+ tevent_req_done(req); >+} >+ >+static void cli_push_chunk_ship(struct cli_push_chunk *chunk) >+{ >+ struct tevent_req *req = chunk->req; >+ struct cli_push_state *state = >+ tevent_req_data(req, >+ struct cli_push_state); >+ bool ok; >+ const uint8_t *buf; >+ off_t ofs; >+ size_t size; >+ >+ if (chunk->done) { >+ DLIST_REMOVE(state->chunks, chunk); >+ SMB_ASSERT(state->num_chunks > 0); >+ state->num_chunks--; >+ TALLOC_FREE(chunk); >+ >+ return; >+ } >+ >+ if (chunk->subreq != NULL) { >+ return; >+ } >+ >+ SMB_ASSERT(state->num_waiting > 0); >+ >+ buf = chunk->buf + chunk->tmp_size; >+ ofs = chunk->ofs + chunk->tmp_size; >+ size = chunk->total_size - chunk->tmp_size; >+ >+ ok = smb1cli_conn_req_possible(state->cli->conn); >+ if (!ok) { >+ return; >+ } >+ >+ chunk->subreq = cli_write_andx_send(chunk, >+ state->ev, >+ state->cli, >+ state->fnum, >+ state->mode, >+ buf, >+ ofs, >+ size); >+ if (tevent_req_nomem(chunk->subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(chunk->subreq, >+ cli_push_chunk_done, >+ chunk); > >- failed: >- tevent_req_nterror(req, NT_STATUS_NO_MEMORY); >- return tevent_req_post(req, ev); >+ state->num_waiting--; >+ return; > } > >-static void cli_push_written(struct tevent_req *subreq) >+static void cli_push_chunk_done(struct tevent_req *subreq) > { >- struct cli_push_write_state *substate = tevent_req_callback_data( >- subreq, struct cli_push_write_state); >- struct tevent_req *req = substate->req; >- struct cli_push_state *state = tevent_req_data( >- req, struct cli_push_state); >+ struct cli_push_chunk *chunk = >+ tevent_req_callback_data(subreq, >+ struct cli_push_chunk); >+ struct tevent_req *req = chunk->req; >+ struct cli_push_state *state = >+ tevent_req_data(req, >+ struct cli_push_state); > NTSTATUS status; >- uint32_t idx = substate->idx; >+ size_t expected = chunk->total_size - chunk->tmp_size; >+ size_t written; > >- state->reqs[idx] = NULL; >- state->pending -= 1; >+ chunk->subreq = NULL; > >- status = cli_writeall_recv(subreq, NULL); >+ status = cli_write_andx_recv(subreq, &written); > TALLOC_FREE(subreq); >- TALLOC_FREE(substate); > if (tevent_req_nterror(req, status)) { > return; > } > >- if (!state->eof) { >- if (!cli_push_write_setup(req, state, idx)) { >- tevent_req_nterror(req, NT_STATUS_NO_MEMORY); >- return; >- } >+ if (written > expected) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); >+ return; > } > >- if (state->pending == 0) { >- tevent_req_done(req); >+ if (written == 0) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); > return; > } >+ >+ chunk->tmp_size += written; >+ >+ if (chunk->tmp_size == chunk->total_size) { >+ chunk->done = true; >+ } else { >+ state->num_waiting++; >+ } >+ >+ cli_push_setup_chunks(req); > } > > NTSTATUS cli_push_recv(struct tevent_req *req) >-- >1.7.9.5 > > >From 404d40580b643433228a1c59060f18757bd52de0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 18:03:50 +0200 >Subject: [PATCH 21/57] s3:libsmb: rewrite cli_pull* to use > smb1cli_conn_req_possible() > >This works out if it's possible to ship the next request dynamically >instead of relying on fixed values. > >The default window size is 16 MByte. > >We limit the number of outstanding chunks/requests to 256. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 8062aefbe3c2fcc73e3d19af6663c8736c570f7c) >--- > source3/libsmb/clireadwrite.c | 417 ++++++++++++++++++++++++----------------- > 1 file changed, 246 insertions(+), 171 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index 550c52b..dd5d4c2 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -388,23 +388,9 @@ static NTSTATUS cli_readall_recv(struct tevent_req *req, ssize_t *received, > return NT_STATUS_OK; > } > >-struct cli_pull_subreq { >- struct tevent_req *req; >- ssize_t received; >- uint8_t *buf; >-}; >- >-/* >- * Parallel read support. >- * >- * cli_pull sends as many read&x requests as the server would allow via >- * max_mux at a time. When replies flow back in, the data is written into >- * the callback function "sink" in the right order. >- */ >+struct cli_pull_chunk; > > struct cli_pull_state { >- struct tevent_req *req; >- > struct tevent_context *ev; > struct cli_state *cli; > uint16_t fnum; >@@ -415,54 +401,49 @@ struct cli_pull_state { > void *priv; > > size_t chunk_size; >+ off_t next_offset; >+ off_t remaining; > > /* >- * Outstanding requests >- */ >- uint16_t max_reqs; >- int num_reqs; >- struct cli_pull_subreq *reqs; >- >- /* >- * For how many bytes did we send requests already? >- */ >- off_t requested; >- >- /* >- * Next request index to push into "sink". This walks around the "req" >- * array, taking care that the requests are pushed to "sink" in the >- * right order. If necessary (i.e. replies don't come in in the right >- * order), replies are held back in "reqs". >+ * How many bytes did we push into "sink"? > */ >- int top_req; >+ off_t pushed; > > /* >- * How many bytes did we push into "sink"? >+ * Outstanding requests >+ * >+ * The maximum is 256: >+ * - which would be a window of 256 MByte >+ * for SMB2 with multi-credit >+ * or smb1 unix extentions. > */ >- >- off_t pushed; >+ uint16_t max_chunks; >+ uint16_t num_chunks; >+ uint16_t num_waiting; >+ struct cli_pull_chunk *chunks; > }; > >-static char *cli_pull_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) >-{ >- struct cli_pull_state *state = tevent_req_data( >- req, struct cli_pull_state); >- char *result; >- >- result = tevent_req_default_print(req, mem_ctx); >- if (result == NULL) { >- return NULL; >- } >- >- return talloc_asprintf_append_buffer( >- result, "num_reqs=%d, top_req=%d", >- state->num_reqs, state->top_req); >-} >+struct cli_pull_chunk { >+ struct cli_pull_chunk *prev, *next; >+ struct tevent_req *req;/* This is the main request! Not the subreq */ >+ struct tevent_req *subreq; >+ off_t ofs; >+ uint8_t *buf; >+ size_t total_size; >+ size_t tmp_size; >+ bool done; >+}; > >-static void cli_pull_read_done(struct tevent_req *read_req); >+static void cli_pull_setup_chunks(struct tevent_req *req); >+static void cli_pull_chunk_ship(struct cli_pull_chunk *chunk); >+static void cli_pull_chunk_done(struct tevent_req *subreq); > > /* >- * Prepare an async pull request >+ * Parallel read support. >+ * >+ * cli_pull sends as many read&x requests as the server would allow via >+ * max_mux at a time. When replies flow back in, the data is written into >+ * the callback function "sink" in the right order. > */ > > struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, >@@ -476,16 +457,13 @@ struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, > { > struct tevent_req *req; > struct cli_pull_state *state; >- int i; > size_t page_size = 1024; >+ uint64_t tmp64; > > req = tevent_req_create(mem_ctx, &state, struct cli_pull_state); > if (req == NULL) { > return NULL; > } >- tevent_req_set_print_fn(req, cli_pull_print); >- state->req = req; >- > state->cli = cli; > state->ev = ev; > state->fnum = fnum; >@@ -493,9 +471,8 @@ struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, > state->size = size; > state->sink = sink; > state->priv = priv; >- >- state->pushed = 0; >- state->top_req = 0; >+ state->next_offset = start_offset; >+ state->remaining = size; > > if (size == 0) { > tevent_req_done(req); >@@ -507,155 +484,251 @@ struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, > state->chunk_size &= ~(page_size - 1); > } > >- state->max_reqs = smbXcli_conn_max_requests(cli->conn); >+ if (window_size == 0) { >+ /* >+ * We use 16 MByte as default window size. >+ */ >+ window_size = 16 * 1024 * 1024; >+ } >+ >+ tmp64 = window_size/state->chunk_size; >+ if ((window_size % state->chunk_size) > 0) { >+ tmp64 += 1; >+ } >+ tmp64 = MAX(tmp64, 1); >+ tmp64 = MIN(tmp64, 256); >+ state->max_chunks = tmp64; >+ >+ /* >+ * We defer the callback because of the complex >+ * substate/subfunction logic >+ */ >+ tevent_req_defer_callback(req, ev); >+ >+ cli_pull_setup_chunks(req); >+ if (!tevent_req_is_in_progress(req)) { >+ return tevent_req_post(req, ev); >+ } >+ >+ return req; >+} > >- state->num_reqs = MAX(window_size/state->chunk_size, 1); >- state->num_reqs = MIN(state->num_reqs, state->max_reqs); >+static void cli_pull_setup_chunks(struct tevent_req *req) >+{ >+ struct cli_pull_state *state = >+ tevent_req_data(req, >+ struct cli_pull_state); >+ struct cli_pull_chunk *chunk, *next = NULL; >+ size_t i; > >- state->reqs = talloc_zero_array(state, struct cli_pull_subreq, >- state->num_reqs); >- if (state->reqs == NULL) { >- goto failed; >+ for (chunk = state->chunks; chunk; chunk = next) { >+ /* >+ * Note that chunk might be removed from this call. >+ */ >+ next = chunk->next; >+ cli_pull_chunk_ship(chunk); >+ if (!tevent_req_is_in_progress(req)) { >+ return; >+ } > } > >- state->requested = 0; >+ for (i = state->num_chunks; i < state->max_chunks; i++) { > >- for (i=0; i<state->num_reqs; i++) { >- struct cli_pull_subreq *subreq = &state->reqs[i]; >- off_t size_left; >- size_t request_thistime; >+ if (state->num_waiting > 0) { >+ return; >+ } > >- if (state->requested >= size) { >- state->num_reqs = i; >+ if (state->remaining == 0) { > break; > } > >- size_left = size - state->requested; >- request_thistime = MIN(size_left, state->chunk_size); >+ chunk = talloc_zero(state, struct cli_pull_chunk); >+ if (tevent_req_nomem(chunk, req)) { >+ return; >+ } >+ chunk->req = req; >+ chunk->ofs = state->next_offset; >+ chunk->total_size = MIN(state->remaining, state->chunk_size); >+ state->next_offset += chunk->total_size; >+ state->remaining -= chunk->total_size; > >- subreq->req = cli_readall_send( >- state->reqs, ev, cli, fnum, >- state->start_offset + state->requested, >- request_thistime); >+ DLIST_ADD_END(state->chunks, chunk, NULL); >+ state->num_chunks++; >+ state->num_waiting++; > >- if (subreq->req == NULL) { >- goto failed; >+ cli_pull_chunk_ship(chunk); >+ if (!tevent_req_is_in_progress(req)) { >+ return; > } >- tevent_req_set_callback(subreq->req, cli_pull_read_done, req); >- state->requested += request_thistime; > } >- return req; > >-failed: >- TALLOC_FREE(req); >- return NULL; >-} >+ if (state->remaining > 0) { >+ return; >+ } > >-/* >- * Handle incoming read replies, push the data into sink and send out new >- * requests if necessary. >- */ >+ if (state->num_chunks > 0) { >+ return; >+ } >+ >+ tevent_req_done(req); >+} > >-static void cli_pull_read_done(struct tevent_req *subreq) >+static void cli_pull_chunk_ship(struct cli_pull_chunk *chunk) > { >- struct tevent_req *req = tevent_req_callback_data( >- subreq, struct tevent_req); >- struct cli_pull_state *state = tevent_req_data( >- req, struct cli_pull_state); >- struct cli_pull_subreq *pull_subreq = NULL; >- NTSTATUS status; >- int i; >+ struct tevent_req *req = chunk->req; >+ struct cli_pull_state *state = >+ tevent_req_data(req, >+ struct cli_pull_state); >+ bool ok; >+ off_t ofs; >+ size_t size; > >- for (i = 0; i < state->num_reqs; i++) { >- pull_subreq = &state->reqs[i]; >- if (subreq == pull_subreq->req) { >- break; >+ if (chunk->done) { >+ NTSTATUS status; >+ >+ if (chunk != state->chunks) { >+ /* >+ * this chunk is not the >+ * first one in the list. >+ * >+ * which means we should not >+ * push it into the sink yet. >+ */ >+ return; >+ } >+ >+ if (chunk->tmp_size == 0) { >+ /* >+ * we git a short read, we're done >+ */ >+ tevent_req_done(req); >+ return; > } >+ >+ status = state->sink((char *)chunk->buf, >+ chunk->tmp_size, >+ state->priv); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ state->pushed += chunk->tmp_size; >+ >+ if (chunk->tmp_size < chunk->total_size) { >+ /* >+ * we git a short read, we're done >+ */ >+ tevent_req_done(req); >+ return; >+ } >+ >+ DLIST_REMOVE(state->chunks, chunk); >+ SMB_ASSERT(state->num_chunks > 0); >+ state->num_chunks--; >+ TALLOC_FREE(chunk); >+ >+ return; > } >- if (i == state->num_reqs) { >- /* Huh -- received something we did not send?? */ >- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); >+ >+ if (chunk->subreq != NULL) { > return; > } > >- status = cli_readall_recv(subreq, &pull_subreq->received, >- &pull_subreq->buf); >- if (!NT_STATUS_IS_OK(status)) { >- tevent_req_nterror(state->req, status); >+ SMB_ASSERT(state->num_waiting > 0); >+ >+ ofs = chunk->ofs + chunk->tmp_size; >+ size = chunk->total_size - chunk->tmp_size; >+ >+ ok = smb1cli_conn_req_possible(state->cli->conn); >+ if (!ok) { > return; > } > >- /* >- * This loop is the one to take care of out-of-order replies. All >- * pending requests are in state->reqs, state->reqs[top_req] is the >- * one that is to be pushed next. If however a request later than >- * top_req is replied to, then we can't push yet. If top_req is >- * replied to at a later point then, we need to push all the finished >- * requests. >- */ >+ chunk->subreq = cli_read_andx_send(chunk, >+ state->ev, >+ state->cli, >+ state->fnum, >+ ofs, >+ size); >+ if (tevent_req_nomem(chunk->subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(chunk->subreq, >+ cli_pull_chunk_done, >+ chunk); > >- while (state->reqs[state->top_req].req != NULL) { >- struct cli_pull_subreq *top_subreq; >+ state->num_waiting--; >+ return; >+} > >- DEBUG(11, ("cli_pull_read_done: top_req = %d\n", >- state->top_req)); >+static void cli_pull_chunk_done(struct tevent_req *subreq) >+{ >+ struct cli_pull_chunk *chunk = >+ tevent_req_callback_data(subreq, >+ struct cli_pull_chunk); >+ struct tevent_req *req = chunk->req; >+ struct cli_pull_state *state = >+ tevent_req_data(req, >+ struct cli_pull_state); >+ NTSTATUS status; >+ size_t expected = chunk->total_size - chunk->tmp_size; >+ ssize_t received; >+ uint8_t *buf = NULL; > >- top_subreq = &state->reqs[state->top_req]; >+ chunk->subreq = NULL; > >- if (tevent_req_is_in_progress(top_subreq->req)) { >- DEBUG(11, ("cli_pull_read_done: top request not yet " >- "done\n")); >- return; >- } >+ status = cli_read_andx_recv(subreq, &received, &buf); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { >+ received = 0; >+ status = NT_STATUS_OK; >+ } >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ if (received > expected) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); >+ return; >+ } > >- DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " >- "pushed\n", (int)top_subreq->received, >- (int)state->pushed)); >+ if (received == 0) { >+ /* >+ * We got EOF we're done >+ */ >+ chunk->done = true; >+ cli_pull_setup_chunks(req); >+ return; >+ } > >- status = state->sink((char *)top_subreq->buf, >- top_subreq->received, state->priv); >- if (tevent_req_nterror(state->req, status)) { >+ if (received == chunk->total_size) { >+ /* >+ * We got it in the first run. >+ * >+ * We don't call TALLOC_FREE(subreq) >+ * here and keep the returned buffer. >+ */ >+ chunk->buf = buf; >+ } else if (chunk->buf == NULL) { >+ chunk->buf = talloc_array(chunk, uint8_t, chunk->total_size); >+ if (tevent_req_nomem(chunk->buf, req)) { > return; > } >- state->pushed += top_subreq->received; >- >- TALLOC_FREE(state->reqs[state->top_req].req); >- >- if (state->requested < state->size) { >- struct tevent_req *new_req; >- off_t size_left; >- size_t request_thistime; >- >- size_left = state->size - state->requested; >- request_thistime = MIN(size_left, state->chunk_size); >- >- DEBUG(10, ("cli_pull_read_done: Requesting %d bytes " >- "at %d, position %d\n", >- (int)request_thistime, >- (int)(state->start_offset >- + 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 (tevent_req_nomem(new_req, state->req)) { >- return; >- } >- tevent_req_set_callback(new_req, cli_pull_read_done, >- req); >- >- state->reqs[state->top_req].req = new_req; >- state->requested += request_thistime; >- } >+ } > >- state->top_req = (state->top_req+1) % state->num_reqs; >+ if (received != chunk->total_size) { >+ uint8_t *p = chunk->buf + chunk->tmp_size; >+ memcpy(p, buf, received); >+ TALLOC_FREE(subreq); > } > >- tevent_req_done(req); >+ chunk->tmp_size += received; >+ >+ if (chunk->tmp_size == chunk->total_size) { >+ chunk->done = true; >+ } else { >+ state->num_waiting++; >+ } >+ >+ cli_pull_setup_chunks(req); > } > > NTSTATUS cli_pull_recv(struct tevent_req *req, off_t *received) >@@ -665,9 +738,11 @@ NTSTATUS cli_pull_recv(struct tevent_req *req, off_t *received) > NTSTATUS status; > > if (tevent_req_is_nterror(req, &status)) { >+ tevent_req_received(req); > return status; > } > *received = state->pushed; >+ tevent_req_received(req); > return NT_STATUS_OK; > } > >-- >1.7.9.5 > > >From a197b9c6d4b956dfe981293602fb3e94a6c9e1a4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 18:23:55 +0200 >Subject: [PATCH 22/57] s3:libsmb: remove unused cli_readall* > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 9193a58375691bfca9e3cce1ff61b2b6dd65a982) >--- > source3/libsmb/clireadwrite.c | 119 ----------------------------------------- > 1 file changed, 119 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index dd5d4c2..10dc79b 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -269,125 +269,6 @@ NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received, > return NT_STATUS_OK; > } > >-struct cli_readall_state { >- struct tevent_context *ev; >- struct cli_state *cli; >- uint16_t fnum; >- off_t start_offset; >- size_t size; >- size_t received; >- uint8_t *buf; >-}; >- >-static void cli_readall_done(struct tevent_req *subreq); >- >-static struct tevent_req *cli_readall_send(TALLOC_CTX *mem_ctx, >- struct tevent_context *ev, >- struct cli_state *cli, >- uint16_t fnum, >- off_t offset, size_t size) >-{ >- struct tevent_req *req, *subreq; >- struct cli_readall_state *state; >- >- req = tevent_req_create(mem_ctx, &state, struct cli_readall_state); >- if (req == NULL) { >- return NULL; >- } >- state->ev = ev; >- state->cli = cli; >- state->fnum = fnum; >- state->start_offset = offset; >- state->size = size; >- state->received = 0; >- state->buf = NULL; >- >- subreq = cli_read_andx_send(state, ev, cli, fnum, offset, size); >- if (tevent_req_nomem(subreq, req)) { >- return tevent_req_post(req, ev); >- } >- tevent_req_set_callback(subreq, cli_readall_done, req); >- return req; >-} >- >-static void cli_readall_done(struct tevent_req *subreq) >-{ >- struct tevent_req *req = tevent_req_callback_data( >- subreq, struct tevent_req); >- struct cli_readall_state *state = tevent_req_data( >- req, struct cli_readall_state); >- ssize_t received; >- uint8_t *buf; >- NTSTATUS status; >- >- status = cli_read_andx_recv(subreq, &received, &buf); >- if (tevent_req_nterror(req, status)) { >- return; >- } >- >- if (received == 0) { >- /* EOF */ >- tevent_req_done(req); >- 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. cli_read_andx 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 = cli_read_andx_send(state, state->ev, state->cli, state->fnum, >- state->start_offset + state->received, >- state->size - state->received); >- if (tevent_req_nomem(subreq, req)) { >- return; >- } >- tevent_req_set_callback(subreq, cli_readall_done, req); >-} >- >-static NTSTATUS cli_readall_recv(struct tevent_req *req, ssize_t *received, >- uint8_t **rcvbuf) >-{ >- struct cli_readall_state *state = tevent_req_data( >- req, struct cli_readall_state); >- NTSTATUS status; >- >- if (tevent_req_is_nterror(req, &status)) { >- return status; >- } >- *received = state->received; >- *rcvbuf = state->buf; >- return NT_STATUS_OK; >-} >- > struct cli_pull_chunk; > > struct cli_pull_state { >-- >1.7.9.5 > > >From 3a7c5f92d4fb7c76beaea814ccb0e4fbbe3ad749 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 10:46:28 +0200 >Subject: [PATCH 23/57] s3:client: use the default io size > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 9b4692f2d057f31f76db0bdf7c4a515db057e2dd) >--- > source3/client/client.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/client/client.c b/source3/client/client.c >index d09d012..5ec2948 100644 >--- a/source3/client/client.c >+++ b/source3/client/client.c >@@ -55,7 +55,7 @@ static bool grepable = false; > static char *cmdstr = NULL; > const char *cmd_ptr = NULL; > >-static int io_bufsize = 524288; >+static int io_bufsize = 0; /* we use the default size */ > > static int name_type = 0x20; > static int max_protocol = -1; >-- >1.7.9.5 > > >From b98c7dfcfa37e4f44a248f7493d861272e064467 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 10:47:11 +0200 >Subject: [PATCH 24/57] s3:client: fix compiler warning > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 2394f8788d2f6e21064db0b6099a0dbe3a33e1d6) >--- > source3/client/client.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/client/client.c b/source3/client/client.c >index 5ec2948..e91db4a 100644 >--- a/source3/client/client.c >+++ b/source3/client/client.c >@@ -5338,6 +5338,7 @@ static int do_message_op(struct user_auth_info *a_info) > > int main(int argc,char *argv[]) > { >+ const char **const_argv = discard_const_p(const char *, argv); > char *base_directory = NULL; > int opt; > char *query_host = NULL; >@@ -5388,7 +5389,7 @@ static int do_message_op(struct user_auth_info *a_info) > popt_common_set_auth_info(auth_info); > > /* skip argv(0) */ >- pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0); >+ pc = poptGetContext("smbclient", argc, const_argv, long_options, 0); > poptSetOtherOptionHelp(pc, "service <password>"); > > while ((opt = poptGetNextOpt(pc)) != -1) { >-- >1.7.9.5 > > >From 9f586e6a0f865a4a531011b542251257e683a99e Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 13:48:55 -0700 >Subject: [PATCH 25/57] s3:lib: 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> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit c80349e0fad7c182b0bddefed99a78d95323faca) >--- > 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 f4b0456..42cd25b 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; > >@@ -965,49 +966,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 a216f15..830ef34 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 a8bdaf0..0f4bac6 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.7.9.5 > > >From b2537feabc3f99dfcf9b165dc6a7d3cb8d8fee8d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:54:05 -0700 >Subject: [PATCH 26/57] s3:libsmb: Add in the core of the libsmb client SMB2 > functions. > >These create a synchronous cli_smb2_XXX() style interface >designed to plug directly into the libsmb/cliXXXX.c code. > >https://bugzilla.samba.org/show_bug.cgi?id=9974 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 28591dfd5d2163d9181d45d64a4a750e335b7c56) >--- > source3/include/client.h | 1 + > source3/libsmb/cli_smb2_fnum.c | 2373 ++++++++++++++++++++++++++++++++++++++++ > source3/libsmb/cli_smb2_fnum.h | 161 +++ > source3/libsmb/clirap.c | 7 +- > source3/libsmb/clirap.h | 4 + > source3/libsmb/libsmb.h | 1 + > source3/wscript_build | 3 +- > 7 files changed, 2543 insertions(+), 7 deletions(-) > create mode 100644 source3/libsmb/cli_smb2_fnum.c > create mode 100644 source3/libsmb/cli_smb2_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/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c >new file mode 100644 >index 0000000..d0b744b >--- /dev/null >+++ b/source3/libsmb/cli_smb2_fnum.c >@@ -0,0 +1,2373 @@ >+/* >+ Unix SMB/CIFS implementation. >+ smb2 lib >+ Copyright (C) Jeremy Allison 2013 >+ Copyright (C) Volker Lendecke 2013 >+ Copyright (C) Stefan Metzmacher 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 >+ cli_smb2_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 "cli_smb2_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_HANDLE; >+ } >+ 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 cli_smb2_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 cli_smb2_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 cli_smb2_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 = cli_smb2_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 cli_smb2_close_fnum(cli, fnum); >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 to delete a directory >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 = cli_smb2_create_fnum(cli, >+ dname, >+ 0, /* create_flags */ >+ DELETE_ACCESS, /* desired_access */ >+ FILE_ATTRIBUTE_DIRECTORY, /* file attributes */ >+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */ >+ FILE_OPEN, /* create_disposition */ >+ FILE_DIRECTORY_FILE|FILE_DELETE_ON_CLOSE, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ return cli_smb2_close_fnum(cli, fnum); >+} >+ >+/*************************************************************** >+ Small wrapper that allows SMB2 to unlink a pathname. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 = cli_smb2_create_fnum(cli, >+ fname, >+ 0, /* create_flags */ >+ DELETE_ACCESS, /* desired_access */ >+ FILE_ATTRIBUTE_NORMAL, /* file attributes */ >+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */ >+ FILE_OPEN, /* create_disposition */ >+ FILE_DELETE_ON_CLOSE, /* create_options */ >+ &fnum, >+ NULL); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ return cli_smb2_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 cli_smb2_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 = cli_smb2_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) { >+ cli_smb2_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 cli_smb2_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 = cli_smb2_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 = cli_smb2_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; >+ } >+ >+ cli_smb2_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 = cli_smb2_create_fnum(cli, >+ name, >+ 0, /* create_flags */ >+ desired_access, >+ 0, /* file attributes */ >+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */ >+ FILE_OPEN, /* create_disposition */ >+ 0, /* create_options */ >+ pfnum, >+ NULL); >+ >+ if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { >+ status = cli_smb2_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 cli_smb2_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) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a fnum info (basic level). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 cli_smb2_qfileinfo_basic(). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 = cli_smb2_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 get pathname attributes. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_getatr(struct cli_state *cli, >+ const char *name, >+ uint16_t *attr, >+ off_t *size, >+ time_t *write_time) >+{ >+ NTSTATUS status; >+ uint16_t fnum = -1; >+ 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 = 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 = cli_smb2_getattrE(cli, >+ fnum, >+ attr, >+ size, >+ NULL, >+ NULL, >+ write_time); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto fail; >+ } >+ >+ fail: >+ >+ if (fnum != -1) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a pathname info (basic level). >+ Implement on top of cli_smb2_qfileinfo_basic(). >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 = cli_smb2_qfileinfo_basic(cli, >+ fnum, >+ mode, >+ size, >+ create_time, >+ access_time, >+ write_time, >+ change_time, >+ ino); >+ >+ fail: >+ >+ if (fnum != -1) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query pathname streams. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set pathname attributes. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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[40]; >+ 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); >+ } >+ /* Set all the other times to -1. */ >+ SBVAL(inbuf.data, 0, 0xFFFFFFFFFFFFFFFFLL); >+ SBVAL(inbuf.data, 8, 0xFFFFFFFFFFFFFFFFLL); >+ SBVAL(inbuf.data, 24, 0xFFFFFFFFFFFFFFFFLL); >+ >+ 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) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set file handle times. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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[40]; >+ 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); >+ >+ SBVAL(inbuf.data, 0, 0xFFFFFFFFFFFFFFFFLL); >+ 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 cli_smb2_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 = cli_smb2_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) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to query a security descriptor. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 cli_smb2_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 cli_smb2_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) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ TALLOC_FREE(frame); >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to set an EA on a fnum. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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 cli_smb2_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) { >+ cli_smb2_close_fnum(cli, fnum); >+ } >+ >+ return status; >+} >+ >+/*************************************************************** >+ Wrapper that allows SMB2 to get an EA list on a pathname. >+ Synchronous only. >+***************************************************************/ >+ >+NTSTATUS cli_smb2_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; >+} >+ >+struct cli_smb2_read_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 cli_smb2_read_done(struct tevent_req *subreq); >+ >+struct tevent_req *cli_smb2_read_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 cli_smb2_read_state *state; >+ >+ req = tevent_req_create(mem_ctx, &state, struct cli_smb2_read_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 (tevent_req_nterror(req, status)) { >+ return tevent_req_post(req, ev); >+ } >+ >+ 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, cli_smb2_read_done, req); >+ return req; >+} >+ >+static void cli_smb2_read_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct cli_smb2_read_state *state = tevent_req_data( >+ req, struct cli_smb2_read_state); >+ NTSTATUS status; >+ >+ status = smb2cli_read_recv(subreq, state, >+ &state->buf, &state->received); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ if (state->received > state->size) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); >+ return; >+ } >+ >+ tevent_req_done(req); >+} >+ >+NTSTATUS cli_smb2_read_recv(struct tevent_req *req, >+ ssize_t *received, >+ uint8_t **rcvbuf) >+{ >+ NTSTATUS status; >+ struct cli_smb2_read_state *state = tevent_req_data( >+ req, struct cli_smb2_read_state); >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ /* >+ * As in cli_read_andx_recv() rcvbuf is talloced from the request, so >+ * better make sure that you copy it away before you talloc_free(req). >+ * "rcvbuf" is NOT a talloc_ctx of its own, so do not talloc_move it! >+ */ >+ *received = (ssize_t)state->received; >+ *rcvbuf = state->buf; >+ return NT_STATUS_OK; >+} >+ >+struct cli_smb2_write_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 cli_smb2_write_written(struct tevent_req *req); >+ >+struct tevent_req *cli_smb2_write_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 cli_smb2_write_state *state = NULL; >+ >+ req = tevent_req_create(mem_ctx, &state, struct cli_smb2_write_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 (tevent_req_nterror(req, status)) { >+ return tevent_req_post(req, ev); >+ } >+ >+ 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, cli_smb2_write_written, req); >+ return req; >+} >+ >+static void cli_smb2_write_written(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct cli_smb2_write_state *state = tevent_req_data( >+ req, struct cli_smb2_write_state); >+ NTSTATUS status; >+ uint32_t written; >+ >+ status = smb2cli_write_recv(subreq, &written); >+ TALLOC_FREE(subreq); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ state->written = written; >+ >+ tevent_req_done(req); >+} >+ >+NTSTATUS cli_smb2_write_recv(struct tevent_req *req, >+ size_t *pwritten) >+{ >+ struct cli_smb2_write_state *state = tevent_req_data( >+ req, struct cli_smb2_write_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ tevent_req_received(req); >+ return status; >+ } >+ >+ if (pwritten != NULL) { >+ *pwritten = (size_t)state->written; >+ } >+ tevent_req_received(req); >+ 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 cli_smb2_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 cli_smb2_writeall_written(struct tevent_req *req); >+ >+struct tevent_req *cli_smb2_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 cli_smb2_writeall_state *state = NULL; >+ uint32_t to_write; >+ uint32_t max_size; >+ bool ok; >+ >+ req = tevent_req_create(mem_ctx, &state, struct cli_smb2_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 (tevent_req_nterror(req, status)) { >+ return tevent_req_post(req, ev); >+ } >+ >+ to_write = state->size; >+ max_size = smb2cli_conn_max_write_size(state->cli->conn); >+ to_write = MIN(max_size, to_write); >+ ok = smb2cli_conn_req_possible(state->cli->conn, &max_size); >+ if (ok) { >+ to_write = MIN(max_size, to_write); >+ } >+ >+ 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->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_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, cli_smb2_writeall_written, req); >+ return req; >+} >+ >+static void cli_smb2_writeall_written(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct cli_smb2_writeall_state *state = tevent_req_data( >+ req, struct cli_smb2_writeall_state); >+ NTSTATUS status; >+ uint32_t written, to_write; >+ uint32_t max_size; >+ bool ok; >+ >+ 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; >+ } >+ >+ max_size = smb2cli_conn_max_write_size(state->cli->conn); >+ to_write = MIN(max_size, to_write); >+ ok = smb2cli_conn_req_possible(state->cli->conn, &max_size); >+ if (ok) { >+ to_write = MIN(max_size, to_write); >+ } >+ >+ 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, cli_smb2_writeall_written, req); >+} >+ >+NTSTATUS cli_smb2_writeall_recv(struct tevent_req *req, >+ size_t *pwritten) >+{ >+ struct cli_smb2_writeall_state *state = tevent_req_data( >+ req, struct cli_smb2_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/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h >new file mode 100644 >index 0000000..0068686 >--- /dev/null >+++ b/source3/libsmb/cli_smb2_fnum.h >@@ -0,0 +1,161 @@ >+/* >+ 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 cli_smb2_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 cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum); >+NTSTATUS cli_smb2_mkdir(struct cli_state *cli, const char *dirname); >+NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dirname); >+NTSTATUS cli_smb2_unlink(struct cli_state *cli,const char *fname); >+NTSTATUS cli_smb2_list(struct cli_state *cli, >+ const char *pathname, >+ NTSTATUS (*fn)(const char *, >+ struct file_info *, >+ const char *, >+ void *), >+ void *state); >+NTSTATUS cli_smb2_qpathinfo_basic(struct cli_state *cli, >+ const char *name, >+ SMB_STRUCT_STAT *sbuf, >+ uint32_t *attributes); >+NTSTATUS cli_smb2_qpathinfo_alt_name(struct cli_state *cli, >+ const char *name, >+ fstring alt_name); >+NTSTATUS cli_smb2_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 cli_smb2_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 cli_smb2_getatr(struct cli_state *cli, >+ const char *name, >+ uint16_t *attr, >+ off_t *size, >+ time_t *write_time); >+NTSTATUS cli_smb2_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 cli_smb2_qpathinfo_streams(struct cli_state *cli, >+ const char *name, >+ TALLOC_CTX *mem_ctx, >+ unsigned int *pnum_streams, >+ struct stream_struct **pstreams); >+NTSTATUS cli_smb2_setatr(struct cli_state *cli, >+ const char *fname, >+ uint16_t attr, >+ time_t mtime); >+NTSTATUS cli_smb2_setattrE(struct cli_state *cli, >+ uint16_t fnum, >+ time_t change_time, >+ time_t access_time, >+ time_t write_time); >+NTSTATUS cli_smb2_dskattr(struct cli_state *cli, >+ int *bsize, >+ int *total, >+ int *avail); >+NTSTATUS cli_smb2_query_security_descriptor(struct cli_state *cli, >+ uint16_t fnum, >+ uint32_t sec_info, >+ TALLOC_CTX *mem_ctx, >+ struct security_descriptor **ppsd); >+NTSTATUS cli_smb2_set_security_descriptor(struct cli_state *cli, >+ uint16_t fnum, >+ uint32_t sec_info, >+ const struct security_descriptor *sd); >+NTSTATUS cli_smb2_rename(struct cli_state *cli, >+ const char *fname_src, >+ const char *fname_dst); >+NTSTATUS cli_smb2_set_ea_fnum(struct cli_state *cli, >+ uint16_t fnum, >+ const char *ea_name, >+ const char *ea_val, >+ size_t ea_len); >+NTSTATUS cli_smb2_get_ea_list_path(struct cli_state *cli, >+ const char *name, >+ TALLOC_CTX *ctx, >+ size_t *pnum_eas, >+ struct ea_struct **pea_list); >+NTSTATUS cli_smb2_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 *cli_smb2_read_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cli_state *cli, >+ uint16_t fnum, >+ off_t offset, >+ size_t size); >+NTSTATUS cli_smb2_read_recv(struct tevent_req *req, >+ ssize_t *received, >+ uint8_t **rcvbuf); >+struct tevent_req *cli_smb2_write_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 cli_smb2_write_recv(struct tevent_req *req, >+ size_t *pwritten); >+struct tevent_req *cli_smb2_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 cli_smb2_writeall_recv(struct tevent_req *req, >+ size_t *pwritten); >+#endif /* __SMB2CLI_FNUM_H__ */ >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/libsmb.h b/source3/libsmb/libsmb.h >index 061f317..6df06ae 100644 >--- a/source3/libsmb/libsmb.h >+++ b/source3/libsmb/libsmb.h >@@ -26,5 +26,6 @@ > #include "client.h" > #include "libads/ads_status.h" > #include "libsmb/proto.h" >+#include "libsmb/cli_smb2_fnum.h" > > #endif /* _LIBSMB_LIBSMB_H */ >diff --git a/source3/wscript_build b/source3/wscript_build >index 0f4bac6..ff631a6 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/cli_smb2_fnum.c''' > > LIBMSRPC_SRC = ''' > rpc_client/cli_pipe.c >-- >1.7.9.5 > > >From 194edc770907a3ea7b2efc890b0dd7d36faf0d40 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 15:59:13 -0700 >Subject: [PATCH 27/57] s3:libsmb: Plumb cli_smb2_rename() inside > cli_rename(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit c748a959b40f184190cd537f0ad5f0772b484841) >--- > source3/libsmb/clifile.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 4b4e1a0..bfc3984 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1097,11 +1097,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 cli_smb2_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.7.9.5 > > >From 6462752feafd9aa0bf8a2ca45e1b1d0a189085fb Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:00:40 -0700 >Subject: [PATCH 28/57] s3:libsmb: Plumb cli_smb2_unlink() inside > cli_unlink(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 179c27dd0235c4949045eef2ffb7a87175a4483b) >--- > 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 bfc3984..f2e4ac2 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1415,11 +1415,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 cli_smb2_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.7.9.5 > > >From 04c17cd645196cc43d73078019269dae64be26c8 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:01:49 -0700 >Subject: [PATCH 29/57] s3:libsmb: Plumb cli_smb2_mkdir() inside cli_mkdir(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 46da267afd540fe2d31f1395cda9e2853cf6432a) >--- > 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 f2e4ac2..9659fc1 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1525,11 +1525,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 cli_smb2_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.7.9.5 > > >From 08cb0080eed01e0c1bb2557120e7d3df8e9b1c1f Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:03:00 -0700 >Subject: [PATCH 30/57] s3:libsmb: Plumb cli_smb2_rmdir() inside cli_rmdir(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 04d396566b90f32dc239450596ab50502f9cbb02) >--- > 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 9659fc1..d63734d 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1635,11 +1635,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 cli_smb2_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.7.9.5 > > >From deeb6fff172a28ad5bcaf98f1fe9c690b8db331d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:06:19 -0700 >Subject: [PATCH 31/57] s3:libsmb: Plumb cli_smb2_create_fnum() inside > cli_ntcreate(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit c1c4491d5e5bb16c274fe4fe162156a7ec910b93) >--- > 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 d63734d..3c799a6 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -1914,11 +1914,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 cli_smb2_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.7.9.5 > > >From f5dc4f193deb33a9bc4d065ac5407bed44a9c47d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:10:34 -0700 >Subject: [PATCH 32/57] s3:libsmb: Plumb cli_smb2_close_fnum() inside > cli_close(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 85f60cc3d8f68ce5eb687cc6e367bb66bdef8b99) >--- > 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 3c799a6..571e1cc 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -2536,11 +2536,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 cli_smb2_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.7.9.5 > > >From ec7b4f14405d562ea737192dc22032028b375211 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:11:59 -0700 >Subject: [PATCH 33/57] s3:libsmb: Plumb cli_smb2_getattrE() inside > cli_getattrE(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 0bbc0446210fa504f9834de948c4d066df752666) >--- > 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 571e1cc..e3fb62d 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3379,11 +3379,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 cli_smb2_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.7.9.5 > > >From 424dadf24144948b273d7d8bf07ddbf7d02099f0 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:14:47 -0700 >Subject: [PATCH 34/57] s3:libsmb: Plumb cli_smb2_setattrE() inside > cli_setattrE(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 83c410c99e3ef8db00dd002c1a1a93b0035cd2e7) >--- > 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 e3fb62d..d0e9bb6 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3647,11 +3647,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 cli_smb2_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.7.9.5 > > >From 795635cce3f6cc8430523fd487a5b6cd022aca64 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:16:03 -0700 >Subject: [PATCH 35/57] s3:libsmb: Plumb cli_smb2_setatr() inside > cli_setatr(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit ea267a7e4b4c413336b2bf54eb53ffc8d1524b44) >--- > 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 d0e9bb6..4ac7313 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3786,11 +3786,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 cli_smb2_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.7.9.5 > > >From 99399b754ceb51f926cb7240b85a438f5dccfc47 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 14 Aug 2013 14:37:11 -0700 >Subject: [PATCH 36/57] s3:libsmb: Plumb cli_smb2_getatr() inside > cli_getatr(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 75d2e18502ccb811c018535f3c5c7325bdf5e613) >--- > 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 4ac7313..f674118 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -3538,11 +3538,21 @@ NTSTATUS cli_getatr(struct cli_state *cli, > off_t *size, > 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 cli_smb2_getatr(cli, >+ fname, >+ attr, >+ size, >+ 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.7.9.5 > > >From 674ec2d995df833448b12c1414b8e27768d13166 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:17:12 -0700 >Subject: [PATCH 37/57] s3:libsmb: Plumb cli_smb2_dskattr() inside > cli_dskattr(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit c6ed0b88312d7e231749a09a87944caea4c9808e) >--- > 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 f674118..77796d8 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4034,11 +4034,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 cli_smb2_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.7.9.5 > > >From 68d79dfb92b6dbc234a604ea1e5a885cc5d807c3 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:19:06 -0700 >Subject: [PATCH 38/57] s3:libsmb: Fix cli_set_ea_path() to use frame instead > of talloc_tos(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit c1aeada4dd1f165eb33354c5a4323ed1ebf453a9) >--- > 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 77796d8..5cd1ff2 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4322,9 +4322,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); >@@ -4337,7 +4338,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.7.9.5 > > >From ac8cb980aa70eb75afb16934c64d91c4e21a5684 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:21:48 -0700 >Subject: [PATCH 39/57] s3:libsmb: Plumb cli_smb2_set_ea_path() inside > cli_set_ea_path(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 3276853e59c2686873baad7c6f9d2665ed6fdd56) >--- > 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 5cd1ff2..2cfe7cd 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4320,7 +4320,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 cli_smb2_set_ea_path(cli, >+ path, >+ ea_name, >+ ea_val, >+ ea_len); >+ } >+ >+ frame = talloc_stackframe(); > > param = talloc_array(frame, uint8_t, 6); > if (!param) { >-- >1.7.9.5 > > >From f2c5239ad21fc9584afcbcccc20c27c6f9987708 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:32:55 -0700 >Subject: [PATCH 40/57] s3:libsmb: Plumb cli_smb2_set_ea_fnum() inside > cli_set_ea_fnum(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f8dfc50124e5b5083aa801d9658389dd3fa6698a) >--- > source3/libsmb/clifile.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c >index 2cfe7cd..d186112 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4365,6 +4365,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 cli_smb2_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.7.9.5 > > >From 5188a6e8889ddcc7d8f6a0f32061aa1f931d21d1 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:42:02 -0700 >Subject: [PATCH 41/57] s3:libsmb: Plumb cli_smb2_get_ea_list_path() inside > cli_get_ea_list_path(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 7e2d969deb1d4bcf3add422d80852b2d386cfaac) >--- > 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 d186112..424354b 100644 >--- a/source3/libsmb/clifile.c >+++ b/source3/libsmb/clifile.c >@@ -4554,11 +4554,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 cli_smb2_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.7.9.5 > > >From d839ebdd064f146f088e5632346e7e4268b6b3ce Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:43:33 -0700 >Subject: [PATCH 42/57] s3:libsmb: Plumb cli_smb2_list() inside cli_list(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 73255d3ba912b3a112f9d766deae895f51e16cd9) >--- > source3/libsmb/clilist.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c >index b0d3a4e..ed970cd 100644 >--- a/source3/libsmb/clilist.c >+++ b/source3/libsmb/clilist.c >@@ -933,7 +933,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 +941,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 cli_smb2_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.7.9.5 > > >From 1415c0f9544f66d2fd2493de557fe8ac645b8930 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:45:05 -0700 >Subject: [PATCH 43/57] s3:libsmb: Plumb cli_smb2_qpathinfo2() inside > cli_qpathinfo2(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f2f566b1cc8d55bd1cf93478b877a3e7f455855c) >--- > source3/libsmb/clirap.c | 16 +++++++++++++++- > 1 file changed, 15 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 12a340c..41608dd 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -845,11 +845,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 cli_smb2_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.7.9.5 > > >From c55396516b96926cf18e69536b42cdbac92d18d4 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:46:05 -0700 >Subject: [PATCH 44/57] s3:libsmb: Plumb cli_smb2_qpathinfo_streams() inside > cli_qpathinfo_streams(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit e96309ca1b057d430444531523bb2c9f59fcd624) >--- > 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 41608dd..bb4f334 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -965,11 +965,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 cli_smb2_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.7.9.5 > > >From 9be3ae4fc5ad1c3659531403428ef99bdacd468f Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:47:21 -0700 >Subject: [PATCH 45/57] s3:libsmb: Plumb cli_smb2_qfileinfo_basic() inside > cli_qfileinfo_basic(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 2bb3e251d59910d9bf527a73271094702bceefe2) >--- > source3/libsmb/clirap.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index bb4f334..06dea82 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -1149,6 +1149,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 cli_smb2_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.7.9.5 > > >From 0bf83c88be3824c402a08129e2dcb3fe4d0dd8c8 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 10:52:02 -0700 >Subject: [PATCH 46/57] s3:libsmb: Plumb cli_smb2_qpathinfo_basic() inside > cli_qpathinfo_basic(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit cba3ed0466b8598e28a44809778b99e97b1bf1a1) >--- > 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 06dea82..7a480d6 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -1275,11 +1275,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 cli_smb2_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.7.9.5 > > >From fbe9f3258d5ade4fa4338a45128928844b5cddfb Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 7 Aug 2013 16:50:03 -0700 >Subject: [PATCH 47/57] s3:libsmb: Plumb cli_smb2_qpathinfo_alt_name() inside > cli_qpathinfo_alt_name(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit de895bf228432f2a42bcdcadcf12ffd1be64022f) >--- > source3/libsmb/clirap.c | 6 ++++++ > 1 file changed, 6 insertions(+) > >diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c >index 7a480d6..d6d2fae 100644 >--- a/source3/libsmb/clirap.c >+++ b/source3/libsmb/clirap.c >@@ -1326,6 +1326,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 cli_smb2_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.7.9.5 > > >From a5f92614aa5636b7ec27f9a0c28b0e709a6b30f2 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:00:08 -0700 >Subject: [PATCH 48/57] s3:libsmb: Plumb cli_smb2_query_security_descriptor() > inside cli_query_security_descriptor(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 1db7e90451f31d75298508c19a859d98d56d7e7c) >--- > source3/libsmb/clisecdesc.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > >diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c >index 24da39d..a82feab 100644 >--- a/source3/libsmb/clisecdesc.c >+++ b/source3/libsmb/clisecdesc.c >@@ -20,6 +20,7 @@ > #include "includes.h" > #include "libsmb/libsmb.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 +34,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 cli_smb2_query_security_descriptor(cli, >+ fnum, >+ sec_info, >+ mem_ctx, >+ sd); >+ } >+ > SIVAL(param, 0, fnum); > SIVAL(param, 4, sec_info); > >-- >1.7.9.5 > > >From 85df78206643f67ca599173036e2220bd389a46f Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 8 Aug 2013 11:00:49 -0700 >Subject: [PATCH 49/57] s3:libsmb: Plumb cli_smb2_set_security_descriptor() > inside cli_set_security_descriptor(). > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 80758e4b07c87280e778ba161c2c9c4a2ee47853) >--- > source3/libsmb/clisecdesc.c | 7 +++++++ > 1 file changed, 7 insertions(+) > >diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c >index a82feab..986610f 100644 >--- a/source3/libsmb/clisecdesc.c >+++ b/source3/libsmb/clisecdesc.c >@@ -104,6 +104,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 cli_smb2_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.7.9.5 > > >From 66cc4267cbc397d2b9af33491d27e78fc836c259 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 16:33:30 +0200 >Subject: [PATCH 50/57] s3:libsmb: add SMB2 support to cli_push* > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 6896bf0b28a07eb8ead5b3bd2bc50229aa59d439) >--- > source3/libsmb/clireadwrite.c | 66 +++++++++++++++++++++++++++++++---------- > 1 file changed, 50 insertions(+), 16 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index 10dc79b..821bcb1 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -1120,7 +1120,11 @@ struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, > state->priv = priv; > state->next_offset = start_offset; > >- state->chunk_size = cli_write_max_bufsize(cli, mode, 14); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ state->chunk_size = smb2cli_conn_max_write_size(cli->conn); >+ } else { >+ state->chunk_size = cli_write_max_bufsize(cli, mode, 14); >+ } > if (state->chunk_size > page_size) { > state->chunk_size &= ~(page_size - 1); > } >@@ -1257,21 +1261,47 @@ static void cli_push_chunk_ship(struct cli_push_chunk *chunk) > ofs = chunk->ofs + chunk->tmp_size; > size = chunk->total_size - chunk->tmp_size; > >- ok = smb1cli_conn_req_possible(state->cli->conn); >- if (!ok) { >- return; >- } >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ uint32_t max_size; > >- chunk->subreq = cli_write_andx_send(chunk, >- state->ev, >- state->cli, >- state->fnum, >- state->mode, >- buf, >- ofs, >- size); >- if (tevent_req_nomem(chunk->subreq, req)) { >- return; >+ ok = smb2cli_conn_req_possible(state->cli->conn, &max_size); >+ if (!ok) { >+ return; >+ } >+ >+ /* >+ * downgrade depending on the available credits >+ */ >+ size = MIN(max_size, size); >+ >+ chunk->subreq = cli_smb2_write_send(chunk, >+ state->ev, >+ state->cli, >+ state->fnum, >+ state->mode, >+ buf, >+ ofs, >+ size); >+ if (tevent_req_nomem(chunk->subreq, req)) { >+ return; >+ } >+ } else { >+ ok = smb1cli_conn_req_possible(state->cli->conn); >+ if (!ok) { >+ return; >+ } >+ >+ chunk->subreq = cli_write_andx_send(chunk, >+ state->ev, >+ state->cli, >+ state->fnum, >+ state->mode, >+ buf, >+ ofs, >+ size); >+ if (tevent_req_nomem(chunk->subreq, req)) { >+ return; >+ } > } > tevent_req_set_callback(chunk->subreq, > cli_push_chunk_done, >@@ -1296,7 +1326,11 @@ static void cli_push_chunk_done(struct tevent_req *subreq) > > chunk->subreq = NULL; > >- status = cli_write_andx_recv(subreq, &written); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ status = cli_smb2_write_recv(subreq, &written); >+ } else { >+ status = cli_write_andx_recv(subreq, &written); >+ } > TALLOC_FREE(subreq); > if (tevent_req_nterror(req, status)) { > return; >-- >1.7.9.5 > > >From 73753e144469a2ec840670e6a94808b79edbe28f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 18:20:08 +0200 >Subject: [PATCH 51/57] s3:libsmb: add SMB2 support to cli_pull* > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit a85d4511e6bc84938d60f090b44a5b1468ee4136) >--- > source3/libsmb/clireadwrite.c | 60 +++++++++++++++++++++++++++++++---------- > 1 file changed, 46 insertions(+), 14 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index 821bcb1..d28c226 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -360,7 +360,11 @@ struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx, > return tevent_req_post(req, ev); > } > >- state->chunk_size = cli_read_max_bufsize(cli); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ state->chunk_size = smb2cli_conn_max_read_size(cli->conn); >+ } else { >+ state->chunk_size = cli_read_max_bufsize(cli); >+ } > if (state->chunk_size > page_size) { > state->chunk_size &= ~(page_size - 1); > } >@@ -519,19 +523,43 @@ static void cli_pull_chunk_ship(struct cli_pull_chunk *chunk) > ofs = chunk->ofs + chunk->tmp_size; > size = chunk->total_size - chunk->tmp_size; > >- ok = smb1cli_conn_req_possible(state->cli->conn); >- if (!ok) { >- return; >- } >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ uint32_t max_size; > >- chunk->subreq = cli_read_andx_send(chunk, >- state->ev, >- state->cli, >- state->fnum, >- ofs, >- size); >- if (tevent_req_nomem(chunk->subreq, req)) { >- return; >+ ok = smb2cli_conn_req_possible(state->cli->conn, &max_size); >+ if (!ok) { >+ return; >+ } >+ >+ /* >+ * downgrade depending on the available credits >+ */ >+ size = MIN(max_size, size); >+ >+ chunk->subreq = cli_smb2_read_send(chunk, >+ state->ev, >+ state->cli, >+ state->fnum, >+ ofs, >+ size); >+ if (tevent_req_nomem(chunk->subreq, req)) { >+ return; >+ } >+ } else { >+ ok = smb1cli_conn_req_possible(state->cli->conn); >+ if (!ok) { >+ return; >+ } >+ >+ chunk->subreq = cli_read_andx_send(chunk, >+ state->ev, >+ state->cli, >+ state->fnum, >+ ofs, >+ size); >+ if (tevent_req_nomem(chunk->subreq, req)) { >+ return; >+ } > } > tevent_req_set_callback(chunk->subreq, > cli_pull_chunk_done, >@@ -557,7 +585,11 @@ static void cli_pull_chunk_done(struct tevent_req *subreq) > > chunk->subreq = NULL; > >- status = cli_read_andx_recv(subreq, &received, &buf); >+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { >+ status = cli_smb2_read_recv(subreq, &received, &buf); >+ } else { >+ status = cli_read_andx_recv(subreq, &received, &buf); >+ } > if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { > received = 0; > status = NT_STATUS_OK; >-- >1.7.9.5 > > >From 044cb3becf763fb8e513f0a6a854f69ebcf39392 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Aug 2013 18:38:57 +0200 >Subject: [PATCH 52/57] s3:libsmb: add support for SMB2 in cli_writeall() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ccf7b3719121e03ed06d15b9af5373eecba3e828) >--- > source3/libsmb/clireadwrite.c | 14 ++++++++++++-- > 1 file changed, 12 insertions(+), 2 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index d28c226..adcd98b 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -1066,7 +1066,13 @@ 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 = cli_smb2_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; > } >@@ -1074,7 +1080,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 = cli_smb2_writeall_recv(req, pwritten); >+ } else { >+ status = cli_writeall_recv(req, pwritten); >+ } > fail: > TALLOC_FREE(frame); > return status; >-- >1.7.9.5 > > >From 426497ffe18b376a72509238dcc38ee7ecd44662 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 11:38:22 +0200 >Subject: [PATCH 53/57] s3:libsmb: make cli_tdis_send/recv static > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 80d4f64352c0ddacb9ee15d2b48a42a0b7929501) >--- > source3/libsmb/cliconnect.c | 4 ++-- > source3/libsmb/proto.h | 4 ---- > 2 files changed, 2 insertions(+), 6 deletions(-) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index d74ea0e..98b3bf1 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -2757,7 +2757,7 @@ struct cli_tdis_state { > > static void cli_tdis_done(struct tevent_req *subreq); > >-struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx, >+static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct cli_state *cli) > { >@@ -2796,7 +2796,7 @@ static void cli_tdis_done(struct tevent_req *subreq) > tevent_req_done(req); > } > >-NTSTATUS cli_tdis_recv(struct tevent_req *req) >+static NTSTATUS cli_tdis_recv(struct tevent_req *req) > { > return tevent_req_simple_recv_ntstatus(req); > } >diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h >index 48496c8..648bdda 100644 >--- a/source3/libsmb/proto.h >+++ b/source3/libsmb/proto.h >@@ -75,10 +75,6 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, > const char *dev, const char *pass, int passlen); > NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share, > const char *dev, const char *pass, int passlen); >-struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx, >- struct tevent_context *ev, >- struct cli_state *cli); >-NTSTATUS cli_tdis_recv(struct tevent_req *req); > NTSTATUS cli_tdis(struct cli_state *cli); > NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss, > uint16_t port, int name_type, const char *myname, >-- >1.7.9.5 > > >From 35dea645add3c27244177150a49767e416cc0f46 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 11:44:10 +0200 >Subject: [PATCH 54/57] s3:libsmb: only set tcon to invalid in smb2cli_tdis* > >This matches the behavior of cli_tdis*. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit d732e9aab3bbad3ea97f8b120e57b41152aaee3b) >--- > source3/libsmb/smb2cli_tcon.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/libsmb/smb2cli_tcon.c b/source3/libsmb/smb2cli_tcon.c >index b3136fa..2467ce5 100644 >--- a/source3/libsmb/smb2cli_tcon.c >+++ b/source3/libsmb/smb2cli_tcon.c >@@ -243,7 +243,8 @@ static void smb2cli_tdis_done(struct tevent_req *subreq) > if (tevent_req_nterror(req, status)) { > return; > } >- TALLOC_FREE(state->cli->smb2.tcon); >+ smb2cli_tcon_set_values(state->cli->smb2.tcon, NULL, >+ UINT32_MAX, 0, 0, 0, 0); > tevent_req_done(req); > } > >-- >1.7.9.5 > > >From cd7d8bbbf51d521eb72c57945041212379c4dd02 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 11:44:58 +0200 >Subject: [PATCH 55/57] s3:libsmb: call smb2cli_tdis() from cli_tdis() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit e6be68fb5e4dc528f7365f3413b9b66090992f42) >--- > source3/libsmb/cliconnect.c | 4 ++++ > 1 file changed, 4 insertions(+) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index 98b3bf1..0e5f8a9 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -2807,6 +2807,10 @@ NTSTATUS cli_tdis(struct cli_state *cli) > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ return smb2cli_tdis(cli); >+ } >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > return NT_STATUS_INVALID_PARAMETER; > } >-- >1.7.9.5 > > >From 339636d7ad7e0b18f3a54b1a8ff60ffe1464dd02 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 11:48:40 +0200 >Subject: [PATCH 56/57] s3:libsmb: make cli_ulogoff_send/recv static > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 1d7bdfc4feac35d92b003c3c78f502897ecc5d4e) >--- > source3/libsmb/cliconnect.c | 4 ++-- > source3/libsmb/proto.h | 4 ---- > 2 files changed, 2 insertions(+), 6 deletions(-) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index 0e5f8a9..f64f37e 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -2245,7 +2245,7 @@ struct cli_ulogoff_state { > > static void cli_ulogoff_done(struct tevent_req *subreq); > >-struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx, >+static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct cli_state *cli) > { >@@ -2288,7 +2288,7 @@ static void cli_ulogoff_done(struct tevent_req *subreq) > tevent_req_done(req); > } > >-NTSTATUS cli_ulogoff_recv(struct tevent_req *req) >+static NTSTATUS cli_ulogoff_recv(struct tevent_req *req) > { > return tevent_req_simple_recv_ntstatus(req); > } >diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h >index 648bdda..a1389ff 100644 >--- a/source3/libsmb/proto.h >+++ b/source3/libsmb/proto.h >@@ -54,10 +54,6 @@ struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct cli_state *cli); > NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req); >-struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx, >- struct tevent_context *ev, >- struct cli_state *cli); >-NTSTATUS cli_ulogoff_recv(struct tevent_req *req); > NTSTATUS cli_ulogoff(struct cli_state *cli); > struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >-- >1.7.9.5 > > >From 98b3da44f057bfa6c29eadf9be4dbe3e2ad1cf5c Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Aug 2013 15:18:47 -0700 >Subject: [PATCH 57/57] s3:libsmb: call smb2cli_logoff() from cli_ulogoff() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Thu Aug 15 10:53:21 CEST 2013 on sn-devel-104 >(cherry picked from commit b706ca6e55aa76d4da901c69d991969602facc3b) >--- > source3/libsmb/cliconnect.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > >diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c >index f64f37e..7ec3b56 100644 >--- a/source3/libsmb/cliconnect.c >+++ b/source3/libsmb/cliconnect.c >@@ -2299,6 +2299,18 @@ NTSTATUS cli_ulogoff(struct cli_state *cli) > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { >+ status = smb2cli_logoff(cli->conn, >+ cli->timeout, >+ cli->smb2.session); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ smb2cli_session_set_id_and_flags(cli->smb2.session, >+ UINT64_MAX, 0); >+ return NT_STATUS_OK; >+ } >+ > if (smbXcli_conn_has_async_calls(cli->conn)) { > return NT_STATUS_INVALID_PARAMETER; > } >-- >1.7.9.5 >
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
Flags:
jra
:
review+
Actions:
View
Attachments on
bug 9974
:
9014
|
9123
|
9135
|
9136
|
9139
|
9148
|
9159