diff mbox series

ksmbd-tools: throttle session setup failures to avoid dictionary attacks

Message ID 20211013084327.22515-1-linkinjeon@kernel.org
State New
Headers show
Series ksmbd-tools: throttle session setup failures to avoid dictionary attacks | expand

Commit Message

Namjae Jeon Oct. 13, 2021, 8:43 a.m. UTC
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(-)
diff mbox series

Patch

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)