[PR PATCH] [Updated] samba-tool domain trust: fix trust compatibility to Windows Server 1709 and FreeIPA
Stefan Metzmacher
metze at samba.org
Mon Jul 23 22:04:36 UTC 2018
Hi Alexander,
here's a patchset that passes all tests.
See https://gitlab.com/samba-team/devel/samba/pipelines/26290634
Please review and push:-)
Thanks!
metze
Am 19.07.2018 um 13:35 schrieb Alexander Bokovoy via samba-technical:
> On to, 19 heinä 2018, Stefan Metzmacher wrote:
>> 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.
> Thanks, they look good to me but python/samba/auth_log.py failed due to
> unexpected SMB to SMB2 upgrade. Attached patch should fix a test.
>
> There is also a failure:
>
> ERROR: Testsuite[samba4.rpc.lsa.secrets on ncacn_np with with -k no --option=gensec:spnego=no --option=clientntlmv2auth=yes(nt4_dc)]
>
>>
>> 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?
> Unfortunately not until second half of August. If you have time to do it
> before that, it would be appreciated.
>
-------------- next part --------------
From 1d7c4f1f38fa4fe6ed96f2c04264185611204f71 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 01/16] 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 a3050ad2c6ebe46a67acf79d2341bd1e3296ce07 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 02/16] 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 e69abf9e9a2a81890dd73e9454476fa65fa458e6 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 03/16] 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 dcfa5fd44c84dc5173e902b58baf60bcb75d24d7 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 04/16] 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 336c65cae5236b3d2eb9bf4bb0e34d9e5793d88c 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 05/16] 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 8b808f57d73007f236b817de0608b74421e80dd8 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 06/16] 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 94dc4448ebd2027473063aebeffb4c99c31fb92d 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 07/16] 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 1e7d58a58ae9a0d193d17366df6b689c2cd5f56b 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 08/16] 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 285d073dbaf28eead0c5b1dc318cc0a11f6b39c3 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 09/16] 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 +++++++++++++++++++++++++++++
source4/librpc/rpc/dcerpc_connect.c | 1 +
2 files changed, 33 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,
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index a3f25efc0b47..d31bbe152e3e 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,
+ false, /* fallback_to_anonymous */
NULL, /* existing_conn */
0, /* previous_session_id */
&options,
--
2.17.1
From a6724b488f94543c72bd61c6f0fa07ea7950886c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 19 Jul 2018 23:04:33 +0200
Subject: [PATCH 10/16] s4:libcli: allow a fallback to NTLMSSP if SPNEGO is not
supported locally
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/libcli/smb2/session.c | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c
index b2cb8384f959..e94512d3d337 100644
--- a/source4/libcli/smb2/session.c
+++ b/source4/libcli/smb2/session.c
@@ -195,13 +195,38 @@ struct tevent_req *smb2_session_setup_spnego_send(
if (state->out_secblob.length > 0) {
chosen_oid = GENSEC_OID_SPNEGO;
+ status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to start set GENSEC client mechanism %s: %s\n",
+ gensec_get_name_by_oid(session->gensec,
+ chosen_oid),
+ nt_errstr(status)));
+ state->out_secblob = data_blob_null;
+ chosen_oid = GENSEC_OID_NTLMSSP;
+ status = gensec_start_mech_by_oid(session->gensec,
+ chosen_oid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to start set (fallback) GENSEC client mechanism %s: %s\n",
+ gensec_get_name_by_oid(session->gensec,
+ chosen_oid),
+ nt_errstr(status)));
+ }
+ }
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
} else {
chosen_oid = GENSEC_OID_NTLMSSP;
- }
-
- status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
- if (tevent_req_nterror(req, status)) {
- return tevent_req_post(req, ev);
+ status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to start set GENSEC client mechanism %s: %s\n",
+ gensec_get_name_by_oid(session->gensec,
+ chosen_oid),
+ nt_errstr(status)));
+ }
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
}
smb2_session_setup_spnego_gensec_next(req);
--
2.17.1
From 7952f64d93641760fc3fbf1a8057a3fee3bdb461 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 11/16] 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 | 209 +++++++++++++++++++
source4/libcli/smb_composite/smb_composite.h | 22 ++
source4/libcli/wscript_build | 20 +-
3 files changed, 246 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..39fef7f8f274
--- /dev/null
+++ b/source4/libcli/smb_composite/connect_nego.c
@@ -0,0 +1,209 @@
+/*
+ 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;
+ const char *target_hostname;
+ 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 *target_hostname,
+ 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;
+ state->target_hostname = target_hostname;
+
+ 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->target_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..e43cbb9dff92 100644
--- a/source4/libcli/smb_composite/smb_composite.h
+++ b/source4/libcli/smb_composite/smb_composite.h
@@ -101,6 +101,28 @@ 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 *target_hostname,
+ 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 d745e059084a74fd7dae7777937d8cff52a88e91 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Thu, 19 Jul 2018 14:07:39 +0300
Subject: [PATCH 12/16] tests/auth_log: Permit SMB2 service description if
empty binding is used for kerberos authentication
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13308
Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Alexander Bokovoy <ab at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/tests/auth_log.py | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/python/samba/tests/auth_log.py b/python/samba/tests/auth_log.py
index cb524d0ed81c..4704b925de58 100644
--- a/python/samba/tests/auth_log.py
+++ b/python/samba/tests/auth_log.py
@@ -28,6 +28,7 @@ from samba.credentials import DONT_USE_KERBEROS, MUST_USE_KERBEROS
from samba import NTSTATUSError
from subprocess import call
from ldb import LdbError
+import re
class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase):
@@ -65,6 +66,20 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase):
messages = self.waitForMessages(isLastExpectedMessage, x)
checkFunction(messages, authTypes, service, binding, protection)
+ def _assert_ncacn_np_serviceDescription(self, binding, serviceDescription):
+ # Turn "[foo,bar]" into a list ("foo", "bar") to test
+ # lambda x: x removes anything that evaluates to False,
+ # including empty strings, so we handle "" as well
+ binding_list = filter(lambda x: x, re.compile('[\[,\]]').split(binding))
+
+ # Handle explicit smb2, smb1 or auto negotiation
+ if "smb2" in binding_list:
+ self.assertEquals(serviceDescription, "SMB2")
+ elif "smb1" in binding_list:
+ self.assertEquals(serviceDescription, "SMB")
+ else:
+ self.assertIn(serviceDescription, ["SMB", "SMB2"])
+
def rpc_ncacn_np_ntlm_check(self, messages, authTypes, service,
binding, protection):
@@ -77,7 +92,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase):
msg = messages[0]
self.assertEquals("Authentication", msg["type"])
self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"])
- self.assertEquals("SMB",
+ self._assert_ncacn_np_serviceDescription(binding,
msg["Authentication"]["serviceDescription"])
self.assertEquals(authTypes[1],
msg["Authentication"]["authDescription"])
@@ -85,7 +100,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase):
# Check the second message it should be an Authorization
msg = messages[1]
self.assertEquals("Authorization", msg["type"])
- self.assertEquals("SMB",
+ self._assert_ncacn_np_serviceDescription(binding,
msg["Authorization"]["serviceDescription"])
self.assertEquals(authTypes[2], msg["Authorization"]["authType"])
self.assertEquals("SMB", msg["Authorization"]["transportProtection"])
@@ -145,12 +160,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase):
# Check the third message it should be an Authorization
msg = messages[2]
self.assertEquals("Authorization", msg["type"])
- serviceDescription = "SMB"
- print("binding %s" % binding)
- if binding == "[smb2]":
- serviceDescription = "SMB2"
-
- self.assertEquals(serviceDescription,
+ self._assert_ncacn_np_serviceDescription(binding,
msg["Authorization"]["serviceDescription"])
self.assertEquals(authTypes[3], msg["Authorization"]["authType"])
self.assertEquals("SMB", msg["Authorization"]["transportProtection"])
--
2.17.1
From b226e810c935944213b9a1860ce50259639998c3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 23 Jul 2018 00:17:35 +0200
Subject: [PATCH 13/16] python/tests: use explicit "client ipc max protocol =
NT1" for samba.tests.net_join_no_spnego
The tests rely on SMB1.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13308
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/tests/net_join_no_spnego.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/python/samba/tests/net_join_no_spnego.py b/python/samba/tests/net_join_no_spnego.py
index 85c6f888d441..e4dd078f2f65 100644
--- a/python/samba/tests/net_join_no_spnego.py
+++ b/python/samba/tests/net_join_no_spnego.py
@@ -42,6 +42,7 @@ class NetJoinNoSpnegoTests(samba.tests.TestCaseInTempDir):
super(NetJoinNoSpnegoTests, self).tearDown()
def test_net_join_no_spnego(self):
+ self.lp.set("client ipc max protocol", "NT1")
self.lp.set("client use spnego", "no")
netbios_name = "NetJoinNoSpnego"
machinepass = "abcdefghij"
@@ -65,6 +66,7 @@ class NetJoinNoSpnegoTests(samba.tests.TestCaseInTempDir):
self.fail("Shoud have rejected NTLMv2 without SPNEGO")
def test_net_join_no_spnego_ntlmv1(self):
+ self.lp.set("client ipc max protocol", "NT1")
self.lp.set("client use spnego", "no")
self.lp.set("client ntlmv2 auth", "no")
netbios_name = "NetJoinNoSpnego"
--
2.17.1
From bb5c2e380a698a0fdd52fcdcbd51a529ab33308e 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 14/16] 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 | 259 +++++++++++++---------------
1 file changed, 120 insertions(+), 139 deletions(-)
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index d31bbe152e3e..c23e85e7cb19 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -36,6 +36,7 @@
#include "param/param.h"
#include "libcli/resolve/resolve.h"
#include "lib/http/http.h"
+#include "lib/util/util_net.h"
struct dcerpc_pipe_connect {
struct dcecli_connection *conn;
@@ -76,6 +77,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 +135,12 @@ 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 *target_hostname = NULL;
+ const char *dest_address = NULL;
+ const char *calling_name = NULL;
/* composite context allocation and setup */
c = composite_create(mem_ctx, io->conn->event_ctx);
@@ -152,12 +158,17 @@ 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 */
+ target_hostname = dcerpc_binding_get_string_option(s->io.binding, "target_hostname");
conn->in.dest_host = dcerpc_binding_get_string_option(s->io.binding, "host");
conn->in.dest_ports = lpcfg_smb_ports(lp_ctx);
- conn->in.called_name =
- dcerpc_binding_get_string_option(s->io.binding, "target_hostname");
+ conn->in.called_name = target_hostname;
if (conn->in.called_name == NULL) {
conn->in.called_name = "*SMBSERVER";
}
@@ -184,21 +195,113 @@ 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";
+ }
+
+ if (target_hostname == NULL) {
+ target_hostname = conn->in.dest_host;
+ }
+
+ if (is_ipaddress(conn->in.dest_host)) {
+ dest_address = conn->in.dest_host;
+ }
+
+ subreq = smb_connect_nego_send(s,
+ c->event_ctx,
+ s->io.resolve_ctx,
+ &conn->in.options,
+ conn->in.socket_options,
+ conn->in.dest_host,
+ dest_address,
+ conn->in.dest_ports,
+ target_hostname,
+ 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) {
+ /*
+ * continue with smb2 session setup/tree connect
+ * on the established connection.
+ */
+ 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;
+ }
+
+ /*
+ * continue with smb1 session setup/tree connect
+ * on the established connection.
+ */
+ 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,93 +341,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,
- false, /* fallback_to_anonymous */
- 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;
@@ -753,7 +769,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);
@@ -792,15 +807,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);
@@ -811,29 +823,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);
@@ -866,24 +865,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 56c826f3dfbe41f21d7673072b9269579e8b190f 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 15/16] 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 3637204a8f4a6e4f4d14c45d15f6ad9252d14134 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 16/16] 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
-------------- 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/20180724/a6eba99b/signature.sig>
More information about the samba-technical
mailing list