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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ struct ksmbd_tree_disconnect_request {
 */
struct ksmbd_logout_request {
	__s8	account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
	__u32	account_flags;
};

/*
@@ -317,6 +318,7 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_USER_FLAG_BAD_UID		BIT(2)
#define KSMBD_USER_FLAG_BAD_USER	BIT(3)
#define KSMBD_USER_FLAG_GUEST_ACCOUNT	BIT(4)
#define KSMBD_USER_FLAG_DELAY_SESSION	BIT(5)

/*
 * Share config flags.
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp)

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->passkey);
	kfree(user);
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ struct ksmbd_user {

	size_t			passkey_sz;
	char			*passkey;
	unsigned int		failed_login_count;
};

static inline bool user_guest(struct ksmbd_user *user)
+24 −3
Original line number Diff line number Diff line
@@ -1779,9 +1779,30 @@ int smb2_sess_setup(struct ksmbd_work *work)
		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);
			work->sess = NULL;
			if (try_delay)
				ssleep(5);
		}
	}

	return rc;
+2 −1
Original line number Diff line number Diff line
@@ -601,7 +601,7 @@ int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
	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_logout_request *req;
@@ -616,6 +616,7 @@ int ksmbd_ipc_logout_request(const char *account)

	msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
	req = (struct ksmbd_logout_request *)msg->payload;
	req->account_flags = flags;
	strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);

	ret = ipc_msg_send(msg);
Loading