[PATCH] Fix bug #Bug 12831 - smbcacls got error NT_STATUS_NETWORK_NAME_DELETED

Jeremy Allison jra at samba.org
Wed Jun 14 15:50:57 UTC 2017


It turns out that smbclient, smbcacls and smbtorture3 depend
on the ability to temporarily replace the client tcon connection
struct internally to the client with a new connection to IPC$,
do some calls on that new connection (usually lookupnames/lookupsids),
then replace the old values of the tcon and continue.

This has some problems. (a). It only works for SMB1 (for SMB2 we
overwrote the tcon pointer) and (b). It didn't really work for SMB1
either - we ended up with a bastardized cli->smb1.tcon pointer that
contains type and string from the IPC$ connection whilst being
connected to the share connection. We only got away with this
due to the fact we don't use the type and string for anything
on the wire.

This patch unifies the cli->smb[1|2].tcon pointer handling and
allows temporary replacement of the pointer, and also SMB2 access
to the get/set the 32-bit tid value.

Most of this patch is fixing up the smbclient/smbcacls/smbtorture3
code so everything keeps working with make test, so I know this
is being tested (it took me a day or so to keep all our tests
passing :-).

Please review and push if you're happy !

Cheers,

	Jeremy.
-------------- next part --------------
>From 53ca9dc795733551a8b4cc9b7842cd2dd44087ac Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:06:22 -0700
Subject: [PATCH 1/8] libcli: smb: Add smbXcli_tcon_copy().

Makes a deep copy of a struct smbXcli_tcon *, will
be used later.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/smb/smbXcli_base.c | 32 ++++++++++++++++++++++++++++++++
 libcli/smb/smbXcli_base.h |  2 ++
 2 files changed, 34 insertions(+)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 1ec11a9dec4..ee25e369b80 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -6099,6 +6099,38 @@ struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx)
 	return tcon;
 }
 
+/*
+ * Return a deep structure copy of a struct smbXcli_tcon *
+ */
+
+struct smbXcli_tcon *smbXcli_tcon_copy(TALLOC_CTX *mem_ctx,
+				const struct smbXcli_tcon *tcon_in)
+{
+	struct smbXcli_tcon *tcon;
+
+	tcon = talloc_memdup(mem_ctx, tcon_in, sizeof(struct smbXcli_tcon));
+	if (tcon == NULL) {
+		return NULL;
+	}
+
+	/* Deal with the SMB1 strings. */
+	if (tcon_in->smb1.service != NULL) {
+		tcon->smb1.service = talloc_strdup(tcon, tcon_in->smb1.service);
+		if (tcon->smb1.service == NULL) {
+			TALLOC_FREE(tcon);
+			return NULL;
+		}
+	}
+	if (tcon->smb1.fs_type != NULL) {
+		tcon->smb1.fs_type = talloc_strdup(tcon, tcon_in->smb1.fs_type);
+		if (tcon->smb1.fs_type == NULL) {
+			TALLOC_FREE(tcon);
+			return NULL;
+		}
+	}
+	return tcon;
+}
+
 void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon,
 				    uint32_t fs_attributes)
 {
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index 1abeb2b180b..7b83b1a7bc8 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -501,6 +501,8 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
 NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session);
 
 struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx);
+struct smbXcli_tcon *smbXcli_tcon_copy(TALLOC_CTX *mem_ctx,
+				const struct smbXcli_tcon *tcon_in);
 void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon,
 				    uint32_t fs_attributes);
 uint32_t smbXcli_tcon_get_fs_attributes(struct smbXcli_tcon *tcon);
-- 
2.13.1.508.gb3defc5cc-goog


>From b72281410da0092db647dd7f6299e5da549e7f30 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:08:22 -0700
Subject: [PATCH 2/8] libcli: smb: Add smb2cli_tcon_set_id().

Will be used in test and client code.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/smb/smbXcli_base.c | 5 +++++
 libcli/smb/smbXcli_base.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index ee25e369b80..31319a34981 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -6209,6 +6209,11 @@ uint32_t smb2cli_tcon_current_id(struct smbXcli_tcon *tcon)
 	return tcon->smb2.tcon_id;
 }
 
