From 1e8309ab171b54e6eeac08113578edcbf7e8e591 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 Aug 2021 14:33:24 +0200 Subject: [PATCH 1/2] s3:libsmb: start encryption as soon as possible after the session setup For the SMB1 UNIX CIFS extensions we create a temporary IPC$ tcon, if there's no tcon yet. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14793 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 21302649c46441ea325c66457294225ddb1d6235) --- source3/libsmb/clidfs.c | 56 +++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 040b957e6f8c..5b64858ca338 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -50,6 +50,7 @@ static NTSTATUS cli_cm_force_encryption_creds(struct cli_state *c, uint16_t major, minor; uint32_t caplow, caphigh; NTSTATUS status; + bool temp_ipc = false; if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) { status = smb2cli_session_encryption_on(c->smb2.session); @@ -72,12 +73,26 @@ static NTSTATUS cli_cm_force_encryption_creds(struct cli_state *c, return NT_STATUS_NOT_SUPPORTED; } + if (c->smb1.tcon == NULL) { + status = cli_tree_connect_creds(c, "IPC$", "IPC", creds); + if (!NT_STATUS_IS_OK(status)) { + d_printf("Encryption required and " + "can't connect to IPC$ to check " + "UNIX CIFS extensions.\n"); + return NT_STATUS_UNKNOWN_REVISION; + } + temp_ipc = true; + } + status = cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh); if (!NT_STATUS_IS_OK(status)) { d_printf("Encryption required and " "can't get UNIX CIFS extensions " "version from server.\n"); + if (temp_ipc) { + cli_tdis(c); + } return NT_STATUS_UNKNOWN_REVISION; } @@ -85,6 +100,9 @@ static NTSTATUS cli_cm_force_encryption_creds(struct cli_state *c, d_printf("Encryption required and " "share %s doesn't support " "encryption.\n", sharename); + if (temp_ipc) { + cli_tdis(c); + } return NT_STATUS_UNSUPPORTED_COMPRESSION; } @@ -93,9 +111,15 @@ static NTSTATUS cli_cm_force_encryption_creds(struct cli_state *c, d_printf("Encryption required and " "setup failed with error %s.\n", nt_errstr(status)); + if (temp_ipc) { + cli_tdis(c); + } return status; } + if (temp_ipc) { + cli_tdis(c); + } return NT_STATUS_OK; } @@ -217,6 +241,22 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, DEBUG(4,(" session setup ok\n")); + if (encryption_state >= SMB_ENCRYPTION_DESIRED) { + status = cli_cm_force_encryption_creds(c, + creds, + sharename); + if (!NT_STATUS_IS_OK(status)) { + switch (encryption_state) { + case SMB_ENCRYPTION_DESIRED: + break; + case SMB_ENCRYPTION_REQUIRED: + default: + cli_shutdown(c); + return status; + } + } + } + /* here's the fun part....to support 'msdfs proxy' shares (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL here before trying to connect to the original share. @@ -241,22 +281,6 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, return status; } - if (encryption_state >= SMB_ENCRYPTION_DESIRED) { - status = cli_cm_force_encryption_creds(c, - creds, - sharename); - if (!NT_STATUS_IS_OK(status)) { - switch (encryption_state) { - case SMB_ENCRYPTION_DESIRED: - break; - case SMB_ENCRYPTION_REQUIRED: - default: - cli_shutdown(c); - return status; - } - } - } - DEBUG(4,(" tconx ok\n")); *pcli = c; return NT_STATUS_OK; -- 2.25.1 From b5094d827aca46633fa7b4cfab6524b6ef1dcb9c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 Aug 2021 15:30:12 +0200 Subject: [PATCH 2/2] s3:libsmb: close the temporary IPC$ connection in cli_full_connection() We don't need the temporary IPC$ connection used for the SMB1 UNIX CIFS extensions encryption setup anymore, so we can also let the server close it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14793 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Aug 11 23:03:11 UTC 2021 on sn-devel-184 (cherry picked from commit 289b7a1595ab13a200cfb327604e4b9296fa81e0) --- source3/libsmb/cliconnect.c | 39 +++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index b95b14b018cb..853fb344bcd6 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -3361,6 +3361,8 @@ static void cli_full_connection_creds_enc_start(struct tevent_req *req); static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq); static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq); static void cli_full_connection_creds_enc_done(struct tevent_req *subreq); +static void cli_full_connection_creds_enc_tdis(struct tevent_req *req); +static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq); static void cli_full_connection_creds_tcon_start(struct tevent_req *req); static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq); @@ -3588,7 +3590,8 @@ static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq) TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { if (encryption_state < SMB_ENCRYPTION_REQUIRED) { - cli_full_connection_creds_tcon_start(req); + /* disconnect ipc$ followed by the real tree connect */ + cli_full_connection_creds_enc_tdis(req); return; } DEBUG(10, ("%s: cli_unix_extensions_version " @@ -3599,7 +3602,8 @@ static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq) if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) { if (encryption_state < SMB_ENCRYPTION_REQUIRED) { - cli_full_connection_creds_tcon_start(req); + /* disconnect ipc$ followed by the real tree connect */ + cli_full_connection_creds_enc_tdis(req); return; } DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP " @@ -3631,6 +3635,37 @@ static void cli_full_connection_creds_enc_done(struct tevent_req *subreq) return; } + /* disconnect ipc$ followed by the real tree connect */ + cli_full_connection_creds_enc_tdis(req); +} + +static void cli_full_connection_creds_enc_tdis(struct tevent_req *req) +{ + struct cli_full_connection_creds_state *state = tevent_req_data( + req, struct cli_full_connection_creds_state); + struct tevent_req *subreq = NULL; + + subreq = cli_tdis_send(state, state->ev, state->cli); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, + cli_full_connection_creds_enc_finished, + req); +} + +static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + NTSTATUS status; + + status = cli_tdis_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + cli_full_connection_creds_tcon_start(req); } -- 2.25.1