Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ksmbd: throttle session setup failures to avoid dictionary attacks

To avoid dictionary attacks (repeated session setups rapidly sent) to
connect to server, ksmbd make a delay of a 5 seconds on session setup
failure to make it harder to send enough random connection requests
to break into a server if a user insert the wrong password 10 times
in a row.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Namjae Jeon and committed by
Steve French
621be84a 34061d6b

+31 -6
+2
fs/ksmbd/ksmbd_netlink.h
··· 211 211 */ 212 212 struct ksmbd_logout_request { 213 213 __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */ 214 + __u32 account_flags; 214 215 }; 215 216 216 217 /* ··· 318 317 #define KSMBD_USER_FLAG_BAD_UID BIT(2) 319 318 #define KSMBD_USER_FLAG_BAD_USER BIT(3) 320 319 #define KSMBD_USER_FLAG_GUEST_ACCOUNT BIT(4) 320 + #define KSMBD_USER_FLAG_DELAY_SESSION BIT(5) 321 321 322 322 /* 323 323 * Share config flags.
+1 -1
fs/ksmbd/mgmt/user_config.c
··· 55 55 56 56 void ksmbd_free_user(struct ksmbd_user *user) 57 57 { 58 - ksmbd_ipc_logout_request(user->name); 58 + ksmbd_ipc_logout_request(user->name, user->flags); 59 59 kfree(user->name); 60 60 kfree(user->passkey); 61 61 kfree(user);
+1
fs/ksmbd/mgmt/user_config.h
··· 18 18 19 19 size_t passkey_sz; 20 20 char *passkey; 21 + unsigned int failed_login_count; 21 22 }; 22 23 23 24 static inline bool user_guest(struct ksmbd_user *user)
+24 -3
fs/ksmbd/smb2pdu.c
··· 1779 1779 conn->mechToken = NULL; 1780 1780 } 1781 1781 1782 - if (rc < 0 && sess) { 1783 - ksmbd_session_destroy(sess); 1784 - work->sess = NULL; 1782 + if (rc < 0) { 1783 + /* 1784 + * SecurityBufferOffset should be set to zero 1785 + * in session setup error response. 1786 + */ 1787 + rsp->SecurityBufferOffset = 0; 1788 + 1789 + if (sess) { 1790 + bool try_delay = false; 1791 + 1792 + /* 1793 + * To avoid dictionary attacks (repeated session setups rapidly sent) to 1794 + * connect to server, ksmbd make a delay of a 5 seconds on session setup 1795 + * failure to make it harder to send enough random connection requests 1796 + * to break into a server. 1797 + */ 1798 + if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) 1799 + try_delay = true; 1800 + 1801 + ksmbd_session_destroy(sess); 1802 + work->sess = NULL; 1803 + if (try_delay) 1804 + ssleep(5); 1805 + } 1785 1806 } 1786 1807 1787 1808 return rc;
+2 -1
fs/ksmbd/transport_ipc.c
··· 601 601 return ret; 602 602 } 603 603 604 - int ksmbd_ipc_logout_request(const char *account) 604 + int ksmbd_ipc_logout_request(const char *account, int flags) 605 605 { 606 606 struct ksmbd_ipc_msg *msg; 607 607 struct ksmbd_logout_request *req; ··· 616 616 617 617 msg->type = KSMBD_EVENT_LOGOUT_REQUEST; 618 618 req = (struct ksmbd_logout_request *)msg->payload; 619 + req->account_flags = flags; 619 620 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ); 620 621 621 622 ret = ipc_msg_send(msg);
+1 -1
fs/ksmbd/transport_ipc.h
··· 25 25 struct sockaddr *peer_addr); 26 26 int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id, 27 27 unsigned long long connect_id); 28 - int ksmbd_ipc_logout_request(const char *account); 28 + int ksmbd_ipc_logout_request(const char *account, int flags); 29 29 struct ksmbd_share_config_response * 30 30 ksmbd_ipc_share_config_request(const char *name); 31 31 struct ksmbd_spnego_authen_response *