+void smb2cli_tcon_set_id(struct smbXcli_tcon *tcon, uint32_t tcon_id)
+{
+	tcon->smb2.tcon_id = tcon_id;
+}
+
 uint32_t smb2cli_tcon_capabilities(struct smbXcli_tcon *tcon)
 {
 	return tcon->smb2.capabilities;
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index 7b83b1a7bc8..52fec9a5044 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -517,6 +517,7 @@ bool smb1cli_tcon_set_values(struct smbXcli_tcon *tcon,
 			     const char *service,
 			     const char *fs_type);
 uint32_t smb2cli_tcon_current_id(struct smbXcli_tcon *tcon);
+void smb2cli_tcon_set_id(struct smbXcli_tcon *tcon, uint32_t tcon_id);
 uint32_t smb2cli_tcon_capabilities(struct smbXcli_tcon *tcon);
 uint32_t smb2cli_tcon_flags(struct smbXcli_tcon *tcon);
 void smb2cli_tcon_set_values(struct smbXcli_tcon *tcon,
-- 
2.13.1.508.gb3defc5cc-goog


>From 9afc8edc08898c7b30aefaf74c229ad4a3246d7d Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:15:00 -0700
Subject: [PATCH 3/8] s3: libsmb: Add cli_state_save_tcon() /
 cli_state_restore_tcon().

Save and restore tcon pointers in smb1 or smb2 structs.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/libsmb/clientgen.c | 20 ++++++++++++++++++++
 source3/libsmb/proto.h     |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index bc5c1b1ce3c..1aea4cf247e 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -362,6 +362,26 @@ uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid)
 	return ret;
 }
 
+struct smbXcli_tcon *cli_state_save_tcon(struct cli_state *cli)
+{
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		return smbXcli_tcon_copy(cli, cli->smb2.tcon);
+	} else {
+		return smbXcli_tcon_copy(cli, cli->smb1.tcon);
+	}
+}
+
+void cli_state_restore_tcon(struct cli_state *cli, struct smbXcli_tcon *tcon)
+{
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		TALLOC_FREE(cli->smb2.tcon);
+		cli->smb2.tcon = tcon;
+	} else {
+		TALLOC_FREE(cli->smb1.tcon);
+		cli->smb1.tcon = tcon;
+	}
+}
+
 uint16_t cli_state_get_uid(struct cli_state *cli)
 {
 	return smb1cli_session_current_id(cli->smb1.session);
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 137c3554771..3d545024d98 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -196,6 +196,9 @@ uint32_t cli_getpid(struct cli_state *cli);
 bool cli_state_has_tcon(struct cli_state *cli);
 uint16_t cli_state_get_tid(struct cli_state *cli);
 uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid);
+struct smbXcli_tcon;
+struct smbXcli_tcon *cli_state_save_tcon(struct cli_state *cli);
+void cli_state_restore_tcon(struct cli_state *cli, struct smbXcli_tcon *tcon);
 uint16_t cli_state_get_uid(struct cli_state *cli);
 uint16_t cli_state_set_uid(struct cli_state *cli, uint16_t uid);
 bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive);
-- 
2.13.1.508.gb3defc5cc-goog


>From 72245a240e1d1658c2cfee12f860f23879513054 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:25:25 -0700
Subject: [PATCH 4/8] s3: smbtorture: Show correct use of cli_state_save_tcon()
 / cli_state_restore_tcon().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/torture/test_smb2.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c
index c0d11e61087..9368ab3264d 100644
--- a/source3/torture/test_smb2.c
+++ b/source3/torture/test_smb2.c
@@ -170,7 +170,10 @@ bool run_smb2_basic(int dummy)
 	}
 
 	saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
-	saved_tcon = cli->smb2.tcon;
+	saved_tcon = cli_state_save_tcon(cli);
+	if (saved_tcon == NULL) {
+		return false;
+	}
 	cli->smb2.tcon = smbXcli_tcon_create(cli);
 	smb2cli_tcon_set_values(cli->smb2.tcon,
 				NULL, /* session */
@@ -187,8 +190,7 @@ bool run_smb2_basic(int dummy)
 		printf("smb2cli_tdis returned %s\n", nt_errstr(status));
 		return false;
 	}
