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 an user insert the wrong password 10 times in a row. Signed-off-by: Namjae Jeon <linkinjeon@xxxxxxxxxx> --- include/linux/ksmbd_server.h | 2 ++ include/management/user.h | 3 +++ lib/management/tree_conn.c | 3 +++ lib/management/user.c | 19 +++++++++++++++++++ mountd/worker.c | 2 +- 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/linux/ksmbd_server.h b/include/linux/ksmbd_server.h index 800925c..b1c5e63 100644 --- a/include/linux/ksmbd_server.h +++ b/include/linux/ksmbd_server.h @@ -122,6 +122,7 @@ struct ksmbd_tree_disconnect_request { struct ksmbd_logout_request { __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; + __u32 account_flags; }; struct ksmbd_rpc_command { @@ -203,6 +204,7 @@ enum KSMBD_TREE_CONN_STATUS { #define KSMBD_USER_FLAG_BAD_UID (1 << 2) #define KSMBD_USER_FLAG_BAD_USER (1 << 3) #define KSMBD_USER_FLAG_GUEST_ACCOUNT (1 << 4) +#define KSMBD_USER_FLAG_DELAY_SESSION (1 << 5) /* * Share config flags. diff --git a/include/management/user.h b/include/management/user.h index 26132d2..7482051 100644 --- a/include/management/user.h +++ b/include/management/user.h @@ -26,6 +26,7 @@ struct ksmbd_user { int flags; int state; GRWLock update_lock; + unsigned int failed_login_count; }; static inline void set_user_flag(struct ksmbd_user *user, int bit) @@ -61,8 +62,10 @@ void for_each_ksmbd_user(walk_users cb, gpointer user_data); struct ksmbd_login_request; struct ksmbd_login_response; +struct ksmbd_logout_request; int usm_handle_login_request(struct ksmbd_login_request *req, struct ksmbd_login_response *resp); +int usm_handle_logout_request(struct ksmbd_logout_request *req); #endif /* __MANAGEMENT_USER_H__ */ diff --git a/lib/management/tree_conn.c b/lib/management/tree_conn.c index 7158e8a..e6fc185 100644 --- a/lib/management/tree_conn.c +++ b/lib/management/tree_conn.c @@ -145,6 +145,9 @@ int tcm_handle_tree_connect(struct ksmbd_tree_connect_request *req, goto out_error; } + user->failed_login_count = 0; + user->flags &= ~KSMBD_USER_FLAG_DELAY_SESSION; + if (test_user_flag(user, KSMBD_USER_FLAG_GUEST_ACCOUNT)) set_conn_flag(conn, KSMBD_TREE_CONN_FLAG_GUEST_ACCOUNT); diff --git a/lib/management/user.c b/lib/management/user.c index 28c4dcd..b4727a7 100644 --- a/lib/management/user.c +++ b/lib/management/user.c @@ -387,3 +387,22 @@ int usm_handle_login_request(struct ksmbd_login_request *req, put_ksmbd_user(user); return 0; } + +int usm_handle_logout_request(struct ksmbd_logout_request *req) +{ + struct ksmbd_user *user; + + user = usm_lookup_user(req->account); + if (!user) + return -ENOENT; + + if (req->account_flags & KSMBD_USER_FLAG_BAD_PASSWORD) { + if (user->failed_login_count < 10) + user->failed_login_count++; + else + user->flags |= KSMBD_USER_FLAG_DELAY_SESSION; + } else { + user->failed_login_count = 0; + user->flags &= ~KSMBD_USER_FLAG_DELAY_SESSION; + } +} diff --git a/mountd/worker.c b/mountd/worker.c index 06ebb81..70f2655 100644 --- a/mountd/worker.c +++ b/mountd/worker.c @@ -204,7 +204,7 @@ static int logout_request(struct ksmbd_ipc_msg *msg) if (!VALID_IPC_MSG(msg, struct ksmbd_logout_request)) return -EINVAL; - return 0; + return usm_handle_logout_request(KSMBD_IPC_MSG_PAYLOAD(msg)); } static int heartbeat_request(struct ksmbd_ipc_msg *msg) -- 2.25.1