| From 92e470163d96df8db6c4fa0f484e4a229edb903d Mon Sep 17 00:00:00 2001 |
| From: Namjae Jeon <linkinjeon@kernel.org> |
| Date: Sat, 13 Jan 2024 15:11:41 +0900 |
| Subject: ksmbd: validate mech token in session setup |
| |
| From: Namjae Jeon <linkinjeon@kernel.org> |
| |
| commit 92e470163d96df8db6c4fa0f484e4a229edb903d upstream. |
| |
| If client send invalid mech token in session setup request, ksmbd |
| validate and make the error if it is invalid. |
| |
| Cc: stable@vger.kernel.org |
| Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22890 |
| Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/smb/server/asn1.c | 5 +++++ |
| fs/smb/server/connection.h | 1 + |
| fs/smb/server/smb2pdu.c | 22 +++++++++++++++++----- |
| 3 files changed, 23 insertions(+), 5 deletions(-) |
| |
| --- a/fs/smb/server/asn1.c |
| +++ b/fs/smb/server/asn1.c |
| @@ -214,10 +214,15 @@ static int ksmbd_neg_token_alloc(void *c |
| { |
| struct ksmbd_conn *conn = context; |
| |
| + if (!vlen) |
| + return -EINVAL; |
| + |
| conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL); |
| if (!conn->mechToken) |
| return -ENOMEM; |
| |
| + conn->mechTokenLen = (unsigned int)vlen; |
| + |
| return 0; |
| } |
| |
| --- a/fs/smb/server/connection.h |
| +++ b/fs/smb/server/connection.h |
| @@ -88,6 +88,7 @@ struct ksmbd_conn { |
| __u16 dialect; |
| |
| char *mechToken; |
| + unsigned int mechTokenLen; |
| |
| struct ksmbd_conn_ops *conn_ops; |
| |
| --- a/fs/smb/server/smb2pdu.c |
| +++ b/fs/smb/server/smb2pdu.c |
| @@ -1412,7 +1412,10 @@ static struct ksmbd_user *session_user(s |
| char *name; |
| unsigned int name_off, name_len, secbuf_len; |
| |
| - secbuf_len = le16_to_cpu(req->SecurityBufferLength); |
| + if (conn->use_spnego && conn->mechToken) |
| + secbuf_len = conn->mechTokenLen; |
| + else |
| + secbuf_len = le16_to_cpu(req->SecurityBufferLength); |
| if (secbuf_len < sizeof(struct authenticate_message)) { |
| ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len); |
| return NULL; |
| @@ -1503,7 +1506,10 @@ static int ntlm_authenticate(struct ksmb |
| struct authenticate_message *authblob; |
| |
| authblob = user_authblob(conn, req); |
| - sz = le16_to_cpu(req->SecurityBufferLength); |
| + if (conn->use_spnego && conn->mechToken) |
| + sz = conn->mechTokenLen; |
| + else |
| + sz = le16_to_cpu(req->SecurityBufferLength); |
| rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess); |
| if (rc) { |
| set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD); |
| @@ -1776,8 +1782,7 @@ int smb2_sess_setup(struct ksmbd_work *w |
| |
| negblob_off = le16_to_cpu(req->SecurityBufferOffset); |
| negblob_len = le16_to_cpu(req->SecurityBufferLength); |
| - if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) || |
| - negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { |
| + if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer)) { |
| rc = -EINVAL; |
| goto out_err; |
| } |
| @@ -1786,8 +1791,15 @@ int smb2_sess_setup(struct ksmbd_work *w |
| negblob_off); |
| |
| if (decode_negotiation_token(conn, negblob, negblob_len) == 0) { |
| - if (conn->mechToken) |
| + if (conn->mechToken) { |
| negblob = (struct negotiate_message *)conn->mechToken; |
| + negblob_len = conn->mechTokenLen; |
| + } |
| + } |
| + |
| + if (negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { |
| + rc = -EINVAL; |
| + goto out_err; |
| } |
| |
| if (server_conf.auth_mechs & conn->auth_mechs) { |