-	talloc_free(cli->smb2.tcon);
-	cli->smb2.tcon = saved_tcon;
+	cli_state_restore_tcon(cli, saved_tcon);
 
 	status = smb2cli_tdis(cli->conn,
 			      cli->timeout,
-- 
2.13.1.508.gb3defc5cc-goog


>From 774f1d5cc1e39007bf4266d97637b78ea79e387e Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:26:00 -0700
Subject: [PATCH 5/8] s3: libsmb: Widen cli_state_get_tid() /
 cli_state_set_tid() to 32-bits.

Copes with SMB2 connections.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/client/client.c    |  5 ++++-
 source3/lib/util_sd.c      |  4 ++--
 source3/libsmb/clidfs.c    |  2 +-
 source3/libsmb/clientgen.c | 22 ++++++++++++++++------
 source3/libsmb/proto.h     |  4 ++--
 source3/torture/torture.c  |  8 ++++----
 6 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/source3/client/client.c b/source3/client/client.c
index 64647365dc4..3285240d404 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -4712,7 +4712,10 @@ static int cmd_tid(void)
 			d_printf("no tcon currently\n");
 		}
 	} else {
-		uint16_t tid = atoi(tid_str);
+		uint32_t tid = atoi(tid_str);
+		if (!cli_state_has_tcon(cli)) {
+			d_printf("no tcon currently\n");
+		}
 		cli_state_set_tid(cli, tid);
 	}
 
diff --git a/source3/lib/util_sd.c b/source3/lib/util_sd.c
index d79fe79b94b..a95cafd5f7a 100644
--- a/source3/lib/util_sd.c
+++ b/source3/lib/util_sd.c
@@ -84,7 +84,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
 				   enum lsa_SidType *type,
 				   char **domain, char **name)
 {
-	uint16_t orig_cnum = cli_state_get_tid(cli);
+	uint32_t orig_cnum = cli_state_get_tid(cli);
 	struct rpc_pipe_client *p = NULL;
 	struct policy_handle handle;
 	NTSTATUS status;
@@ -165,7 +165,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
 				    enum lsa_SidType *type,
 				    struct dom_sid *sid)
 {
-	uint16_t orig_cnum = cli_state_get_tid(cli);
+	uint32_t orig_cnum = cli_state_get_tid(cli);
 	struct rpc_pipe_client *p;
 	struct policy_handle handle;
 	NTSTATUS status;
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index c477d7c6a46..1010e1b5c28 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -1205,7 +1205,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 	size_t consumed = 0;
 	char *fullpath = NULL;
 	bool res;
-	uint16_t cnum;
+	uint32_t cnum;
 	char *newextrapath = NULL;
 	NTSTATUS status;
 	const char *remote_name;
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 1aea4cf247e..25f72991956 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -341,7 +341,7 @@ uint32_t cli_getpid(struct cli_state *cli)
 
 bool cli_state_has_tcon(struct cli_state *cli)
 {
-	uint16_t tid = cli_state_get_tid(cli);
+	uint32_t tid = cli_state_get_tid(cli);
 
 	if (tid == UINT16_MAX) {
 		return false;
@@ -350,15 +350,25 @@ bool cli_state_has_tcon(struct cli_state *cli)
 	return true;
 }
 
-uint16_t cli_state_get_tid(struct cli_state *cli)
+uint32_t cli_state_get_tid(struct cli_state *cli)
 {
-	return smb1cli_tcon_current_id(cli->smb1.tcon);
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		return smb2cli_tcon_current_id(cli->smb2.tcon);
+	} else {
+		return (uint32_t)smb1cli_tcon_current_id(cli->smb1.tcon);
+	}
 }
 
-uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid)
+uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid)
 {
-	uint16_t ret = smb1cli_tcon_current_id(cli->smb1.tcon);
-	smb1cli_tcon_set_id(cli->smb1.tcon, tid);
+	uint32_t ret;
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		ret = smb2cli_tcon_current_id(cli->smb2.tcon);
+		smb2cli_tcon_set_id(cli->smb1.tcon, tid);
+	} else {
+		ret = smb1cli_tcon_current_id(cli->smb1.tcon);
+		smb1cli_tcon_set_id(cli->smb1.tcon, tid);
+	}
 	return ret;
 }
 
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 3d545024d98..6728c97664c 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -194,8 +194,8 @@ uint16_t cli_state_get_vc_num(struct cli_state *cli);
 uint32_t cli_setpid(struct cli_state *cli, uint32_t pid);
 uint32_t cli_getpid(struct cli_state *cli);
 bool cli_state_has_tcon(struct cli_state *cli);
