[PR PATCH] [Updated] samba-tool domain trust: fix trust compatibility to Windows Server 1709 and FreeIPA

Stefan Metzmacher metze at samba.org
Thu Jul 19 08:06:53 UTC 2018


Hi Alexander,

I've implemented the autodetection of smb1 and smb2 for our dcerpc
client side.

Please review patches 1-13 from the attached patchset and push it.

Here's the related pending pipeline:
https://gitlab.com/samba-team/devel/samba/pipelines/26062213

>> Can you split the last patch and demonstrate the the test passes with
>> a temporary file in selftest/knownfail.d/ and then gets fixed with the
>> changes. From reading the test I guess it won't fail as the bug happens
>> in two places.
> Thing is, it will not fail for wrong salt too because we are running
> against the same code that uses the same method to generate salt
> principal. So before the patch we've got 'EXAMPLE.COMFOO$' as a salt,
> after the patch we'd get 'EXAMPLE.COMkrbtgtFOO' but in both cases both
> client and KDC would be operating with the same salt because we retrieve
> this keytab from the same KDC.
> 
> I wonder if we can retrieve it from a different KDC and store under
> the proper principal but current code for keytab retrieval in libnet
> doesn't handle that because it has no way to specify a different
> principal name when writing keys to a keytab (we want to retrieve
> FOO$@EXAMPLE.COM as EXAMPLE$@FOO.COM and then try to auth against
> FOO.COM KDC).
> 
> With my parallel patches (in works) to FreeIPA and SSSD, I get Samba AD
> DC properly trusted by FreeIPA and FreeIPA properly trusted by Samba AD
> DC when trust is driven from FreeIPA side. So salt fixes helped, for
> cases when TDA is used for authentication by both sides. There
> is a remaining need to fix cross-realm TGT on FreeIPA side to allow
> FreeIPA -> Samba AD leg to work with cross-realm referral issuance.
> Samba AD -> FreeIPA leg works already.

I ported the patch to master (some defines are different...)

The pipeline with the complete set is:
https://gitlab.com/samba-team/devel/samba/pipelines/26062727

In the commit message of path 14 I added some TODOs:

    TODO: unit tests: loop over all account types with, loop over names with
    and without upn, with and without '$'. Use 'eXaMpLe.COM' and similar
    names to check the correct upper/lower case result.

    TODO: Also verify this against windows...
    A test can create objects via ldap and/or lsa (for trusts)
    then get the object including supplementalCredentials
    via drsuapi (as admin) and check the stored salt.
    We should have similar tests already.

I think we need at least some test that can't fail because
of a symmetric fix.

Would you have time to work on such tests?

metze
-------------- next part --------------
From 5835a998fe39571ab062a3f730a620eec5ce7e8e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 15:36:31 +0200
Subject: [PATCH 01/15] s4:libcli: split out smb_raw_negotiate_fill_transport()

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/raw/rawnegotiate.c | 74 ++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 30 deletions(-)

diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c
index 73c9123411d6..cec081c364a4 100644
--- a/source4/libcli/raw/rawnegotiate.c
+++ b/source4/libcli/raw/rawnegotiate.c
@@ -28,6 +28,47 @@
 #include "../libcli/smb/smbXcli_base.h"
 #include "../lib/util/tevent_ntstatus.h"
 
+NTSTATUS smb_raw_negotiate_fill_transport(struct smbcli_transport *transport)
+{
+	struct smbcli_negotiate *n = &transport->negotiate;
+	struct smbXcli_conn *c = transport->conn;
+	NTTIME ntt;
+
+	n->protocol = smbXcli_conn_protocol(c);
+	if (n->protocol > PROTOCOL_NT1) {
+		return NT_STATUS_REVISION_MISMATCH;
+	}
+
+	n->sec_mode = smb1cli_conn_server_security_mode(c);
+	n->max_mux  = smbXcli_conn_max_requests(c);
+	n->max_xmit = smb1cli_conn_max_xmit(c);
+	n->sesskey  = smb1cli_conn_server_session_key(c);
+	n->capabilities = smb1cli_conn_capabilities(c);;
+
+	/* this time arrives in real GMT */
+	ntt = smbXcli_conn_server_system_time(c);
+	n->server_time = nt_time_to_unix(ntt);
+	n->server_zone = smb1cli_conn_server_time_zone(c);
+
+	if (n->capabilities & CAP_EXTENDED_SECURITY) {
+		const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c);
+		if (b) {
+			n->secblob = *b;
+		}
+	} else {
+		const uint8_t *p = smb1cli_conn_server_challenge(c);
+		if (p) {
+			n->secblob = data_blob_const(p, 8);
+		}
+	}
+
+	n->readbraw_supported = smb1cli_conn_server_readbraw(c);
+	n->readbraw_supported = smb1cli_conn_server_writebraw(c);
+	n->lockread_supported = smb1cli_conn_server_lockread(c);
+
+	return NT_STATUS_OK;
+}
+
 struct smb_raw_negotiate_state {
 	struct smbcli_transport *transport;
 };
@@ -82,10 +123,7 @@ static void smb_raw_negotiate_done(struct tevent_req *subreq)
 	struct smb_raw_negotiate_state *state =
 		tevent_req_data(req,
 		struct smb_raw_negotiate_state);
-	struct smbcli_negotiate *n = &state->transport->negotiate;
-	struct smbXcli_conn *c = state->transport->conn;
 	NTSTATUS status;
-	NTTIME ntt;
 
 	status = smbXcli_negprot_recv(subreq);
 	TALLOC_FREE(subreq);
@@ -93,35 +131,11 @@ static void smb_raw_negotiate_done(struct tevent_req *subreq)
 		return;
 	}
 
-	n->protocol = smbXcli_conn_protocol(c);
-
-	n->sec_mode = smb1cli_conn_server_security_mode(c);
-	n->max_mux  = smbXcli_conn_max_requests(c);
-	n->max_xmit = smb1cli_conn_max_xmit(c);
-	n->sesskey  = smb1cli_conn_server_session_key(c);
-	n->capabilities = smb1cli_conn_capabilities(c);;
-
-	/* this time arrives in real GMT */
-	ntt = smbXcli_conn_server_system_time(c);
-	n->server_time = nt_time_to_unix(ntt);
-	n->server_zone = smb1cli_conn_server_time_zone(c);
-
-	if (n->capabilities & CAP_EXTENDED_SECURITY) {
-		const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c);
-		if (b) {
-			n->secblob = *b;
-		}
-	} else {
-		const uint8_t *p = smb1cli_conn_server_challenge(c);
-		if (p) {
-			n->secblob = data_blob_const(p, 8);
-		}
+	status = smb_raw_negotiate_fill_transport(state->transport);
+	if (tevent_req_nterror(req, status)) {
+		return;
 	}
 
-	n->readbraw_supported = smb1cli_conn_server_readbraw(c);
-	n->readbraw_supported = smb1cli_conn_server_writebraw(c);
-	n->lockread_supported = smb1cli_conn_server_lockread(c);
-
 	tevent_req_done(req);
 }
 
-- 
2.17.1


From 79d799005ac5d4c901c2aed35adc2082b0d4bc99 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 15:36:52 +0200
Subject: [PATCH 02/15] s4:libcli: add smbcli_transport_raw_init()

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/raw/clitransport.c | 44 +++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index d0dd1f9dee6a..47b8dbf3ae7f 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -113,6 +113,50 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
 	return transport;
 }
 
