@@ -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.
@@ -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__ */
@@ -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);
@@ -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;
+ }
+}
@@ -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)
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@kernel.org> --- 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(-)