-uint16_t cli_state_get_tid(struct cli_state *cli);
-uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid);
+uint32_t cli_state_get_tid(struct cli_state *cli);
+uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid);
 struct smbXcli_tcon;
 struct smbXcli_tcon *cli_state_save_tcon(struct cli_state *cli);
 void cli_state_restore_tcon(struct cli_state *cli, struct smbXcli_tcon *tcon);
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index bdcf1e13f17..58f0ce0a31f 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -1301,7 +1301,7 @@ static bool run_tcon_test(int dummy)
 	static struct cli_state *cli;
 	const char *fname = "\\tcontest.tmp";
 	uint16_t fnum1;
-	uint16_t cnum1, cnum2, cnum3;
+	uint32_t cnum1, cnum2, cnum3;
 	uint16_t vuid1, vuid2;
 	char buf[4];
 	bool ret = True;
@@ -2764,8 +2764,8 @@ static bool run_fdsesstest(int dummy)
 	struct cli_state *cli;
 	uint16_t new_vuid;
 	uint16_t saved_vuid;
-	uint16_t new_cnum;
-	uint16_t saved_cnum;
+	uint32_t new_cnum;
+	uint32_t saved_cnum;
 	const char *fname = "\\fdsess.tst";
 	const char *fname1 = "\\fdsess1.tst";
 	uint16_t fnum1;
