Bug 14987 - Test smb2.notify.invalid-reauth.invalid-reauth fails when encyrption is enabled
Summary: Test smb2.notify.invalid-reauth.invalid-reauth fails when encyrption is enabled
Status: NEW
Alias: None
Product: Samba 4.1 and newer
Classification: Unclassified
Component: File services (show other bugs)
Version: 4.15.2
Hardware: All Linux
: P5 normal (vote)
Target Milestone: ---
Assignee: Samba QA Contact
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-02-22 20:25 UTC by Sri
Modified: 2022-02-24 15:12 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sri 2022-02-22 20:25:55 UTC
We’re seeing the smb2.notify.invalid-reauth.invalid-reauth test fail in samba 4.15.2 because there was a check added at the end of it that doesn’t pass when encryption is enabled on the share. This was added within the last year.

The added check is:

```
/*
 * Demonstrate that the session is no longer valid.
 */
status = smb2_create(tree1, torture, &(io.smb2));
CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
```

The failure that is generated when we add ‘server smb encrypt = required’ to the share in smb.conf is:

```
failure: invalid-reauth [
(../../source4/torture/smb2/notify.c:1719) Incorrect status NT_STATUS_CONNECTION_DISCONNECTED - should be NT_STATUS_USER_SESSION_DELETED
]
```

I believe this check was added to the test as part of commit 30fa5a45c2df42cc5c28a912cb4f11f514a89390 for https://bugzilla.samba.org/show_bug.cgi?id=14512

What I can see in level 10 log files when I run the test with and without encryption enabled is that the passing test without encryption enabled logs this:

```
smbd_smb2_request_error_ex: smbd_smb2_request_error_ex: idx[1] status[NT_STATUS_USER_SESSION_DELETED] 
```

And the failing test with encryption enabled logs this:

```
smbd_server_connection_terminate_ex: conn[ptr=0x5604be601190,id=0,addr=ipv4:127.0.0.1:43176] num_ok[0] reason[NT_STATUS_USER_SESSION_DELETED]

```

So, we can see that in one case, we’re returning an error status while in the second case, we’re terminating with an error status.

In the failing case, this message is logged just before the ‘terminate' message (and is not seen in the passing case):

```
invalid session[3362368276] in SMB2_TRANSFORM header

```

Tracking down that message in the code base, we can see that it comes from smbd_smb2_inbuf_parse_compound() in source3/smbd/smb2_server.c (I also added some additional logging to show that the routine is called from smbd_smb2_io_handler()). Note that both the passing and failing cases follow this code path.

The difference is that the failing case falls into this ‘if’ statement in smbd_smb2_inbuf_parse_compound():

```
if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
```

That makes sense because I see SMB2_TF_MAGIC being set earlier within an ‘if (req->do_encryption)’ statement.

So, in the failing case, we eventually hit this within the ‘if’ statement (which includes the log message we saw):

```
if (s == NULL) {
        DEBUG(1, ("invalid session[%llu] in "
                  "SMB2_TRANSFORM header\n",
                    (unsigned long long)uid));
        TALLOC_FREE(iov_alloc);
        return NT_STATUS_USER_SESSION_DELETED;
}
```

So, smbd_smb2_inbuf_parse_compound() is returning NT_STATUS_USER_SESSION_DELETED in the failing case and NT_STATUS_OK in the passing case.

The return value of NT_STATUS_USER_SESSION_DELETED causes smbd_smb2_io_handler() to immediately return without dispatching and instead terminate the connection:

```
status = smbd_smb2_io_handler(xconn, flags);
if (!NT_STATUS_IS_OK(status)) {
        smbd_server_connection_terminate(xconn, nt_errstr(status));
        return;
}
```

So, in summary, I’m not sure what’s at fault here.

The product is behaving differently in the USER_SESSION_DELETE situation depending on whether encryption is enabled. That might be fine, in which case the test is making a wrong assumption.

So this is either a product bug or a test bug.
Comment 1 Stefan Metzmacher 2022-02-23 08:13:14 UTC
Other tests in the same file use this:

        if (encrypted) {
                torture_assert_goto(tctx, !smbXcli_conn_is_connected(transport1->conn), ret, done,
                                                "smb2_util_unlink worked");
        } else {
                torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_USER_SESSION_DELETED, ret, done,
                                                "smb2_util_unlink worked");
        }

I think we should use the same here
Comment 2 Stefan Metzmacher 2022-02-23 08:14:48 UTC
(In reply to Stefan Metzmacher from comment #1)

Sorry, not the same file but source4/torture/smb2/session.c
Comment 3 Sri 2022-02-23 12:19:53 UTC
Will try testing with the added code and report back results.  Thank you.
Comment 4 Sri 2022-02-24 15:12:33 UTC
The suggested workaround fixed the issue, thanks!

Here's the patch for the fix:

diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index d82ddab..831ac01 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -1586,6 +1586,7 @@ static bool torture_smb2_notify_invalid_reauth(struct torture_context *torture,
 	struct smb2_handle h1;
 	struct smb2_request *req;
 	struct cli_credentials *invalid_creds;
+	bool encrypted;
 
 	smb2_deltree(tree2, BASEDIR_IR);
 	smb2_util_rmdir(tree2, BASEDIR_IR);
@@ -1650,8 +1651,14 @@ static bool torture_smb2_notify_invalid_reauth(struct torture_context *torture,
 	/*
 	 * Demonstrate that the session is no longer valid.
 	 */
+	encrypted = smb2cli_tcon_is_encryption_on(tree1->smbXcli);
 	status = smb2_create(tree1, torture, &(io.smb2));
-	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+	if (encrypted) {
+		CHECK_STATUS(status, NT_STATUS_CONNECTION_DISCONNECTED);
+	} else {
+		CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+	}
+
 done:
 	smb2_deltree(tree2, BASEDIR_IR);
 	return ret;
-- 
2.19.1