ksmbd: handle channel binding with a different user

When an authenticated user tries to bind a channel to a session owned by a
different user, ksmbd returns STATUS_LOGON_FAILURE. Windows instead rejects
this attempt with STATUS_ACCESS_DENIED. The supplied credentials are valid
but cannot be used with the existing session.

Use a distinct internal error for a user mismatch in both NTLM and Kerberos
authentication and map it to STATUS_ACCESS_DENIED during SESSION_SETUP.
Keep ordinary authentication failures mapped to STATUS_LOGON_FAILURE.

A failed SMB 3.1.1 binding also leaves its preauthentication context on the
connection. A subsequent binding attempt for the same session reuses the
stale hash and derives an incorrect channel signing key. Remove the binding
preauthentication context on failure so a valid retry starts with a fresh
hash.

This fixes smb2.session.bind_different_user.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon
2026-07-02 20:07:25 +09:00
committed by Steve French
parent faf8578c77
commit 1c5daa2ea9
2 changed files with 16 additions and 3 deletions

View File

@@ -451,7 +451,7 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
} else {
if (!ksmbd_compare_user(sess->user, user)) {
ksmbd_debug(AUTH, "different user tried to reuse session\n");
retval = -EPERM;
retval = -EKEYREJECTED;
ksmbd_free_user(user);
goto out;
}

View File

@@ -1734,7 +1734,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
if (!ksmbd_compare_user(sess->user, user)) {
ksmbd_free_user(user);
return -EPERM;
return -EKEYREJECTED;
}
ksmbd_free_user(user);
} else {
@@ -1845,7 +1845,8 @@ static int krb5_authenticate(struct ksmbd_work *work,
out_blob, &out_len, auth_key);
if (retval) {
ksmbd_debug(SMB, "krb5 authentication failed\n");
retval = -EINVAL;
if (retval != -EKEYREJECTED)
retval = -EINVAL;
goto out;
}
@@ -2139,6 +2140,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
else if (rc == -EOPNOTSUPP)
rsp->hdr.Status = STATUS_NOT_SUPPORTED;
else if (rc == -EKEYREJECTED)
rsp->hdr.Status = STATUS_ACCESS_DENIED;
else if (rc)
rsp->hdr.Status = STATUS_LOGON_FAILURE;
@@ -2148,6 +2151,16 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
if (rc < 0) {
if (sess && (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
struct preauth_session *preauth_sess;
preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
if (preauth_sess) {
list_del(&preauth_sess->preauth_entry);
kfree(preauth_sess);
}
}
/*
* SecurityBufferOffset should be set to zero
* in session setup error response.