@@ -9015,7 +9015,7 @@ static bool run_uid_regression_test(int dummy)
 {
 	static struct cli_state *cli;
 	int16_t old_vuid;
-	int16_t old_cnum;
+	int32_t old_cnum;
 	bool correct = True;
 	NTSTATUS status;
 
-- 
2.13.1.508.gb3defc5cc-goog


>From 344d065a9c0604dbba902b6657aaedbd6b8cc5b0 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:36:54 -0700
Subject: [PATCH 6/8] s3: libsmb: Fix cli_state_has_tcon() to cope with SMB2
 connections.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/libsmb/clientgen.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 25f72991956..4541763ea3f 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -341,12 +341,24 @@ uint32_t cli_getpid(struct cli_state *cli)
 
 bool cli_state_has_tcon(struct cli_state *cli)
 {
-	uint32_t tid = cli_state_get_tid(cli);
-
-	if (tid == UINT16_MAX) {
-		return false;
+	uint32_t tid;
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		if (cli->smb2.tcon == NULL) {
+			return false;
+		}
+		tid = cli_state_get_tid(cli);
+		if (tid == UINT32_MAX) {
+			return false;
+		}
+	} else {
+		if (cli->smb1.tcon == NULL) {
+			return false;
+		}
+		tid = cli_state_get_tid(cli);
+		if (tid == UINT16_MAX) {
+			return false;
+		}
 	}
-
 	return true;
 }
 
-- 
2.13.1.508.gb3defc5cc-goog


>From 675678e98fade2ecd852f1263889fcb306f231fc Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:37:39 -0700
Subject: [PATCH 7/8] s3: libsmb: Correctly do lifecycle management on
 cli->smb1.tcon and cli->smb2.tcon.

Treat them identically. Create them on demand after for a tcon call,
and delete them on a tdis call.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/libsmb/cliconnect.c | 23 +++++++++++++++++++++--
 source3/libsmb/clientgen.c  |  5 -----
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 200657aff09..3fa80a2ec36 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1948,6 +1948,13 @@ struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
 	state->cli = cli;
 	vwv = state->vwv;
 
+	TALLOC_FREE(cli->smb1.tcon);
+	cli->smb1.tcon = smbXcli_tcon_create(cli);
+	if (tevent_req_nomem(cli->smb1.tcon, req)) {
+		return tevent_req_post(req, ev);
+	}
+	smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
+
 	cli->share = talloc_strdup(cli, share);
 	if (!cli->share) {
 		return NULL;
@@ -2257,6 +2264,7 @@ static struct tevent_req *cli_tree_connect_send(
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
 		char *unc;
 
+		TALLOC_FREE(cli->smb2.tcon);
 		cli->smb2.tcon = smbXcli_tcon_create(cli);
 		if (tevent_req_nomem(cli->smb2.tcon, req)) {
 			return tevent_req_post(req, ev);
@@ -2429,7 +2437,7 @@ static void cli_tdis_done(struct tevent_req *subreq)
 		tevent_req_nterror(req, status);
 		return;
 	}
-	cli_state_set_tid(state->cli, UINT16_MAX);
+	TALLOC_FREE(state->cli->smb1.tcon);
 	tevent_req_done(req);
 }
 
@@ -2445,10 +2453,14 @@ NTSTATUS cli_tdis(struct cli_state *cli)
 	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		return smb2cli_tdis(cli->conn,
+		status = smb2cli_tdis(cli->conn,
 				    cli->timeout,
 				    cli->smb2.session,
 				    cli->smb2.tcon);
+		if (NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(cli->smb2.tcon);
+		}
+		return status;
 	}
 
 	if (smbXcli_conn_has_async_calls(cli->conn)) {
@@ -3623,6 +3635,13 @@ static struct tevent_req *cli_raw_tcon_send(
 		return tevent_req_post(req, ev);
 	}
 
+	TALLOC_FREE(cli->smb1.tcon);
+	cli->smb1.tcon = smbXcli_tcon_create(cli);
+	if (tevent_req_nomem(cli->smb1.tcon, req)) {
+		return tevent_req_post(req, ev);
+	}
+	smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
+
 	bytes = talloc_array(state, uint8_t, 0);
 	bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
 	bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 4541763ea3f..2b53a930809 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -227,11 +227,6 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
 
 	cli->smb1.pid = (uint32_t)getpid();
 	cli->smb1.vc_num = cli->smb1.pid;
-	cli->smb1.tcon = smbXcli_tcon_create(cli);
-	if (cli->smb1.tcon == NULL) {
-		goto error;
-	}
-	smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
 	cli->smb1.session = smbXcli_session_create(cli, cli->conn);
 	if (cli->smb1.session == NULL) {
 		goto error;
-- 
2.13.1.508.gb3defc5cc-goog


>From 811cc4b491e66b43d02476d83397c12fb3978807 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 13 Jun 2017 16:56:48 -0700
Subject: [PATCH 8/8] s3: libsmb: Correctly save and restore connection tcon in
 smbclient, smbcacls and smbtorture3.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12831

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/lib/util_sd.c     | 24 ++++++++++++++++++++----
 source3/libsmb/clidfs.c   | 18 ++++++++++++++----
 source3/torture/torture.c | 16 ++++++++++++++++
 source3/utils/net_rpc.c   | 12 +++++++++---
 source3/utils/smbcacls.c  | 12 ++++++++++--
 5 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/source3/lib/util_sd.c b/source3/lib/util_sd.c
index a95cafd5f7a..aa6d4809fc8 100644
--- a/source3/lib/util_sd.c
+++ b/source3/lib/util_sd.c
@@ -84,7 +84,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
 				   enum lsa_SidType *type,
 				   char **domain, char **name)
 {
-	uint32_t orig_cnum = cli_state_get_tid(cli);
+	struct smbXcli_tcon *orig_tcon = NULL;
 	struct rpc_pipe_client *p = NULL;
 	struct policy_handle handle;
 	NTSTATUS status;
@@ -93,6 +93,14 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
 	char **domains;
 	char **names;
 
+	if (cli_state_has_tcon(cli)) {
+		orig_tcon = cli_state_save_tcon(cli);
+		if (orig_tcon == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto tcon_fail;
+		}
+	}
+
 	status = cli_tree_connect(cli, "IPC$", "?????", NULL);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto tcon_fail;
@@ -125,7 +133,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
 	TALLOC_FREE(p);
 	cli_tdis(cli);
  tcon_fail:
-	cli_state_set_tid(cli, orig_cnum);
+	cli_state_restore_tcon(cli, orig_tcon);
 	TALLOC_FREE(frame);
 	return status;
 }
@@ -165,7 +173,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
 				    enum lsa_SidType *type,
 				    struct dom_sid *sid)
 {
-	uint32_t orig_cnum = cli_state_get_tid(cli);
+	struct smbXcli_tcon *orig_tcon = NULL;
 	struct rpc_pipe_client *p;
 	struct policy_handle handle;
 	NTSTATUS status;
@@ -173,6 +181,14 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
 	struct dom_sid *sids;
 	enum lsa_SidType *types;
 
+	if (cli_state_has_tcon(cli)) {
+		orig_tcon = cli_state_save_tcon(cli);
+		if (orig_tcon == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto tcon_fail;
+		}
+	}
+
 	status = cli_tree_connect(cli, "IPC$", "?????", NULL);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto tcon_fail;
@@ -204,7 +220,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
 	TALLOC_FREE(p);
 	cli_tdis(cli);
  tcon_fail:
-	cli_state_set_tid(cli, orig_cnum);
+	cli_state_restore_tcon(cli, orig_tcon);
 	TALLOC_FREE(frame);
 	return status;
 }
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 1010e1b5c28..75012b28e87 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -1205,7 +1205,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 	size_t consumed = 0;
 	char *fullpath = NULL;
 	bool res;
-	uint32_t cnum;
+	struct smbXcli_tcon *orig_tcon = NULL;
 	char *newextrapath = NULL;
 	NTSTATUS status;
 	const char *remote_name;
@@ -1215,7 +1215,6 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 	}
 
 	remote_name = smbXcli_conn_remote_name(cli->conn);
-	cnum = cli_state_get_tid(cli);
 
 	/* special case.  never check for a referral on the IPC$ share */
 
@@ -1230,15 +1229,25 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 		return false;
 	}
 
