Commit 621be84a authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French

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: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 34061d6b
...@@ -211,6 +211,7 @@ struct ksmbd_tree_disconnect_request { ...@@ -211,6 +211,7 @@ struct ksmbd_tree_disconnect_request {
*/ */
struct ksmbd_logout_request { struct ksmbd_logout_request {
__s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
__u32 account_flags;
}; };
/* /*
...@@ -317,6 +318,7 @@ enum KSMBD_TREE_CONN_STATUS { ...@@ -317,6 +318,7 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_USER_FLAG_BAD_UID BIT(2) #define KSMBD_USER_FLAG_BAD_UID BIT(2)
#define KSMBD_USER_FLAG_BAD_USER BIT(3) #define KSMBD_USER_FLAG_BAD_USER BIT(3)
#define KSMBD_USER_FLAG_GUEST_ACCOUNT BIT(4) #define KSMBD_USER_FLAG_GUEST_ACCOUNT BIT(4)
#define KSMBD_USER_FLAG_DELAY_SESSION BIT(5)
/* /*
* Share config flags. * Share config flags.
......
...@@ -55,7 +55,7 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp) ...@@ -55,7 +55,7 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp)
void ksmbd_free_user(struct ksmbd_user *user) void ksmbd_free_user(struct ksmbd_user *user)
{ {
ksmbd_ipc_logout_request(user->name); ksmbd_ipc_logout_request(user->name, user->flags);
kfree(user->name); kfree(user->name);
kfree(user->passkey); kfree(user->passkey);
kfree(user); kfree(user);
......
...@@ -18,6 +18,7 @@ struct ksmbd_user { ...@@ -18,6 +18,7 @@ struct ksmbd_user {
size_t passkey_sz; size_t passkey_sz;
char *passkey; char *passkey;
unsigned int failed_login_count;
}; };
static inline bool user_guest(struct ksmbd_user *user) static inline bool user_guest(struct ksmbd_user *user)
......
...@@ -1779,9 +1779,30 @@ int smb2_sess_setup(struct ksmbd_work *work) ...@@ -1779,9 +1779,30 @@ int smb2_sess_setup(struct ksmbd_work *work)
conn->mechToken = NULL; conn->mechToken = NULL;
} }
if (rc < 0 && sess) { if (rc < 0) {
/*
* SecurityBufferOffset should be set to zero
* in session setup error response.
*/
rsp->SecurityBufferOffset = 0;
if (sess) {
bool try_delay = false;
/*
* 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 (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION)
try_delay = true;
ksmbd_session_destroy(sess); ksmbd_session_destroy(sess);
work->sess = NULL; work->sess = NULL;
if (try_delay)
ssleep(5);
}
} }
return rc; return rc;
......
...@@ -601,7 +601,7 @@ int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id, ...@@ -601,7 +601,7 @@ int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
return ret; return ret;
} }
int ksmbd_ipc_logout_request(const char *account) int ksmbd_ipc_logout_request(const char *account, int flags)
{ {
struct ksmbd_ipc_msg *msg; struct ksmbd_ipc_msg *msg;
struct ksmbd_logout_request *req; struct ksmbd_logout_request *req;
...@@ -616,6 +616,7 @@ int ksmbd_ipc_logout_request(const char *account) ...@@ -616,6 +616,7 @@ int ksmbd_ipc_logout_request(const char *account)
msg->type = KSMBD_EVENT_LOGOUT_REQUEST; msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
req = (struct ksmbd_logout_request *)msg->payload; req = (struct ksmbd_logout_request *)msg->payload;
req->account_flags = flags;
strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ); strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
ret = ipc_msg_send(msg); ret = ipc_msg_send(msg);
......
...@@ -25,7 +25,7 @@ ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess, ...@@ -25,7 +25,7 @@ ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
struct sockaddr *peer_addr); struct sockaddr *peer_addr);
int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id, int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
unsigned long long connect_id); unsigned long long connect_id);
int ksmbd_ipc_logout_request(const char *account); int ksmbd_ipc_logout_request(const char *account, int flags);
struct ksmbd_share_config_response * struct ksmbd_share_config_response *
ksmbd_ipc_share_config_request(const char *name); ksmbd_ipc_share_config_request(const char *name);
struct ksmbd_spnego_authen_response * struct ksmbd_spnego_authen_response *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment