Commit f5a544e3 authored by Namjae Jeon's avatar Namjae Jeon
Browse files

ksmbd: add support for SMB3 multichannel



Add support for SMB3 multichannel. It will be enable by setting
'server multi channel support = yes' in smb.conf.

Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 5fb68864
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -921,13 +921,14 @@ static int generate_key(struct ksmbd_session *sess, struct kvec label,
}

static int generate_smb3signingkey(struct ksmbd_session *sess,
				   struct ksmbd_conn *conn,
				   const struct derivation *signing)
{
	int rc;
	struct channel *chann;
	char *key;

	chann = lookup_chann_list(sess);
	chann = lookup_chann_list(sess, conn);
	if (!chann)
		return 0;

@@ -953,7 +954,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
	return 0;
}

int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess)
int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
			       struct ksmbd_conn *conn)
{
	struct derivation d;

@@ -961,22 +963,32 @@ int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess)
	d.label.iov_len = 12;
	d.context.iov_base = "SmbSign";
	d.context.iov_len = 8;
	d.binding = false;
	d.binding = conn->binding;

	return generate_smb3signingkey(sess, &d);
	return generate_smb3signingkey(sess, conn, &d);
}

int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess)
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
				struct ksmbd_conn *conn)
{
	struct derivation d;

	d.label.iov_base = "SMBSigningKey";
	d.label.iov_len = 14;
	if (conn->binding) {
		struct preauth_session *preauth_sess;

		preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
		if (!preauth_sess)
			return -ENOENT;
		d.context.iov_base = preauth_sess->Preauth_HashValue;
	} else {
		d.context.iov_base = sess->Preauth_HashValue;
	}
	d.context.iov_len = 64;
	d.binding = false;
	d.binding = conn->binding;

	return generate_smb3signingkey(sess, &d);
	return generate_smb3signingkey(sess, conn, &d);
}

struct derivation_twin {
@@ -1148,7 +1160,7 @@ static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
	struct ksmbd_session *sess;
	u8 *ses_enc_key;

	sess = ksmbd_session_lookup(conn, ses_id);
	sess = ksmbd_session_lookup_all(conn, ses_id);
	if (!sess)
		return -EINVAL;

+4 −2
Original line number Diff line number Diff line
@@ -54,8 +54,10 @@ int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
			int n_vec, char *sig);
int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
			int n_vec, char *sig);
int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess);
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess);
int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
			       struct ksmbd_conn *conn);
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
				struct ksmbd_conn *conn);
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess);
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess);
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
+1 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ struct ksmbd_conn {
	__le16				cipher_type;
	__le16				compress_algorithm;
	bool				posix_ext_supported;
	bool				binding;
};

struct ksmbd_conn_ops {
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct ksmbd_heartbeat {
#define KSMBD_GLOBAL_FLAG_CACHE_TBUF		BIT(1)
#define KSMBD_GLOBAL_FLAG_CACHE_RBUF		BIT(2)
#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION	BIT(3)
#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL	BIT(4)

struct ksmbd_startup_request {
	__u32	flags;
+48 −1
Original line number Diff line number Diff line
@@ -207,7 +207,8 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
	}
}

bool ksmbd_session_id_match(struct ksmbd_session *sess, unsigned long long id)
static bool ksmbd_session_id_match(struct ksmbd_session *sess,
				   unsigned long long id)
{
	return sess->id == id;
}
@@ -250,6 +251,52 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
	return sess;
}

struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
					       unsigned long long id)
{
	struct ksmbd_session *sess;

	sess = ksmbd_session_lookup(conn, id);
	if (!sess && conn->binding)
		sess = ksmbd_session_lookup_slowpath(id);
	return sess;
}

struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
						    u64 sess_id)
{
	struct preauth_session *sess;

	sess = kmalloc(sizeof(struct preauth_session), GFP_KERNEL);
	if (!sess)
		return NULL;

	sess->id = sess_id;
	memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue,
	       PREAUTH_HASHVALUE_SIZE);
	list_add(&sess->preauth_entry, &conn->preauth_sess_table);

	return sess;
}

static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
					   unsigned long long id)
{
	return sess->id == id;
}

struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
						     unsigned long long id)
{
	struct preauth_session *sess = NULL;

	list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) {
		if (ksmbd_preauth_session_id_match(sess, id))
			return sess;
	}
	return NULL;
}

static int __init_smb2_session(struct ksmbd_session *sess)
{
	int id = ksmbd_acquire_smb2_uid(&session_ida);
Loading