+	/* Store tcon state. */
+	if (cli_state_has_tcon(cli)) {
+		orig_tcon = cli_state_save_tcon(cli);
+		if (orig_tcon == NULL) {
+			return false;
+		}
+	}
+
 	/* check for the referral */
 
 	if (!NT_STATUS_IS_OK(cli_tree_connect(cli, "IPC$", "IPC", NULL))) {
+		cli_state_restore_tcon(cli, orig_tcon);
 		return false;
 	}
 
 	if (force_encrypt) {
 		status = cli_cm_force_encryption_creds(cli, creds, "IPC$");
 		if (!NT_STATUS_IS_OK(status)) {
+			cli_state_restore_tcon(cli, orig_tcon);
 			return false;
 		}
 	}
@@ -1248,12 +1257,13 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 	res = NT_STATUS_IS_OK(status);
 
 	status = cli_tdis(cli);
+
+	cli_state_restore_tcon(cli, orig_tcon);
+
 	if (!NT_STATUS_IS_OK(status)) {
 		return false;
 	}
 
-	cli_state_set_tid(cli, cnum);
-
 	if (!res || !num_refs) {
 		return false;
 	}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 58f0ce0a31f..378cb8ba35f 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -1302,6 +1302,7 @@ static bool run_tcon_test(int dummy)
 	const char *fname = "\\tcontest.tmp";
 	uint16_t fnum1;
 	uint32_t cnum1, cnum2, cnum3;
+	struct smbXcli_tcon *orig_tcon = NULL;
 	uint16_t vuid1, vuid2;
 	char buf[4];
 	bool ret = True;
@@ -1333,6 +1334,11 @@ static bool run_tcon_test(int dummy)
 		return False;
 	}
 