+/*
+  create a transport structure based on an established socket
+*/
+NTSTATUS smbcli_transport_raw_init(TALLOC_CTX *mem_ctx,
+				   struct tevent_context *ev,
+				   struct smbXcli_conn **_conn,
+				   const struct smbcli_options *options,
+				   struct smbcli_transport **_transport)
+{
+	struct smbcli_transport *transport = NULL;
+	NTSTATUS status;
+
+	if (*_conn == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	transport = talloc_zero(mem_ctx, struct smbcli_transport);
+	if (transport == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	transport->ev = ev;
+	transport->options = *options;
+
+	/*
+	 * First only set the pointer without move.
+	 */
+	transport->conn = *_conn;
+	status = smb_raw_negotiate_fill_transport(transport);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(transport);
+		return status;
+	}
+
+	talloc_set_destructor(transport, transport_destructor);
+
+	/*
+	 * Now move it away from the caller...
+	 */
+	transport->conn = talloc_move(transport, _conn);
+	*_transport = transport;
+	return NT_STATUS_OK;
+}
+
 /*
   mark the transport as dead
 */
-- 
2.17.1


From 639cf055204db0480e23f401a58f3b59f792d6eb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 15:01:50 +0200
Subject: [PATCH 03/15] s4:libcli: use talloc_zero() for struct
 smb_composite_connect in fetchfile.c

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/smb_composite/fetchfile.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/libcli/smb_composite/fetchfile.c b/source4/libcli/smb_composite/fetchfile.c
index d19c86a8d05b..dc6f71b452e2 100644
--- a/source4/libcli/smb_composite/fetchfile.c
+++ b/source4/libcli/smb_composite/fetchfile.c
@@ -131,7 +131,7 @@ struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetc
 	state = talloc(c, struct fetchfile_state);
 	if (state == NULL) goto failed;
 
-	state->connect = talloc(state, struct smb_composite_connect);
+	state->connect = talloc_zero(state, struct smb_composite_connect);
 	if (state->connect == NULL) goto failed;
 
 	state->io = io;
-- 
2.17.1


From 606d623554b9e6b6a47fe0ebd232e2cf898d6200 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 15:34:55 +0200
Subject: [PATCH 04/15] s4:libcli: allow passing an already negotiated
 connection to smb_composite_connect()

It will just do the session setup and tree connect steps.

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/raw/clitree.c                 |  1 +
 source4/libcli/smb_composite/connect.c       | 48 ++++++++++++++++----
 source4/libcli/smb_composite/smb_composite.h |  1 +
 source4/ntvfs/cifs/vfs_cifs.c                |  1 +
 4 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c
index 11be5485f261..b1b6159e7508 100644
--- a/source4/libcli/raw/clitree.c
+++ b/source4/libcli/raw/clitree.c
@@ -207,6 +207,7 @@ NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
 	io.in.called_name = strupper_talloc(tmp_ctx, dest_host);
 	io.in.service = service;
 	io.in.service_type = service_type;
+	io.in.existing_conn = NULL;
 	io.in.credentials = credentials;
 	io.in.gensec_settings = gensec_settings;
 	io.in.fallback_to_anonymous = false;
diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c
index fffa768ac977..582d43ef1730 100644
--- a/source4/libcli/smb_composite/connect.c
+++ b/source4/libcli/smb_composite/connect.c
@@ -228,18 +228,10 @@ static NTSTATUS connect_session_setup(struct composite_context *c,
 	return NT_STATUS_OK;
 }
 
-/*
-  a negprot request has completed
-*/
-static NTSTATUS connect_negprot(struct composite_context *c, 
-				struct smb_composite_connect *io)
+static NTSTATUS connect_send_session(struct composite_context *c,
+				     struct smb_composite_connect *io)
 {
 	struct connect_state *state = talloc_get_type(c->private_data, struct connect_state);
-	NTSTATUS status;
-
-	status = smb_raw_negotiate_recv(state->subreq);
-	TALLOC_FREE(state->subreq);
-	NT_STATUS_NOT_OK_RETURN(status);
 
 	/* next step is a session setup */
 	state->session = smbcli_session_init(state->transport, state, true, io->in.session_options);
@@ -281,6 +273,22 @@ static NTSTATUS connect_negprot(struct composite_context *c,
 	return NT_STATUS_OK;
 }
 
+/*
+  a negprot request has completed
+*/
+static NTSTATUS connect_negprot(struct composite_context *c,
+				struct smb_composite_connect *io)
+{
+	struct connect_state *state = talloc_get_type(c->private_data, struct connect_state);
+	NTSTATUS status;
+
+	status = smb_raw_negotiate_recv(state->subreq);
+	TALLOC_FREE(state->subreq);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	return connect_send_session(c, io);
+}
+
 /*
   setup a negprot send 
 */
@@ -432,6 +440,26 @@ struct composite_context *smb_composite_connect_send(struct smb_composite_connec
 	nbt_choose_called_name(state, &state->called,
 			       io->in.called_name, NBT_NAME_SERVER);
 
+	if (io->in.existing_conn != NULL) {
+		NTSTATUS status;
+
+		status = smbcli_transport_raw_init(state,
+						   c->event_ctx,
+						   &io->in.existing_conn,
+						   &io->in.options,
+						   &state->transport);
+		if (!NT_STATUS_IS_OK(status)) {
+			goto failed;
+		}
+
+		status = connect_send_session(c, io);
+		if (!NT_STATUS_IS_OK(status)) {
+			goto failed;
+		}
+
+		return c;
+	}
+
 	state->creq = smbcli_sock_connect_send(state, 
 					       NULL,
 					       io->in.dest_ports,
diff --git a/source4/libcli/smb_composite/smb_composite.h b/source4/libcli/smb_composite/smb_composite.h
index a92c9612c6ac..383946f1307a 100644
--- a/source4/libcli/smb_composite/smb_composite.h
+++ b/source4/libcli/smb_composite/smb_composite.h
@@ -118,6 +118,7 @@ struct smb_composite_connect {
 		const char *called_name;
 		const char *service;
 		const char *service_type;
+		struct smbXcli_conn *existing_conn; /* optional */
 		struct cli_credentials *credentials;
 		bool fallback_to_anonymous;
 		const char *workgroup;
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c
index 478428e32465..d88c034c6f2a 100644
--- a/source4/ntvfs/cifs/vfs_cifs.c
+++ b/source4/ntvfs/cifs/vfs_cifs.c
@@ -296,6 +296,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
 	io.in.dest_ports = lpcfg_smb_ports(ntvfs->ctx->lp_ctx);
 	io.in.socket_options = lpcfg_socket_options(ntvfs->ctx->lp_ctx);
 	io.in.called_name = host;
+	io.in.existing_conn = NULL;
 	io.in.credentials = credentials;
 	io.in.fallback_to_anonymous = false;
 	io.in.workgroup = lpcfg_workgroup(ntvfs->ctx->lp_ctx);
-- 
2.17.1


From af9ed03a678cc5a894e8fbebd137c4f35125a054 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 16:43:04 +0200
Subject: [PATCH 05/15] s4:libcli: add smb2_transport_raw_init()

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/smb2/transport.c | 35 +++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c
index 166f34b82569..1d08289341ba 100644
--- a/source4/libcli/smb2/transport.c
+++ b/source4/libcli/smb2/transport.c
@@ -85,6 +85,41 @@ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock,
 	return transport;
 }
 
+/*
+  create a transport structure based on an established socket
+*/
+NTSTATUS smb2_transport_raw_init(TALLOC_CTX *mem_ctx,
+				 struct tevent_context *ev,
+				 struct smbXcli_conn **_conn,
+				 const struct smbcli_options *options,
+				 struct smb2_transport **_transport)
+{
+	struct smb2_transport *transport = NULL;
+	enum protocol_types protocol;
+
+	if (*_conn == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	protocol = smbXcli_conn_protocol(*_conn);
+	if (protocol < PROTOCOL_SMB2_02) {
+		return NT_STATUS_REVISION_MISMATCH;
+	}
+
+	transport = talloc_zero(mem_ctx, struct smb2_transport);
+	if (transport == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	transport->ev = ev;
+	transport->options = *options;
+	transport->conn = talloc_move(transport, _conn);
+
+	talloc_set_destructor(transport, transport_destructor);
+	*_transport = transport;
+	return NT_STATUS_OK;
+}
+
 /*
   mark the transport as dead
 */
-- 
2.17.1


From c39fca2f9007509bfadd39bf5e7f2c2bfe80fc91 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 16:43:32 +0200
Subject: [PATCH 06/15] s4:libcli: split out smb2_connect_session_start()

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/smb2/connect.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c
index 8ff56c9ca8f8..ac37eae6aa89 100644
--- a/source4/libcli/smb2/connect.c
+++ b/source4/libcli/smb2/connect.c
@@ -50,6 +50,7 @@ struct smb2_connect_state {
 	struct smb2_tree *tree;
 };
 
+static void smb2_connect_session_start(struct tevent_req *req);
 static void smb2_connect_socket_done(struct composite_context *creq);
 
 /*
@@ -170,10 +171,6 @@ static void smb2_connect_negprot_done(struct tevent_req *subreq)
 	struct tevent_req *req =
 		tevent_req_callback_data(subreq,
 		struct tevent_req);
-	struct smb2_connect_state *state =
-		tevent_req_data(req,
-		struct smb2_connect_state);
-	struct smb2_transport *transport = state->transport;
 	NTSTATUS status;
 
 	status = smbXcli_negprot_recv(subreq);
@@ -182,6 +179,17 @@ static void smb2_connect_negprot_done(struct tevent_req *subreq)
 		return;
 	}
 
+	smb2_connect_session_start(req);
+}
+
+static void smb2_connect_session_start(struct tevent_req *req)
+{
+	struct smb2_connect_state *state =
+		tevent_req_data(req,
+		struct smb2_connect_state);
+	struct smb2_transport *transport = state->transport;
+	struct tevent_req *subreq = NULL;
+
 	state->session = smb2_session_init(transport, state->gensec_settings, state);
 	if (tevent_req_nomem(state->session, req)) {
 		return;
-- 
2.17.1


From dde3c6103d48035e950633cc3c3bfd7961bef5eb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 16:44:16 +0200
Subject: [PATCH 07/15] s4:libcli: allow passing an already negotiated
 connection to smb2_connect_send()

It will just do the session setup and tree connect steps.

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/smb2/connect.c       | 21 +++++++++++++++++++++
 source4/librpc/rpc/dcerpc_connect.c |  1 +
 2 files changed, 22 insertions(+)

diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c
index ac37eae6aa89..2dee50218694 100644
--- a/source4/libcli/smb2/connect.c
+++ b/source4/libcli/smb2/connect.c
@@ -64,6 +64,7 @@ struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
 				     const char *share,
 				     struct resolve_context *resolve_ctx,
 				     struct cli_credentials *credentials,
+				     struct smbXcli_conn **existing_conn,
 				     uint64_t previous_session_id,
 				     const struct smbcli_options *options,
 				     const char *socket_options,
@@ -107,6 +108,25 @@ struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	if (existing_conn != NULL) {
+		NTSTATUS status;
+
+		status = smb2_transport_raw_init(state, ev,
+						 existing_conn,
+						 options,
+						 &state->transport);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+
+		smb2_connect_session_start(req);
+		if (!tevent_req_is_in_progress(req)) {
+			return tevent_req_post(req, ev);
+		}
+
+		return req;
+	}
+
 	creq = smbcli_sock_connect_send(state, NULL, state->ports,
 					state->host, state->resolve_ctx,
 					state->ev, state->socket_options,
@@ -311,6 +331,7 @@ NTSTATUS smb2_connect_ext(TALLOC_CTX *mem_ctx,
 				   share,
 				   resolve_ctx,
 				   credentials,
+				   NULL, /* existing_conn */
 				   previous_session_id,
 				   options,
 				   socket_options,
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 1252e74b5a9d..a3f25efc0b47 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -301,6 +301,7 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
 			"IPC$",
 			s->io.resolve_ctx,
 			s->io.creds,
+			NULL, /* existing_conn */
 			0, /* previous_session_id */
 			&options,
 			lpcfg_socket_options(lp_ctx),
-- 
2.17.1


From 5529fc17ec3f59103d6da17a5b11546334a46e5f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 23:52:30 +0200
Subject: [PATCH 08/15] s4:libcli: add fallback_to_anonymous to
 smb2_connect_send()

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/smb2/connect.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c
index 2dee50218694..e4cbf8c5c419 100644
--- a/source4/libcli/smb2/connect.c
+++ b/source4/libcli/smb2/connect.c
@@ -35,6 +35,7 @@
 struct smb2_connect_state {
 	struct tevent_context *ev;
 	struct cli_credentials *credentials;
+	bool fallback_to_anonymous;
 	uint64_t previous_session_id;
 	struct resolve_context *resolve_ctx;
 	const char *host;
@@ -64,6 +65,7 @@ struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
 				     const char *share,
 				     struct resolve_context *resolve_ctx,
 				     struct cli_credentials *credentials,
+				     bool fallback_to_anonymous,
 				     struct smbXcli_conn **existing_conn,
 				     uint64_t previous_session_id,
 				     const struct smbcli_options *options,
@@ -83,6 +85,7 @@ struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
 
 	state->ev = ev;
 	state->credentials = credentials;
+	state->fallback_to_anonymous = fallback_to_anonymous;
 	state->previous_session_id = previous_session_id;
 	state->options = *options;
 	state->host = host;
@@ -240,6 +243,34 @@ static void smb2_connect_session_done(struct tevent_req *subreq)
 
 	status = smb2_session_setup_spnego_recv(subreq);
 	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status) &&
+	    !cli_credentials_is_anonymous(state->credentials) &&
+	    state->fallback_to_anonymous) {
+		struct cli_credentials *anon_creds = NULL;
+
+		/*
+		 * The transport was moved to session,
+		 * we need to revert that before removing
+		 * the old broken session.
+		 */
+		state->transport = talloc_move(state, &state->session->transport);
+		TALLOC_FREE(state->session);
+
+		anon_creds = cli_credentials_init_anon(state);
+		if (tevent_req_nomem(anon_creds, req)) {
+			return;
+		}
+		cli_credentials_set_workstation(anon_creds,
+		   cli_credentials_get_workstation(state->credentials),
+		   CRED_SPECIFIED);
+
+		/*
+		 * retry with anonymous credentials
+		 */
+		state->credentials = anon_creds;
+		smb2_connect_session_start(req);
+		return;
+	}
 	if (tevent_req_nterror(req, status)) {
 		return;
 	}
@@ -331,6 +362,7 @@ NTSTATUS smb2_connect_ext(TALLOC_CTX *mem_ctx,
 				   share,
 				   resolve_ctx,
 				   credentials,
+				   false, /* fallback_to_anonymous */
 				   NULL, /* existing_conn */
 				   previous_session_id,
 				   options,
-- 
2.17.1


From c5ac6f40c6fe93e273c7b4208bbf2405d0db8dad Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 14:52:43 +0200
Subject: [PATCH 09/15] s4:libcli: add smb_connect_nego_{send,recv}()

This can be used to create a connection up to a negotiated
smbXcli_conn.

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/libcli/smb_composite/connect_nego.c  | 206 +++++++++++++++++++
 source4/libcli/smb_composite/smb_composite.h |  21 ++
 source4/libcli/wscript_build                 |  20 +-
 3 files changed, 242 insertions(+), 5 deletions(-)
 create mode 100644 source4/libcli/smb_composite/connect_nego.c

diff --git a/source4/libcli/smb_composite/connect_nego.c b/source4/libcli/smb_composite/connect_nego.c
new file mode 100644
index 000000000000..14538c76afcb
--- /dev/null
+++ b/source4/libcli/smb_composite/connect_nego.c
@@ -0,0 +1,206 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) Stefan Metzmacher 2018
+
+   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/tevent_ntstatus.h"
+#include "libcli/composite/composite.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "libcli/smb_composite/smb_composite.h"
+#include "lib/socket/socket.h"
+#include "libcli/resolve/resolve.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "libcli/smb/smbXcli_base.h"
+
+struct smb_connect_nego_state {
+	struct tevent_context *ev;
+	struct resolve_context *resolve_ctx;
+	const char *socket_options;
+	struct smbcli_options options;
+	const char *dest_hostname;
+	const char *dest_address;
+	const char **dest_ports;
+	struct nbt_name calling, called;
+	struct smbXcli_conn *conn;
+};
+
+static void smb_connect_nego_connect_done(struct composite_context *creq);
+static void smb_connect_nego_nego_done(struct tevent_req *subreq);
+
+struct tevent_req *smb_connect_nego_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 struct resolve_context *resolve_ctx,
+					 const struct smbcli_options *options,
+					 const char *socket_options,
+					 const char *dest_hostname,
+					 const char *dest_address, /* optional */
+					 const char **dest_ports,
+					 const char *called_name,
+					 const char *calling_name)
+{
+	struct tevent_req *req = NULL;
+	struct smb_connect_nego_state *state = NULL;
+	struct composite_context *creq = NULL;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct smb_connect_nego_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+	state->resolve_ctx= resolve_ctx;
+	state->options = *options;
+	state->socket_options = socket_options;
+	state->dest_hostname = dest_hostname;
+	state->dest_address = dest_address;
+	state->dest_ports = dest_ports;
+
+	make_nbt_name_client(&state->calling, calling_name);
+
+	nbt_choose_called_name(state, &state->called,
+			       called_name, NBT_NAME_SERVER);
+	if (tevent_req_nomem(state->called.name, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	creq = smbcli_sock_connect_send(state,
+					state->dest_address,
+					state->dest_ports,
+					state->dest_hostname,
+					state->resolve_ctx,
+					state->ev,
+					state->socket_options,
+					&state->calling,
+					&state->called);
+	if (tevent_req_nomem(creq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	creq->async.private_data = req;
+	creq->async.fn = smb_connect_nego_connect_done;
+
+	return req;
+}
+
+static void smb_connect_nego_connect_done(struct composite_context *creq)
+{
+	struct tevent_req *req =
+		talloc_get_type_abort(creq->async.private_data,
+		struct tevent_req);
+	struct smb_connect_nego_state *state =
+		tevent_req_data(req,
+		struct smb_connect_nego_state);
+	struct tevent_req *subreq = NULL;
+	struct smbcli_socket *sock = NULL;
+	uint32_t smb1_capabilities;
+	uint32_t timeout_msec = state->options.request_timeout * 1000;
+	NTSTATUS status;
+
+	status = smbcli_sock_connect_recv(creq, state, &sock);
+	creq = NULL;
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	TALLOC_FREE(sock->event.fde);
+	TALLOC_FREE(sock->event.te);
+
+	smb1_capabilities = 0;
+	smb1_capabilities |= CAP_LARGE_FILES;
+	smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
+	smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND;
+	smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS;
+	smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX;
+	smb1_capabilities |= CAP_LWIO;
+
+	if (state->options.ntstatus_support) {
+		smb1_capabilities |= CAP_STATUS32;
+	}
+
+	if (state->options.unicode) {
+		smb1_capabilities |= CAP_UNICODE;
+	}
+
+	if (state->options.use_spnego) {
+		smb1_capabilities |= CAP_EXTENDED_SECURITY;
+	}
+
+	if (state->options.use_level2_oplocks) {
+		smb1_capabilities |= CAP_LEVEL_II_OPLOCKS;
+	}
+
+	state->conn = smbXcli_conn_create(state,
+					  sock->sock->fd,
+					  state->dest_hostname,
+					  state->options.signing,
+					  smb1_capabilities,
+					  &state->options.client_guid,
+					  state->options.smb2_capabilities);
+	if (tevent_req_nomem(state->conn, req)) {
+		return;
+	}
+	sock->sock->fd = -1;
+	TALLOC_FREE(sock);
+
+	subreq = smbXcli_negprot_send(state,
+				      state->ev,
+				      state->conn,
+				      timeout_msec,
+				      state->options.min_protocol,
+				      state->options.max_protocol,
+				      state->options.max_credits);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, smb_connect_nego_nego_done, req);
+}
+
+static void smb_connect_nego_nego_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	NTSTATUS status;
+
+	status = smbXcli_negprot_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	tevent_req_done(req);
+}
+
+NTSTATUS smb_connect_nego_recv(struct tevent_req *req,
+			       TALLOC_CTX *mem_ctx,
+			       struct smbXcli_conn **_conn)
+{
+	struct smb_connect_nego_state *state =
+		tevent_req_data(req,
+		struct smb_connect_nego_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+
+	*_conn = talloc_move(mem_ctx, &state->conn);
+	tevent_req_received(req);
+	return NT_STATUS_OK;
+}
diff --git a/source4/libcli/smb_composite/smb_composite.h b/source4/libcli/smb_composite/smb_composite.h
index 383946f1307a..72c9bc7507e6 100644
--- a/source4/libcli/smb_composite/smb_composite.h
+++ b/source4/libcli/smb_composite/smb_composite.h
@@ -101,6 +101,27 @@ NTSTATUS smb_composite_savefile_recv(struct composite_context *c);
 NTSTATUS smb_composite_savefile(struct smbcli_tree *tree, 
 				struct smb_composite_savefile *io);
 
+/*
+  a composite request for a low level connection to a remote server. Includes
+
+    - socket establishment
+    - session request
+    - negprot
+*/
+struct tevent_req *smb_connect_nego_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 struct resolve_context *resolve_ctx,
+					 const struct smbcli_options *options,
+					 const char *socket_options,
+					 const char *dest_hostname,
+					 const char *dest_address, /* optional */
+					 const char **dest_ports,
+					 const char *called_name,
+					 const char *calling_name);
+NTSTATUS smb_connect_nego_recv(struct tevent_req *req,
+			       TALLOC_CTX *mem_ctx,
+			       struct smbXcli_conn **_conn);
+
 /*
   a composite request for a full connection to a remote server. Includes
 
diff --git a/source4/libcli/wscript_build b/source4/libcli/wscript_build
index 220b028cb368..d3641f538af3 100644
--- a/source4/libcli/wscript_build
+++ b/source4/libcli/wscript_build
@@ -25,11 +25,21 @@ bld.SAMBA_SUBSYSTEM('cli_composite',
 
 
 bld.SAMBA_SUBSYSTEM('LIBCLI_SMB_COMPOSITE',
-	source='smb_composite/loadfile.c smb_composite/savefile.c smb_composite/connect.c smb_composite/sesssetup.c smb_composite/fetchfile.c smb_composite/appendacl.c smb_composite/fsinfo.c smb_composite/smb2.c',
-	deps='LIBCLI_SMB2 tevent-util',
-	public_deps='cli_composite samba-credentials gensec LIBCLI_RESOLVE tevent',
-	private_headers='smb_composite/smb_composite.h',
-	)
+    source='''
+       smb_composite/loadfile.c
+       smb_composite/savefile.c
+       smb_composite/connect_nego.c
+       smb_composite/connect.c
+       smb_composite/sesssetup.c
+       smb_composite/fetchfile.c
+       smb_composite/appendacl.c
+       smb_composite/fsinfo.c
+       smb_composite/smb2.c
+    ''',
+    deps='LIBCLI_SMB2 tevent-util',
+    public_deps='cli_composite samba-credentials gensec LIBCLI_RESOLVE tevent',
+    private_headers='smb_composite/smb_composite.h',
+    )
 
 
 for env in bld.gen_python_environments():
-- 
2.17.1


From 1852d9d898e51f78e24b86e11e233565328d689c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 19 Jul 2018 07:32:08 +0200
Subject: [PATCH 10/15] librpc: add binding handle support for [smb1]

This will be used to force smb1.

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 librpc/rpc/binding.c    | 1 +
 librpc/rpc/rpc_common.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/librpc/rpc/binding.c b/librpc/rpc/binding.c
index 63ba682a577e..aa8cc6b46c6f 100644
--- a/librpc/rpc/binding.c
+++ b/librpc/rpc/binding.c
@@ -103,6 +103,7 @@ static const struct ncacn_option {
 	{"print", DCERPC_DEBUG_PRINT_BOTH},
 	{"padcheck", DCERPC_DEBUG_PAD_CHECK},
 	{"bigendian", DCERPC_PUSH_BIGENDIAN},
+	{"smb1", DCERPC_SMB1},
 	{"smb2", DCERPC_SMB2},
 	{"ndr64", DCERPC_NDR64},
 	{"packet", DCERPC_PACKET},
diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h
index d6b2d5dbc055..cdc9fe8ac882 100644
--- a/librpc/rpc/rpc_common.h
+++ b/librpc/rpc/rpc_common.h
@@ -108,6 +108,8 @@ struct dcerpc_binding;
 
 #define DCERPC_PACKET			(1<<26)
 
+#define DCERPC_SMB1                    (1<<27)
+
 /* The following definitions come from ../librpc/rpc/dcerpc_error.c  */
 
 const char *dcerpc_errstr(TALLOC_CTX *mem_ctx, uint32_t fault_code);
-- 
2.17.1


From afc70b6ee590e9e295aca01c0d3bf210e06afada Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jul 2018 16:55:33 +0200
Subject: [PATCH 11/15] s4:librpc: autonegotiate SMB1/2/3

Windows Server 1709 defaults to SMB2 and does not have SMB1 enabled.
When establishing trust, samba-tool does not specify SMB protocol
version and fail by default.

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/librpc/rpc/dcerpc_connect.c | 238 ++++++++++++----------------
 1 file changed, 102 insertions(+), 136 deletions(-)

diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index a3f25efc0b47..93619c6a54fb 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -76,6 +76,8 @@ static void continue_pipe_open_smb(struct composite_context *ctx)
 }
 
 static void continue_smb_open(struct composite_context *c);
+static void continue_smb2_connect(struct tevent_req *subreq);
+static void continue_smbXcli_connect(struct tevent_req *subreq);
 
 /*
   Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
@@ -132,9 +134,10 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CT
 {
 	struct composite_context *c;
 	struct pipe_np_smb_state *s;
-	struct composite_context *conn_req;
+	struct tevent_req *subreq = NULL;
 	struct smb_composite_connect *conn;
 	uint32_t flags;
+	const char *calling_name = NULL;
 
 	/* composite context allocation and setup */
 	c = composite_create(mem_ctx, io->conn->event_ctx);
@@ -152,6 +155,11 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CT
 		return c;
 	}
 
+	if (s->io.creds == NULL) {
+		composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+		return c;
+	}
+
 	/* prepare smb connection parameters: we're connecting to IPC$ share on
 	   remote rpc server */
 	conn->in.dest_host = dcerpc_binding_get_string_option(s->io.binding, "host");
@@ -184,21 +192,100 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CT
 		conn->in.fallback_to_anonymous  = false;
 	}
 
-	conn->in.options.min_protocol = PROTOCOL_NT1;
-	conn->in.options.max_protocol = PROTOCOL_NT1;
+	conn->in.options.min_protocol = lpcfg_client_ipc_min_protocol(lp_ctx);
+	conn->in.options.max_protocol = lpcfg_client_ipc_max_protocol(lp_ctx);
+	if ((flags & DCERPC_SMB1) && (flags & DCERPC_SMB2)) {
+		/* auto */
+	} else if (flags & DCERPC_SMB2) {
+		if (conn->in.options.min_protocol < PROTOCOL_SMB2_02) {
+			conn->in.options.min_protocol = PROTOCOL_SMB2_02;
+		}
+		if (conn->in.options.max_protocol < PROTOCOL_SMB2_02) {
+			conn->in.options.max_protocol = PROTOCOL_LATEST;
+		}
+	} else if (flags & DCERPC_SMB1) {
+		conn->in.options.min_protocol = PROTOCOL_NT1;
+		conn->in.options.max_protocol = PROTOCOL_NT1;
+	} else {
+		/* auto */
+	}
 
 	conn->in.options.signing = lpcfg_client_ipc_signing(lp_ctx);
 
-	/* send smb connect request */
-	conn_req = smb_composite_connect_send(conn, s->io.conn,
-					      s->io.resolve_ctx,
-					      c->event_ctx);
-	if (composite_nomem(conn_req, c)) return c;
+	if (s->conn.in.credentials != NULL) {
+		calling_name = cli_credentials_get_workstation(s->conn.in.credentials);
+	}
+	if (calling_name == NULL) {
+		calling_name = "SMBCLIENT";
+	}
+
+	subreq = smb_connect_nego_send(s,
+				       c->event_ctx,
+				       s->io.resolve_ctx,
+				       &conn->in.options,
+				       conn->in.socket_options,
+				       conn->in.dest_host,
+				       NULL, /* dest_address */
+				       conn->in.dest_ports,
+				       conn->in.called_name,
+				       calling_name);
+	if (composite_nomem(subreq, c)) return c;
+	tevent_req_set_callback(subreq,
+				continue_smbXcli_connect,
+				c);
 
-	composite_continue(c, conn_req, continue_smb_connect, c);
 	return c;
 }
 
+static void continue_smbXcli_connect(struct tevent_req *subreq)
+{
+	struct composite_context *c =
+		tevent_req_callback_data(subreq,
+		struct composite_context);
+	struct pipe_np_smb_state *s =
+		talloc_get_type_abort(c->private_data,
+		struct pipe_np_smb_state);
+	struct smb_composite_connect *conn = &s->conn;
+	struct composite_context *creq = NULL;
+	enum protocol_types protocol;
+
+	c->status = smb_connect_nego_recv(subreq, s,
+					  &conn->in.existing_conn);
+	TALLOC_FREE(subreq);
+	if (!composite_is_ok(c)) return;
+
+	protocol = smbXcli_conn_protocol(conn->in.existing_conn);
+	if (protocol >= PROTOCOL_SMB2_02) {
+		// TODO add [smb2] to binding
+
+		/* send smb2 connect request */
+		subreq = smb2_connect_send(s, c->event_ctx,
+				conn->in.dest_host,
+				conn->in.dest_ports,
+				conn->in.service,
+				s->io.resolve_ctx,
+				conn->in.credentials,
+				conn->in.fallback_to_anonymous,
+				&conn->in.existing_conn,
+				0, /* previous_session_id */
+				&conn->in.options,
+				conn->in.socket_options,
+				conn->in.gensec_settings);
+		if (composite_nomem(subreq, c)) return;
+		tevent_req_set_callback(subreq, continue_smb2_connect, c);
+		return;
+	}
+
+	/* send smb connect request */
+	creq = smb_composite_connect_send(conn, s->io.conn,
+					  s->io.resolve_ctx,
+					  c->event_ctx);
+	if (composite_nomem(creq, c)) return;
+
+	composite_continue(c, creq, continue_smb_connect, c);
+	return;
+}
+
 
 /*
   Receive result of a rpc connection to a rpc pipe on SMB
@@ -238,92 +325,6 @@ static void continue_smb2_connect(struct tevent_req *subreq)
 }
 
 
-/* 
-   Initiate async open of a rpc connection request on SMB2 using
-   the binding structure to determine the endpoint and options
-*/
-static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
-					TALLOC_CTX *mem_ctx,
-					struct dcerpc_pipe_connect *io,
-					struct loadparm_context *lp_ctx)
-{
-	struct composite_context *c;
-	struct pipe_np_smb_state *s;
-	struct tevent_req *subreq;
-	struct smbcli_options options;
-	const char *host;
-	uint32_t flags;
-
-	/* composite context allocation and setup */
-	c = composite_create(mem_ctx, io->conn->event_ctx);
-	if (c == NULL) return NULL;
-
-	s = talloc_zero(c, struct pipe_np_smb_state);
-	if (composite_nomem(s, c)) return c;
-	c->private_data = s;
-
-	s->io = *io;
-
-	if (smbXcli_conn_is_connected(s->io.smb.conn)) {
-		continue_smb_open(c);
-		return c;
-	}
-
-	host = dcerpc_binding_get_string_option(s->io.binding, "host");
-	flags = dcerpc_binding_get_flags(s->io.binding);
-
-	/*
-	 * provide proper credentials - user supplied or anonymous in case this is
-	 * schannel connection
-	 */
-	if (flags & DCERPC_SCHANNEL) {
-		s->io.creds = cli_credentials_init_anon(mem_ctx);
-		if (composite_nomem(s->io.creds, c)) return c;
-	}
-
-	lpcfg_smbcli_options(lp_ctx, &options);
-
-	options.min_protocol = lpcfg_client_ipc_min_protocol(lp_ctx);
-	if (options.min_protocol < PROTOCOL_SMB2_02) {
-		options.min_protocol = PROTOCOL_SMB2_02;
-	}
-	options.max_protocol = lpcfg_client_ipc_max_protocol(lp_ctx);
-	if (options.max_protocol < PROTOCOL_SMB2_02) {
-		options.max_protocol = PROTOCOL_SMB2_02;
-	}
-
-	options.signing = lpcfg_client_ipc_signing(lp_ctx);
-
-	/* send smb2 connect request */
-	subreq = smb2_connect_send(s, c->event_ctx,
-			host,
-			lpcfg_parm_string_list(mem_ctx, lp_ctx, NULL, "smb2", "ports", NULL),
-			"IPC$",
-			s->io.resolve_ctx,
-			s->io.creds,
-			NULL, /* existing_conn */
-			0, /* previous_session_id */
-			&options,
-			lpcfg_socket_options(lp_ctx),
-			lpcfg_gensec_settings(mem_ctx, lp_ctx));
-	if (composite_nomem(subreq, c)) return c;
-	tevent_req_set_callback(subreq, continue_smb2_connect, c);
-	return c;
-}
-
-
-/*
-  Receive result of a rpc connection to a rpc pipe on SMB2
-*/
-static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
-{
-	NTSTATUS status = composite_wait(c);
-	
-	talloc_free(c);
-	return status;
-}
-
-
 struct pipe_ip_tcp_state {
 	struct dcerpc_pipe_connect io;
 	const char *localaddr;
@@ -752,7 +753,6 @@ struct pipe_connect_state {
 
 static void continue_map_binding(struct composite_context *ctx);
 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
-static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
 static void continue_pipe_connect_ncacn_http(struct composite_context *ctx);
@@ -791,15 +791,12 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
 	struct dcerpc_pipe_connect pc;
 
 	/* potential exits to another stage by sending an async request */
-	struct composite_context *ncacn_np_smb2_req;
 	struct composite_context *ncacn_np_smb_req;
 	struct composite_context *ncacn_ip_tcp_req;
 	struct composite_context *ncacn_http_req;
 	struct composite_context *ncacn_unix_req;
 	struct composite_context *ncalrpc_req;
 	enum dcerpc_transport_t transport;
-	enum protocol_types min_ipc_protocol;
-	uint32_t flags;
 
 	/* dcerpc pipe connect input parameters */
 	ZERO_STRUCT(pc);
@@ -810,29 +807,16 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
 	pc.resolve_ctx  = lpcfg_resolve_context(s->lp_ctx);
 
 	transport = dcerpc_binding_get_transport(s->binding);
-	flags = dcerpc_binding_get_flags(s->binding);
-
-	min_ipc_protocol = lpcfg_client_ipc_min_protocol(s->lp_ctx);
-	if (min_ipc_protocol >= PROTOCOL_SMB2_02) {
-		flags |= DCERPC_SMB2;
-	}
 
 	/* connect dcerpc pipe depending on required transport */
 	switch (transport) {
 	case NCACN_NP:
-		if (flags & DCERPC_SMB2) {
-			/* new varient of SMB a.k.a. SMB2 */
-			ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc, s->lp_ctx);
-			composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
-			return;
-
-		} else {
-			/* good old ordinary SMB */
-			ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
-			composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
-			return;
-		}
-		break;
+		/*
+		 * SMB1/2/3...
+		 */
+		ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
+		composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
+		return;
 
 	case NCACN_IP_TCP:
 		ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
@@ -865,24 +849,6 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
 }
 
 
-/*
-  Stage 3 of pipe_connect_b: Receive result of pipe connect request on
-  named pipe on smb2
-*/
-static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
-{
-	struct composite_context *c = talloc_get_type(ctx->async.private_data,
-						      struct composite_context);
-	struct pipe_connect_state *s = talloc_get_type(c->private_data,
-						       struct pipe_connect_state);
-
-	c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
-	if (!composite_is_ok(c)) return;
-
-	continue_pipe_connect(c, s);
-}
-
-
 /*
   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
   named pipe on smb
-- 
2.17.1


From 4b946dc79050564c70f59a86aedfc6cb40bd2350 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 19 Jul 2018 07:34:11 +0200
Subject: [PATCH 12/15] s3:selftest: run rpc.lsa.lookupsids also with explicit
 [smb1] and [smb2]

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/selftest/tests.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index a061483c5f5f..bf0ba2a44546 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -581,7 +581,7 @@ for t in tests:
 
 
 test = 'rpc.lsa.lookupsids'
-auth_options = ["", "ntlm", "spnego", "spnego,ntlm" ]
+auth_options = ["", "ntlm", "spnego", "spnego,ntlm", "spnego,smb1", "spnego,smb2"]
 signseal_options = ["", ",connect", ",packet", ",sign", ",seal"]
 endianness_options = ["", ",bigendian"]
 for s in signseal_options:
-- 
2.17.1


From 778fa18127b5ae07bb61862fbf8b0756fb1175c4 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Sat, 24 Feb 2018 14:34:44 +0200
Subject: [PATCH 13/15] samba-tool trust: support discovery via netr_GetDcName

In case a remote DC does not support netr_DsRGetDCNameEx2(),
use netr_GetDcName() instead.

This should help with FreeIPA where embedded smbd runs as a domain
controller but does not implement full Active Directory compatibility.

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

Signed-off-by: Alexander Bokovoy <ab at samba.org>
---
 python/samba/netcmd/domain.py | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index 555462c9615c..becbc498b9e8 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -1876,6 +1876,15 @@ class DomainTrustCommand(Command):
 
         return (policy, info)
 
+    def get_netlogon_dc_unc(self, conn, server, domain):
+        try:
+            info = conn.netr_DsRGetDCNameEx2(server,
+                                             None, 0, None, None, None,
+                                             netlogon.DS_RETURN_DNS_NAME)
+            return info.dc_unc
+        except RuntimeError:
+            return conn.netr_GetDcName(server, domain)
+
     def get_netlogon_dc_info(self, conn, server):
         info = conn.netr_DsRGetDCNameEx2(server,
                                          None, 0, None, None, None,
@@ -2509,7 +2518,8 @@ class cmd_domain_trust_create(DomainTrustCommand):
                 raise self.RemoteRuntimeError(self, error, "failed to connect netlogon server")
 
             try:
-                remote_netlogon_info = self.get_netlogon_dc_info(remote_netlogon, remote_server)
+                remote_netlogon_dc_unc = self.get_netlogon_dc_unc(remote_netlogon,
+                                                                  remote_server, domain)
             except RuntimeError as error:
                 raise self.RemoteRuntimeError(self, error, "failed to get netlogon dc info")
 
@@ -2659,9 +2669,9 @@ class cmd_domain_trust_create(DomainTrustCommand):
                         # this triggers netr_GetForestTrustInformation to our domain.
                         # and lsaRSetForestTrustInformation() remotely, but new top level
                         # names are disabled by default.
-                        remote_forest_info = remote_netlogon.netr_DsRGetForestTrustInformation(remote_netlogon_info.dc_unc,
-                                                                      local_lsa_info.dns_domain.string,
-                                                                      netlogon.DS_GFTI_UPDATE_TDO)
+                        remote_forest_info = remote_netlogon.netr_DsRGetForestTrustInformation(remote_netlogon_dc_unc,
+                                                                                               local_lsa_info.dns_domain.string,
+                                                                                               netlogon.DS_GFTI_UPDATE_TDO)
                     except RuntimeError as error:
                         raise self.RemoteRuntimeError(self, error, "netr_DsRGetForestTrustInformation() failed")
 
@@ -2712,10 +2722,10 @@ class cmd_domain_trust_create(DomainTrustCommand):
                 if remote_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_OUTBOUND:
                     self.outf.write("Validating incoming trust...\n")
                     try:
-                        remote_trust_verify = remote_netlogon.netr_LogonControl2Ex(remote_netlogon_info.dc_unc,
-                                                                      netlogon.NETLOGON_CONTROL_TC_VERIFY,
-                                                                      2,
-                                                                      local_lsa_info.dns_domain.string)
+                        remote_trust_verify = remote_netlogon.netr_LogonControl2Ex(remote_netlogon_dc_unc,
+                                                                                   netlogon.NETLOGON_CONTROL_TC_VERIFY,
+                                                                                   2,
+                                                                                   local_lsa_info.dns_domain.string)
                     except RuntimeError as error:
                         raise self.RemoteRuntimeError(self, error, "NETLOGON_CONTROL_TC_VERIFY failed")
 
-- 
2.17.1


From fee54c664684b46f6079d157b5b43c78364f4b48 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Fri, 16 Feb 2018 18:15:28 +0200
Subject: [PATCH 14/15] TODO: krb5-samba: interdomain trust uses different salt
 principal

Salt principal for the interdomain trust is krbtgt/DOMAIN at REALM where
DOMAIN is the sAMAccountName without the dollar sign ($)

The salt principal for the BLA$ user object was generated wrong.

dn: CN=bla.base,CN=System,DC=w4edom-l4,DC=base
securityIdentifier: S-1-5-21-4053568372-2049667917-3384589010
trustDirection: 3
trustPartner: bla.base
trustPosixOffset: -2147483648
trustType: 2
trustAttributes: 8
flatName: BLA

dn: CN=BLA$,CN=Users,DC=w4edom-l4,DC=base
userAccountControl: 2080
primaryGroupID: 513
objectSid: S-1-5-21-278041429-3399921908-1452754838-1597
accountExpires: 9223372036854775807
sAMAccountName: BLA$
sAMAccountType: 805306370
pwdLastSet: 131485652467995000

The salt stored by Windows in the package_PrimaryKerberosBlob
(within supplementalCredentials) seems to be
'W4EDOM-L4.BASEkrbtgtBLA' for the above trust
and Samba stores 'W4EDOM-L4.BASEBLA$'.

While the salt used when building the keys from
trustAuthOutgoing/trustAuthIncoming is
'W4EDOM-L4.BASEkrbtgtBLA.BASE', which we handle correct.

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

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

TODO: Signed-off-by: Alexander Bokovoy <ab at samba.org>
TODO: Signed-off-by: Stefan Metzmacher <metze at samba.org>

TODO: unit tests: loop over all account types with, loop over names with
and without upn, with and without '$'. Use 'eXaMpLe.COM' and similar
names to check the correct upper/lower case result.

TODO: Also verify this against windows...
A test can create objects via ldap and/or lsa (for trusts)
then get the object including supplementalCredentials
via drsuapi (as admin) and check the stored salt.
We should have similar tests already.
---
 auth/credentials/credentials_krb5.c           | 16 +++--
 lib/krb5_wrap/krb5_samba.c                    | 61 ++++++++++++++-----
 lib/krb5_wrap/krb5_samba.h                    |  2 +-
 source3/passdb/machine_account_secrets.c      |  3 +-
 .../dsdb/samdb/ldb_modules/password_hash.c    |  6 +-
 5 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index 9da1aa09250d..d36797bf0f37 100644
--- a/auth/credentials/credentials_krb5.c
+++ b/auth/credentials/credentials_krb5.c
@@ -34,6 +34,7 @@
 #include "auth/kerberos/kerberos_util.h"
 #include "auth/kerberos/pac_utils.h"
 #include "param/param.h"
+#include "../libds/common/flags.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
@@ -974,7 +975,7 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
 	const char *upn = NULL;
 	const char *realm = cli_credentials_get_realm(cred);
 	char *salt_principal = NULL;
-	bool is_computer = false;
+	uint32_t uac_flags = 0;
 
 	if (cred->keytab_obtained >= (MAX(cred->principal_obtained, 
 					  cred->username_obtained))) {
@@ -999,9 +1000,15 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
 
 	switch (cred->secure_channel_type) {
 	case SEC_CHAN_WKSTA:
-	case SEC_CHAN_BDC:
 	case SEC_CHAN_RODC:
-		is_computer = true;
+		uac_flags = UF_WORKSTATION_TRUST_ACCOUNT;
+		break;
+	case SEC_CHAN_BDC:
+		uac_flags = UF_SERVER_TRUST_ACCOUNT;
+		break;
+	case SEC_CHAN_DOMAIN:
+	case SEC_CHAN_DNS_DOMAIN:
+		uac_flags = UF_INTERDOMAIN_TRUST_ACCOUNT;
 		break;
 	default:
 		upn = cli_credentials_get_principal(cred, mem_ctx);
@@ -1009,13 +1016,14 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
 			TALLOC_FREE(mem_ctx);
 			return ENOMEM;
 		}
+		uac_flags = UF_NORMAL_ACCOUNT;
 		break;
 	}
 
 	ret = smb_krb5_salt_principal(realm,
 				      username, /* sAMAccountName */
 				      upn, /* userPrincipalName */
-				      is_computer,
+				      uac_flags,
 				      mem_ctx,
 				      &salt_principal);
 	if (ret) {
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
index 7e90913beb0f..a6ff97640cae 100644
--- a/lib/krb5_wrap/krb5_samba.c
+++ b/lib/krb5_wrap/krb5_samba.c
@@ -24,6 +24,7 @@
 #include "system/filesys.h"
 #include "krb5_samba.h"
 #include "lib/crypto/crypto.h"
+#include "../libds/common/flags.h"
 
 #ifdef HAVE_COM_ERR_H
 #include <com_err.h>
@@ -445,8 +446,7 @@ int smb_krb5_get_pw_salt(krb5_context context,
  * @param[in]  userPrincipalName  The userPrincipalName attribute of the object
  *                                or NULL is not available.
  *
- * @param[in]  is_computer        The indication of the object includes
- *                                objectClass=computer.
+ * @param[in]  uac_flags          UF_ACCOUNT_TYPE_MASKed userAccountControl field
  *
  * @param[in]  mem_ctx            The TALLOC_CTX to allocate _salt_principal.
  *
@@ -459,7 +459,7 @@ int smb_krb5_get_pw_salt(krb5_context context,
 int smb_krb5_salt_principal(const char *realm,
 			    const char *sAMAccountName,
 			    const char *userPrincipalName,
-			    bool is_computer,
+			    uint32_t uac_flags,
 			    TALLOC_CTX *mem_ctx,
 			    char **_salt_principal)
 {
@@ -480,6 +480,23 @@ int smb_krb5_salt_principal(const char *realm,
 		return EINVAL;
 	}
 
+	if (uac_flags & ~UF_ACCOUNT_TYPE_MASK) {
+		/*
+		 * catch callers which still
+		 * pass 'true'.
+		 */
+		TALLOC_FREE(frame);
+		return EINVAL;
+	}
+	if (uac_flags == 0) {
+		/*
+		 * catch callers which still
+		 * pass 'false'.
+		 */
+		TALLOC_FREE(frame);
+		return EINVAL;
+	}
+
 	upper_realm = strupper_talloc(frame, realm);
 	if (upper_realm == NULL) {
 		TALLOC_FREE(frame);
@@ -493,7 +510,7 @@ int smb_krb5_salt_principal(const char *realm,
 	/*
 	 * Determine a salting principal
 	 */
-	if (is_computer) {
+	if (uac_flags & UF_TRUST_ACCOUNT_MASK) {
 		int computer_len = 0;
 		char *tmp = NULL;
 
@@ -502,20 +519,32 @@ int smb_krb5_salt_principal(const char *realm,
 			computer_len -= 1;
 		}
 
-		tmp = talloc_asprintf(frame, "host/%*.*s.%s",
-				      computer_len, computer_len,
-				      sAMAccountName, realm);
-		if (tmp == NULL) {
-			TALLOC_FREE(frame);
-			return ENOMEM;
-		}
+		if (uac_flags & UF_INTERDOMAIN_TRUST_ACCOUNT) {
+			principal = talloc_asprintf(frame, "krbtgt/%*.*s",
+						    computer_len, computer_len,
+						    sAMAccountName);
+			if (principal == NULL) {
+				TALLOC_FREE(frame);
+				return ENOMEM;
+			}
+		} else {
 
-		principal = strlower_talloc(frame, tmp);
-		TALLOC_FREE(tmp);
-		if (principal == NULL) {
-			TALLOC_FREE(frame);
-			return ENOMEM;
+			tmp = talloc_asprintf(frame, "host/%*.*s.%s",
+					      computer_len, computer_len,
+					      sAMAccountName, realm);
+			if (tmp == NULL) {
+				TALLOC_FREE(frame);
+				return ENOMEM;
+			}
+
+			principal = strlower_talloc(frame, tmp);
+			TALLOC_FREE(tmp);
+			if (principal == NULL) {
+				TALLOC_FREE(frame);
+				return ENOMEM;
+			}
 		}
+
 		principal_len = strlen(principal);
 
 	} else if (userPrincipalName != NULL) {
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h
index 315d3c3492e6..8305c1f77af0 100644
--- a/lib/krb5_wrap/krb5_samba.h
+++ b/lib/krb5_wrap/krb5_samba.h
@@ -353,7 +353,7 @@ int smb_krb5_get_pw_salt(krb5_context context,
 int smb_krb5_salt_principal(const char *realm,
 			    const char *sAMAccountName,
 			    const char *userPrincipalName,
-			    bool is_computer,
+			    uint32_t uac_flags,
 			    TALLOC_CTX *mem_ctx,
 			    char **_salt_principal);
 int smb_krb5_salt_principal2data(krb5_context context,
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index 94a7e21c8098..a96bf1c0b6ac 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -36,6 +36,7 @@
 #include "lib/crypto/crypto.h"
 #include "lib/krb5_wrap/krb5_samba.h"
 #include "lib/util/time_basic.h"
+#include "../libds/common/flags.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
@@ -1601,7 +1602,7 @@ NTSTATUS secrets_store_JoinCtx(const struct libnet_JoinCtx *r)
 		ret = smb_krb5_salt_principal(info->domain_info.dns_domain.string,
 					      info->account_name,
 					      NULL /* userPrincipalName */,
-					      true /* is_computer */,
+					      UF_WORKSTATION_TRUST_ACCOUNT,
 					      info, &p);
 		if (ret != 0) {
 			status = krb5_to_nt_status(ret);
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 58ae64537eb6..5f5710330044 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -130,7 +130,6 @@ struct setup_password_fields_io {
 		NTTIME pwdLastSet;
 		const char *sAMAccountName;
 		const char *user_principal_name;
-		bool is_computer;
 		bool is_krbtgt;
 		uint32_t restrictions;
 		struct dom_sid *account_sid;
@@ -678,15 +677,17 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 	krb5_data salt;
 	krb5_keyblock key;
 	krb5_data cleartext_data;
+	uint32_t uac_flags = 0;
 
 	ldb = ldb_module_get_ctx(io->ac->module);
 	cleartext_data.data = (char *)io->n.cleartext_utf8->data;
 	cleartext_data.length = io->n.cleartext_utf8->length;
 
+	uac_flags = io->u.userAccountControl & UF_ACCOUNT_TYPE_MASK;
 	krb5_ret = smb_krb5_salt_principal(io->ac->status->domain_data.realm,
 					   io->u.sAMAccountName,
 					   io->u.user_principal_name,
-					   io->u.is_computer,
+					   uac_flags,
 					   io->ac,
 					   &salt_principal);
 	if (krb5_ret) {
@@ -3190,7 +3191,6 @@ static int setup_io(struct ph_context *ac,
 								      "sAMAccountName", NULL);
 	io->u.user_principal_name	= ldb_msg_find_attr_as_string(info_msg,
 								      "userPrincipalName", NULL);
-	io->u.is_computer		= ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
 
 	/* Ensure it has an objectSID too */
 	io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
-- 
2.17.1


From 80f157adf683f18e0eba0343a3af0f9aee6a72b0 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Fri, 16 Feb 2018 18:15:28 +0200
Subject: [PATCH 15/15] TODO s4:selftest: test interdomain trust uses different
 salt principal

To test it, add a blackbox test that ensures we pass a keytab-based
authentication with a TDO account from a trusted domain.

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

Signed-off-by: Alexander Bokovoy <ab at samba.org>

TODO: move before fix and add selftest/knownfail.d/ entry
---
 source4/selftest/tests.py      |  1 +
 testprogs/blackbox/test_tdo.sh | 44 ++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100755 testprogs/blackbox/test_tdo.sh

diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 978a52000552..d1fca008d0a0 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -428,6 +428,7 @@ plantestsuite("samba4.blackbox.trust_token", "fl2008r2dc", [os.path.join(bbdir,
 plantestsuite("samba4.blackbox.trust_token", "fl2003dc", [os.path.join(bbdir, "test_trust_token.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$DOMSID', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$TRUST_DOMSID', 'external'])
 plantestsuite("samba4.blackbox.ktpass(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(bbdir, "test_ktpass.sh"), '$PREFIX/ad_dc_ntvfs'])
 plantestsuite("samba4.blackbox.password_settings(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_password_settings.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"])
+plantestsuite("samba4.blackbox.kinit_trust_tdo(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_tdo.sh"), '$PREFIX', '$REALM', '$DOMAIN', '$TRUST_REALM', '$TRUST_DOMAIN'])
 plantestsuite("samba4.blackbox.cifsdd(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(samba4srcdir, "client/tests/test_cifsdd.sh"), '$SERVER', '$USERNAME', '$PASSWORD', "$DOMAIN"])
 plantestsuite("samba4.blackbox.nmblookup(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(samba4srcdir, "utils/tests/test_nmblookup.sh"), '$NETBIOSNAME', '$NETBIOSALIAS', '$SERVER', '$SERVER_IP', nmblookup4])
 plantestsuite("samba4.blackbox.locktest(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(samba4srcdir, "torture/tests/test_locktest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX'])
diff --git a/testprogs/blackbox/test_tdo.sh b/testprogs/blackbox/test_tdo.sh
new file mode 100755
index 000000000000..bcbdbdfdada1
--- /dev/null
+++ b/testprogs/blackbox/test_tdo.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+if [ $# -lt 1 ]; then
+cat <<EOF
+Usage: test_tdo.sh PREFIX OUR_REALM OUR_FLAT REMOTE_REALM REMOTE_FLAT
+EOF
+exit 1;
+fi
+
+PREFIX="$1"
+OUR_REALM="$2"
+OUR_FLAT="$3"
+REMOTE_REALM="$4"
+REMOTE_FLAT="$5"
+shift 5
+
+. `dirname $0`/subunit.sh
+
+
+samba_tool="$BINDIR/samba-tool"
+samba4bindir="$BINDIR"
+samba4srcdir="$SRCDIR/source4"
+samba4kinit="kinit -k"
+if test -x $BINDIR/samba4kinit; then
+	samba4kinit="$BINDIR/samba4kinit --use-keytab"
+fi
+
+KEYTAB="$PREFIX/tmptdo.keytab"
+
+KRB5_TRACE=/dev/stderr
+export KRB5_TRACE
+
+testit "retrieve keytab for TDO of $REMOTE_REALM" $samba_tool domain exportkeytab $KEYTAB $CONFIGURATION --principal "$REMOTE_FLAT\$@$OUR_REALM" || failed=`expr $failed + 1`
+
+KRB5CCNAME="$PREFIX/tmptdo.ccache"
+export KRB5CCNAME
+
+rm -f $KRB5CCNAME
+
+testit "kinit with keytab for TDO of $REMOTE_REALM" $samba4kinit -t $KEYTAB "$REMOTE_FLAT\$@$OUR_REALM" || failed=`expr $failed + 1`
+
+rm -f $KRB5CCNAME $KEYTAB
+
+exit $failed
-- 
2.17.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20180719/98c06a1d/signature-0001.sig>


More information about the samba-technical mailing list