From 691a7ce0041120d20529f55d2f6e151dbe7682f4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Jul 2018 07:32:08 +0200 Subject: [PATCH 01/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 062b518cabd9fb5f72f96cdf400c978c0b844619) --- 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 4ddf4350f01c68b5d68dc6bfbf442e0d454dd854 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 15:36:31 +0200 Subject: [PATCH 02/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 17b12a9b9a9dfd859679de77aa0c7ffbc782f1bc) --- 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 59caa60e3c2346ef6dddb5926adfc8c9e5989459 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 15:36:52 +0200 Subject: [PATCH 03/15] s4:libcli: add smbcli_transport_raw_init() BUG: https://bugzilla.samba.org/show_bug.cgi?id=13308 Signed-off-by: Stefan Metzmacher Reviewed-by: Alexander Bokovoy (cherry picked from commit b7e99c2571e31971a6d7f1898e7458c16dc1031e) --- 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 935443eaa7b4ba69731d616c8fe92043b12a9f33 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 15:01:50 +0200 Subject: [PATCH 04/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 87d73397f9a9dee8fa0055a2ff08244b2c85e120) --- 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 ae5790de7820d4239aecf695b18c539dc4543813 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 15:34:55 +0200 Subject: [PATCH 05/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 2b68f9b8b0dd944fa89b9e0037886ddd4fb4e5f9) --- 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 3f7016a043e4254f7fb265ef9369ca0236fc0300 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 16:43:04 +0200 Subject: [PATCH 06/15] s4:libcli: add smb2_transport_raw_init() BUG: https://bugzilla.samba.org/show_bug.cgi?id=13308 Signed-off-by: Stefan Metzmacher Reviewed-by: Alexander Bokovoy (cherry picked from commit ce2248c4b5aad2d00155a2e77b3e6340ce824979) --- 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 f4f8ea5dcf8830473b4a24ae4deeeeb10937eae8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 16:43:32 +0200 Subject: [PATCH 07/15] s4:libcli: split out smb2_connect_session_start() BUG: https://bugzilla.samba.org/show_bug.cgi?id=13308 Signed-off-by: Stefan Metzmacher Reviewed-by: Alexander Bokovoy (cherry picked from commit 5ad5b81b6ef601596583b4ad7d6a14241fa99a71) --- 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 55eb440ac87083f991ebf9f855d60532bda06458 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 16:44:16 +0200 Subject: [PATCH 08/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit f20e607c15b4c8ae56ade5d7e68d832542a2cd5e) --- 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 373432822a39727dc879dd0a84aa5ef6dc842939 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 23:52:30 +0200 Subject: [PATCH 09/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit ca000d8901e6acb8a7c59d26d4f75c9d92bafece) --- 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 6bd183c133335c5cf17736e1b3166124855fa4f0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Jul 2018 23:04:33 +0200 Subject: [PATCH 10/15] s4:libcli: allow a fallback to NTLMSSP if SPNEGO is not supported locally Signed-off-by: Stefan Metzmacher Reviewed-by: Alexander Bokovoy (cherry picked from commit 5188454bdce80f6e2bfc45deca18bd1b7289a7a6) --- 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 e3e54cbe31a1..a8985b2542c7 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -196,13 +196,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 daf1b5dbc6629fcd8e496e800039beb92dda4c4c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 14:52:43 +0200 Subject: [PATCH 11/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit e4910f35eab008a41cfcac3d97b3647c721ac679) --- 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 . +*/ + +#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 38a8f4e07183..d895424efd14 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', + ) bld.SAMBA_PYTHON('pysmb', source='pysmb.c', -- 2.17.1 From 64eb3174cc8e3645c56f767f25ba6405194bcb23 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 19 Jul 2018 14:07:39 +0300 Subject: [PATCH 12/15] 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 Signed-off-by: Alexander Bokovoy Signed-off-by: Stefan Metzmacher (cherry picked from commit 70a9cf9ccfc4075cc08209191db1bce2c9b432fc) --- python/samba/tests/auth_log.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/auth_log.py b/python/samba/tests/auth_log.py index 6b032a80edc3..6233228fe5e1 100644 --- a/python/samba/tests/auth_log.py +++ b/python/samba/tests/auth_log.py @@ -33,6 +33,7 @@ from samba.credentials import Credentials, 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): @@ -71,6 +72,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): @@ -83,14 +98,14 @@ 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", - msg["Authentication"]["serviceDescription"]) + self._assert_ncacn_np_serviceDescription(binding, + msg["Authentication"]["serviceDescription"]) self.assertEquals(authTypes[1], msg["Authentication"]["authDescription"]) # 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"]) @@ -139,12 +154,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 0eb01513e89074012134528d991aac3e9d8f0b59 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Jul 2018 00:17:35 +0200 Subject: [PATCH 13/15] 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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 802e43bf742e756896fa73fcd139feca9ae293dd) --- 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 09a2856c9b5b..0f45913f215f 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 74471d8b74a3612e8e927d02d21bf3ca86e6f814 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 16:55:33 +0200 Subject: [PATCH 14/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 4422f7382aad3090cb959ade030a02bf4fef81ac) --- 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 85ea87fba41ce2aed020afe7188c0a5cbdc2de90 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Jul 2018 07:34:11 +0200 Subject: [PATCH 15/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 Reviewed-by: Alexander Bokovoy (cherry picked from commit 6800077c5c57c257326573537d1f2bb7a8066149) --- 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 9092c1776c8d..1e18acc80f26 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -569,7 +569,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