+	orig_tcon = cli_state_save_tcon(cli);
+	if (orig_tcon == NULL) {
+		return false;
+	}
+
 	status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
 	if (!NT_STATUS_IS_OK(status)) {
 		printf("%s refused 2nd tree connect (%s)\n", host,
@@ -1400,6 +1406,8 @@ static bool run_tcon_test(int dummy)
 		return False;
 	}
 
+	cli_state_restore_tcon(cli, orig_tcon);
+
 	cli_state_set_tid(cli, cnum1);
 
 	if (!torture_close_connection(cli)) {
@@ -9017,6 +9025,7 @@ static bool run_uid_regression_test(int dummy)
 	int16_t old_vuid;
 	int32_t old_cnum;
 	bool correct = True;
+	struct smbXcli_tcon *orig_tcon = NULL;
 	NTSTATUS status;
 
 	printf("starting uid regression test\n");
@@ -9057,6 +9066,11 @@ static bool run_uid_regression_test(int dummy)
 	}
 
 	old_cnum = cli_state_get_tid(cli);
+	orig_tcon = cli_state_save_tcon(cli);
+	if (orig_tcon == NULL) {
+		correct = false;
+		goto out;
+	}
 
 	/* Now try a SMBtdis with the invald vuid set to zero. */
 	cli_state_set_uid(cli, 0);
@@ -9069,9 +9083,11 @@ static bool run_uid_regression_test(int dummy)
 	} else {
 		d_printf("First tdis failed (%s)\n", nt_errstr(status));
 		correct = false;
+		cli_state_restore_tcon(cli, orig_tcon);
 		goto out;
 	}
 
+	cli_state_restore_tcon(cli, orig_tcon);
 	cli_state_set_uid(cli, old_vuid);
 	cli_state_set_tid(cli, old_cnum);
 
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index e98f65a3158..7059ebde3ca 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -5101,7 +5101,7 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd,
 	union srvsvc_NetShareInfo info;
 	WERROR result;
 	NTSTATUS status;
-	uint16_t cnum;
+	struct smbXcli_tcon *orig_tcon = NULL;
 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
 
 	status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
@@ -5123,9 +5123,15 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd,
 			  netname));
 	}
 
-	cnum = cli_state_get_tid(cli);
+	if (cli_state_has_tcon(cli)) {
+		orig_tcon = cli_state_save_tcon(cli);
+		if (orig_tcon == NULL) {
+			return;
+		}
+	}
 
 	if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", NULL))) {
+		cli_state_restore_tcon(cli, orig_tcon);
 		return;
 	}
 
@@ -5168,7 +5174,7 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd,
 	if (fnum != (uint16_t)-1)
 		cli_close(cli, fnum);
 	cli_tdis(cli);
-	cli_state_set_tid(cli, cnum);
+	cli_state_restore_tcon(cli, orig_tcon);
 
 	return;
 }
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 11289e69e43..86b4591d365 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -51,12 +51,20 @@ static NTSTATUS cli_lsa_lookup_domain_sid(struct cli_state *cli,
 					  struct dom_sid *sid)
 {
 	union lsa_PolicyInformation *info = NULL;
-	uint16_t orig_cnum = cli_state_get_tid(cli);
+	struct smbXcli_tcon *orig_tcon = NULL;
 	struct rpc_pipe_client *rpc_pipe = NULL;
 	struct policy_handle handle;
 	NTSTATUS status, result;
 	TALLOC_CTX *frame = talloc_stackframe();
 
+	if (cli_state_has_tcon(cli)) {
+		orig_tcon = cli_state_save_tcon(cli);
+		if (orig_tcon == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto done;
+		}
+	}
+
 	status = cli_tree_connect(cli, "IPC$", "?????", NULL);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
@@ -88,7 +96,7 @@ tdis:
 	TALLOC_FREE(rpc_pipe);
 	cli_tdis(cli);
 done:
-	cli_state_set_tid(cli, orig_cnum);
+	cli_state_restore_tcon(cli, orig_tcon);
 	TALLOC_FREE(frame);
 	return status;
 }
-- 
2.13.1.508.gb3defc5cc-goog



More information about the samba-technical mailing list