From 137139a8d0889dc9a4347255ef4f40ef61490838 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Aug 2023 15:12:05 -0700 Subject: [PATCH 1/2] s3: torture: Add a test doing an SMB1 negotiate+exit. Robert Morris noticed a missing return in reply_exit_done(). Adds knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15430 Signed-off-by: Jeremy Allison Reviewed-by: Noel Power (Back-ported from commit 63895e03c4e8ed79a3b2cda928f58ec278cd6608) --- selftest/knownfail.d/smb1_negotiate_exit | 1 + source3/selftest/tests.py | 11 ++ source3/torture/torture.c | 181 +++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 selftest/knownfail.d/smb1_negotiate_exit diff --git a/selftest/knownfail.d/smb1_negotiate_exit b/selftest/knownfail.d/smb1_negotiate_exit new file mode 100644 index 00000000000..8fd9d749686 --- /dev/null +++ b/selftest/knownfail.d/smb1_negotiate_exit @@ -0,0 +1 @@ +^samba3.smbtorture_s3.smb1.SMB1-NEGOTIATE-EXIT.smbtorture\(fileserver_smb1\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index dbf70bbe715..62f4662c9a3 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -214,6 +214,17 @@ plantestsuite("samba3.smbtorture_s3.smb1.SMB1-TRUNCATED-SESSSETUP", smbtorture3, "-mNT1"]) +plantestsuite("samba3.smbtorture_s3.smb1.SMB1-NEGOTIATE-EXIT", + "fileserver_smb1", + [os.path.join(samba3srcdir, + "script/tests/test_smbtorture_s3.sh"), + 'SMB1-NEGOTIATE-EXIT', + '//$SERVER_IP/tmp', + '$USERNAME', + '$PASSWORD', + smbtorture3, + "-mNT1"]) + # # MSDFS attribute tests. # diff --git a/source3/torture/torture.c b/source3/torture/torture.c index e6b34c4a43c..c87f0766215 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -14815,6 +14815,183 @@ static bool run_smb1_truncated_sesssetup(int dummy) return true; } +struct smb1_negotiate_exit_state { + int dummy; +}; + +static void smb1_negotiate_exit_done(struct tevent_req *subreq); + +static struct tevent_req *smb1_negotiate_exit_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbXcli_conn *conn) +{ + struct smb1_negotiate_exit_state *state = NULL; + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + + req = tevent_req_create(mem_ctx, + &state, + struct smb1_negotiate_exit_state); + if (req == NULL) { + return NULL; + } + subreq = smb1cli_req_send(state, ev, conn, + SMBexit, + 0, /* additional_flags */ + 0, /* clear_flags */ + 0, /* additional_flags2 */ + 0, /* clear_flags2 */ + 10000, /* timeout_msec */ + getpid(), + NULL, /* tcon */ + NULL, /* session */ + 0, /* wct */ + NULL, + 0, + NULL); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, + smb1_negotiate_exit_done, + req); + return req; +} + +static void smb1_negotiate_exit_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct smb1_negotiate_exit_state *state = + tevent_req_data(req, + struct smb1_negotiate_exit_state); + NTSTATUS status; + struct smb1cli_req_expected_response expected[] = { + { + .status = NT_STATUS_OK, + .wct = 0, + }, + }; + + status = smb1cli_req_recv(subreq, state, + NULL, + NULL, + NULL, + NULL, + NULL, /* pvwv_offset */ + NULL, + NULL, + NULL, /* pbytes_offset */ + NULL, + expected, ARRAY_SIZE(expected)); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); +} + +static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +static bool do_smb1_exit(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbXcli_conn *conn) +{ + struct tevent_req *req; + bool ok; + NTSTATUS status; + NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);; + + req = smb1_negotiate_exit_send(ev, ev, conn); + if (req == NULL) { + d_fprintf(stderr, "smb1_negotiate_exit_send failed\n"); + return false; + } + + ok = tevent_req_poll_ntstatus(req, ev, &status); + if (!ok) { + d_fprintf(stderr, "tevent_req_poll failed with status %s\n", + nt_errstr(status)); + return false; + } + + status = smb1_negotiate_exit_recv(req); + if (!NT_STATUS_EQUAL(status, expected_status)) { + d_fprintf(stderr, "smb1_negotiate_exit_recv returned " + "%s, expected ERRSRV, ERRinvnid\n", + nt_errstr(status)); + return false; + } + return true; +} + +static bool run_smb1_negotiate_exit(int dummy) +{ + struct tevent_context *ev; + struct smbXcli_conn *conn; + struct sockaddr_storage ss; + NTSTATUS status; + int fd; + bool ok; + + printf("Starting send SMB1 negotiate+exit.\n"); + + ok = resolve_name(host, &ss, 0x20, true); + if (!ok) { + d_fprintf(stderr, "Could not resolve name %s\n", host); + return false; + } + + status = open_socket_out(&ss, 445, 10000, &fd); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "open_socket_out failed: %s\n", + nt_errstr(status)); + return false; + } + + conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0, + NULL, 0, NULL); + if (conn == NULL) { + d_fprintf(stderr, "smbXcli_conn_create failed\n"); + return false; + } + + status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "smbXcli_negprot failed!\n"); + return false; + } + + ev = samba_tevent_context_init(talloc_tos()); + if (ev == NULL) { + d_fprintf(stderr, "samba_tevent_context_init failed\n"); + return false; + } + + /* + * Call do_smb1_exit twice to catch a server crash, the + * server sends the first return code then crashes. + */ + ok = do_smb1_exit(ev, ev, conn); + if (!ok) { + d_fprintf(stderr, "do_smb1_exit (1) failed\n"); + return false; + } + ok = do_smb1_exit(ev, ev, conn); + if (!ok) { + d_fprintf(stderr, "do_smb1_exit (2) failed\n"); + return false; + } + + TALLOC_FREE(conn); + return true; +} + static bool run_ign_bad_negprot(int dummy) { struct tevent_context *ev; @@ -15547,6 +15724,10 @@ static struct { .name = "SMB1-TRUNCATED-SESSSETUP", .fn = run_smb1_truncated_sesssetup, }, + { + .name = "SMB1-NEGOTIATE-EXIT", + .fn = run_smb1_negotiate_exit, + }, { .name = "PIDHIGH", .fn = run_pidhigh, -- 2.34.1 From 0b3777241a02c8ad499e5d27fda4a280037d073d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Aug 2023 15:19:01 -0700 Subject: [PATCH 2/2] s3: smbd: Add missing 'return;'s in exit paths in reply_exit_done(). Remove knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15430 Signed-off-by: Jeremy Allison Reviewed-by: Noel Power Autobuild-User(master): Noel Power Autobuild-Date(master): Mon Aug 14 19:52:49 UTC 2023 on atb-devel-224 (cherry picked from commit d79d0508a4b8bdc4582a350d109181ecae0bf1e2) --- selftest/knownfail.d/smb1_negotiate_exit | 1 - source3/smbd/smb1_reply.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/smb1_negotiate_exit diff --git a/selftest/knownfail.d/smb1_negotiate_exit b/selftest/knownfail.d/smb1_negotiate_exit deleted file mode 100644 index 8fd9d749686..00000000000 --- a/selftest/knownfail.d/smb1_negotiate_exit +++ /dev/null @@ -1 +0,0 @@ -^samba3.smbtorture_s3.smb1.SMB1-NEGOTIATE-EXIT.smbtorture\(fileserver_smb1\) diff --git a/source3/smbd/smb1_reply.c b/source3/smbd/smb1_reply.c index 343b7ee2b49..fbba3800b95 100644 --- a/source3/smbd/smb1_reply.c +++ b/source3/smbd/smb1_reply.c @@ -4661,6 +4661,7 @@ static void reply_exit_done(struct tevent_req *req) reply_force_doserror(smb1req, ERRSRV, ERRinvnid); smb_request_done(smb1req); END_PROFILE(SMBexit); + return; } /* @@ -4700,6 +4701,7 @@ static void reply_exit_done(struct tevent_req *req) reply_force_doserror(smb1req, ERRSRV, ERRinvnid); smb_request_done(smb1req); END_PROFILE(SMBexit); + return; } close_file_free(NULL, &fsp, SHUTDOWN_CLOSE); } -- 2.34.1