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: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
5fb6886467
commit
f5a544e3ba
|
@ -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;
|
||||
d.context.iov_base = sess->Preauth_HashValue;
|
||||
d.context.iov_len = 64;
|
||||
d.binding = false;
|
||||
if (conn->binding) {
|
||||
struct preauth_session *preauth_sess;
|
||||
|
||||
return generate_smb3signingkey(sess, &d);
|
||||
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 = conn->binding;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -106,6 +106,7 @@ struct ksmbd_conn {
|
|||
__le16 cipher_type;
|
||||
__le16 compress_algorithm;
|
||||
bool posix_ext_supported;
|
||||
bool binding;
|
||||
};
|
||||
|
||||
struct ksmbd_conn_ops {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -26,8 +26,8 @@ struct channel {
|
|||
|
||||
struct preauth_session {
|
||||
__u8 Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
|
||||
u64 sess_id;
|
||||
struct list_head list_entry;
|
||||
u64 id;
|
||||
struct list_head preauth_entry;
|
||||
};
|
||||
|
||||
struct ksmbd_session {
|
||||
|
@ -82,13 +82,18 @@ struct ksmbd_session *ksmbd_smb2_session_create(void);
|
|||
|
||||
void ksmbd_session_destroy(struct ksmbd_session *sess);
|
||||
|
||||
bool ksmbd_session_id_match(struct ksmbd_session *sess, unsigned long long id);
|
||||
struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id);
|
||||
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||
unsigned long long id);
|
||||
void ksmbd_session_register(struct ksmbd_conn *conn,
|
||||
struct ksmbd_session *sess);
|
||||
void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
|
||||
struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
|
||||
unsigned long long id);
|
||||
struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
|
||||
u64 sess_id);
|
||||
struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
|
||||
unsigned long long id);
|
||||
|
||||
int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess);
|
||||
void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id);
|
||||
|
|
|
@ -229,6 +229,9 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
|
|||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
|
||||
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
|
||||
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
|
||||
|
||||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
|
||||
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -250,6 +253,9 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
|
|||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
|
||||
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
|
||||
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
|
||||
|
||||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
|
||||
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -271,6 +277,9 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
|
|||
if (conn->cipher_type)
|
||||
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
|
||||
|
||||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
|
||||
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
|
||||
|
||||
INIT_LIST_HEAD(&conn->preauth_sess_table);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -64,21 +64,21 @@ static inline int check_session_id(struct ksmbd_conn *conn, u64 id)
|
|||
if (id == 0 || id == -1)
|
||||
return 0;
|
||||
|
||||
sess = ksmbd_session_lookup(conn, id);
|
||||
sess = ksmbd_session_lookup_all(conn, id);
|
||||
if (sess)
|
||||
return 1;
|
||||
ksmbd_err("Invalid user session id: %llu\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct channel *lookup_chann_list(struct ksmbd_session *sess)
|
||||
struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
|
||||
{
|
||||
struct channel *chann;
|
||||
struct list_head *t;
|
||||
|
||||
list_for_each(t, &sess->ksmbd_chann_list) {
|
||||
chann = list_entry(t, struct channel, chann_list);
|
||||
if (chann && chann->conn == sess->conn)
|
||||
if (chann && chann->conn == conn)
|
||||
return chann;
|
||||
}
|
||||
|
||||
|
@ -600,7 +600,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
|
|||
|
||||
sess_id = le64_to_cpu(req_hdr->SessionId);
|
||||
/* Check for validity of user session */
|
||||
work->sess = ksmbd_session_lookup(conn, sess_id);
|
||||
work->sess = ksmbd_session_lookup_all(conn, sess_id);
|
||||
if (work->sess)
|
||||
return 1;
|
||||
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
|
||||
|
@ -1165,18 +1165,30 @@ static int generate_preauth_hash(struct ksmbd_work *work)
|
|||
{
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
struct ksmbd_session *sess = work->sess;
|
||||
u8 *preauth_hash;
|
||||
|
||||
if (conn->dialect != SMB311_PROT_ID)
|
||||
return 0;
|
||||
|
||||
if (!sess->Preauth_HashValue) {
|
||||
if (alloc_preauth_hash(sess, conn))
|
||||
return -ENOMEM;
|
||||
if (conn->binding) {
|
||||
struct preauth_session *preauth_sess;
|
||||
|
||||
preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
|
||||
if (!preauth_sess) {
|
||||
preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id);
|
||||
if (!preauth_sess)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
preauth_hash = preauth_sess->Preauth_HashValue;
|
||||
} else {
|
||||
if (!sess->Preauth_HashValue)
|
||||
if (alloc_preauth_hash(sess, conn))
|
||||
return -ENOMEM;
|
||||
preauth_hash = sess->Preauth_HashValue;
|
||||
}
|
||||
|
||||
ksmbd_gen_preauth_integrity_hash(conn,
|
||||
work->request_buf,
|
||||
sess->Preauth_HashValue);
|
||||
ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1383,15 +1395,19 @@ static int ntlm_authenticate(struct ksmbd_work *work)
|
|||
* that it is reauthentication. And the user/password
|
||||
* has been verified, so return it here.
|
||||
*/
|
||||
if (sess->state == SMB2_SESSION_VALID)
|
||||
if (sess->state == SMB2_SESSION_VALID) {
|
||||
if (conn->binding)
|
||||
goto binding_session;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conn->sign || server_conf.enforced_signing) ||
|
||||
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
|
||||
sess->sign = true;
|
||||
|
||||
if (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION &&
|
||||
conn->ops->generate_encryptionkey) {
|
||||
conn->ops->generate_encryptionkey &&
|
||||
!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
|
||||
rc = conn->ops->generate_encryptionkey(sess);
|
||||
if (rc) {
|
||||
ksmbd_debug(SMB,
|
||||
|
@ -1409,8 +1425,9 @@ static int ntlm_authenticate(struct ksmbd_work *work)
|
|||
}
|
||||
}
|
||||
|
||||
binding_session:
|
||||
if (conn->dialect >= SMB30_PROT_ID) {
|
||||
chann = lookup_chann_list(sess);
|
||||
chann = lookup_chann_list(sess, conn);
|
||||
if (!chann) {
|
||||
chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
|
||||
if (!chann)
|
||||
|
@ -1423,7 +1440,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
|
|||
}
|
||||
|
||||
if (conn->ops->generate_signingkey) {
|
||||
rc = conn->ops->generate_signingkey(sess);
|
||||
rc = conn->ops->generate_signingkey(sess, conn);
|
||||
if (rc) {
|
||||
ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
|
||||
rsp->hdr.Status = STATUS_LOGON_FAILURE;
|
||||
|
@ -1500,7 +1517,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
|
|||
}
|
||||
|
||||
if (conn->dialect >= SMB30_PROT_ID) {
|
||||
chann = lookup_chann_list(sess);
|
||||
chann = lookup_chann_list(sess, conn);
|
||||
if (!chann) {
|
||||
chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
|
||||
if (!chann)
|
||||
|
@ -1513,7 +1530,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
|
|||
}
|
||||
|
||||
if (conn->ops->generate_signingkey) {
|
||||
retval = conn->ops->generate_signingkey(sess);
|
||||
retval = conn->ops->generate_signingkey(sess, conn);
|
||||
if (retval) {
|
||||
ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
|
||||
rsp->hdr.Status = STATUS_LOGON_FAILURE;
|
||||
|
@ -1562,12 +1579,59 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
|||
}
|
||||
rsp->hdr.SessionId = cpu_to_le64(sess->id);
|
||||
ksmbd_session_register(conn, sess);
|
||||
} else if (conn->dialect >= SMB30_PROT_ID &&
|
||||
(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
|
||||
req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) {
|
||||
u64 sess_id = le64_to_cpu(req->hdr.SessionId);
|
||||
|
||||
sess = ksmbd_session_lookup_slowpath(sess_id);
|
||||
if (!sess) {
|
||||
rc = -ENOENT;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (conn->dialect != sess->conn->dialect) {
|
||||
rc = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
|
||||
rc = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (strncmp(conn->ClientGUID, sess->conn->ClientGUID,
|
||||
SMB2_CLIENT_GUID_SIZE)) {
|
||||
rc = -ENOENT;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
|
||||
rc = -EACCES;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (sess->state == SMB2_SESSION_EXPIRED) {
|
||||
rc = -EFAULT;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (ksmbd_session_lookup(conn, sess_id)) {
|
||||
rc = -EACCES;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
conn->binding = true;
|
||||
} else if ((conn->dialect < SMB30_PROT_ID ||
|
||||
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
|
||||
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
|
||||
rc = -EACCES;
|
||||
goto out_err;
|
||||
} else {
|
||||
sess = ksmbd_session_lookup(conn,
|
||||
le64_to_cpu(req->hdr.SessionId));
|
||||
if (!sess) {
|
||||
rc = -ENOENT;
|
||||
rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
@ -1585,15 +1649,15 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
|||
}
|
||||
|
||||
if (server_conf.auth_mechs & conn->auth_mechs) {
|
||||
rc = generate_preauth_hash(work);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
if (conn->preferred_auth_mech &
|
||||
(KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
|
||||
rc = generate_preauth_hash(work);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
rc = krb5_authenticate(work);
|
||||
if (rc) {
|
||||
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
|
||||
rc = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
|
@ -1602,10 +1666,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
|||
kfree(sess->Preauth_HashValue);
|
||||
sess->Preauth_HashValue = NULL;
|
||||
} else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
|
||||
rc = generate_preauth_hash(work);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
if (negblob->MessageType == NtLmNegotiate) {
|
||||
rc = ntlm_negotiate(work, negblob);
|
||||
if (rc)
|
||||
|
@ -1625,6 +1685,16 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
|||
|
||||
ksmbd_conn_set_good(work);
|
||||
sess->state = SMB2_SESSION_VALID;
|
||||
if (conn->binding) {
|
||||
struct preauth_session *preauth_sess;
|
||||
|
||||
preauth_sess =
|
||||
ksmbd_preauth_session_lookup(conn, sess->id);
|
||||
if (preauth_sess) {
|
||||
list_del(&preauth_sess->preauth_entry);
|
||||
kfree(preauth_sess);
|
||||
}
|
||||
}
|
||||
kfree(sess->Preauth_HashValue);
|
||||
sess->Preauth_HashValue = NULL;
|
||||
}
|
||||
|
@ -1632,15 +1702,24 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
|||
/* TODO: need one more negotiation */
|
||||
ksmbd_err("Not support the preferred authentication\n");
|
||||
rc = -EINVAL;
|
||||
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
} else {
|
||||
ksmbd_err("Not support authentication\n");
|
||||
rc = -EINVAL;
|
||||
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
out_err:
|
||||
if (rc == -EINVAL)
|
||||
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
|
||||
else if (rc == -ENOENT)
|
||||
rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
|
||||
else if (rc == -EACCES)
|
||||
rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
|
||||
else if (rc == -EFAULT)
|
||||
rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED;
|
||||
else if (rc)
|
||||
rsp->hdr.Status = STATUS_LOGON_FAILURE;
|
||||
|
||||
if (conn->use_spnego && conn->mechToken) {
|
||||
kfree(conn->mechToken);
|
||||
conn->mechToken = NULL;
|
||||
|
@ -7883,7 +7962,7 @@ void smb2_set_sign_rsp(struct ksmbd_work *work)
|
|||
*/
|
||||
int smb3_check_sign_req(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_conn *conn;
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
char *signing_key;
|
||||
struct smb2_hdr *hdr, *hdr_org;
|
||||
struct channel *chann;
|
||||
|
@ -7906,13 +7985,11 @@ int smb3_check_sign_req(struct ksmbd_work *work)
|
|||
|
||||
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
|
||||
signing_key = work->sess->smb3signingkey;
|
||||
conn = work->sess->conn;
|
||||
} else {
|
||||
chann = lookup_chann_list(work->sess);
|
||||
chann = lookup_chann_list(work->sess, conn);
|
||||
if (!chann)
|
||||
return 0;
|
||||
signing_key = chann->smb3signingkey;
|
||||
conn = chann->conn;
|
||||
}
|
||||
|
||||
if (!signing_key) {
|
||||
|
@ -7943,7 +8020,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
|
|||
*/
|
||||
void smb3_set_sign_rsp(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_conn *conn;
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
struct smb2_hdr *req_hdr;
|
||||
struct smb2_hdr *hdr, *hdr_org;
|
||||
struct channel *chann;
|
||||
|
@ -7970,13 +8047,11 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
|
|||
|
||||
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
|
||||
signing_key = work->sess->smb3signingkey;
|
||||
conn = work->sess->conn;
|
||||
} else {
|
||||
chann = lookup_chann_list(work->sess);
|
||||
chann = lookup_chann_list(work->sess, work->conn);
|
||||
if (!chann)
|
||||
return;
|
||||
signing_key = chann->smb3signingkey;
|
||||
conn = chann->conn;
|
||||
}
|
||||
|
||||
if (!signing_key)
|
||||
|
@ -8020,11 +8095,21 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
|
|||
ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
|
||||
conn->preauth_info->Preauth_HashValue);
|
||||
|
||||
if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
|
||||
sess && sess->state == SMB2_SESSION_IN_PROGRESS) {
|
||||
if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
|
||||
__u8 *hash_value;
|
||||
|
||||
hash_value = sess->Preauth_HashValue;
|
||||
if (conn->binding) {
|
||||
struct preauth_session *preauth_sess;
|
||||
|
||||
preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
|
||||
if (!preauth_sess)
|
||||
return;
|
||||
hash_value = preauth_sess->Preauth_HashValue;
|
||||
} else {
|
||||
hash_value = sess->Preauth_HashValue;
|
||||
if (!hash_value)
|
||||
return;
|
||||
}
|
||||
ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
|
||||
hash_value);
|
||||
}
|
||||
|
@ -8116,7 +8201,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
|
|||
unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
|
||||
int rc = 0;
|
||||
|
||||
sess = ksmbd_session_lookup(conn, le64_to_cpu(tr_hdr->SessionId));
|
||||
sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId));
|
||||
if (!sess) {
|
||||
ksmbd_err("invalid session id(%llx) in transform header\n",
|
||||
le64_to_cpu(tr_hdr->SessionId));
|
||||
|
|
|
@ -1647,7 +1647,8 @@ struct file_lock *smb_flock_init(struct file *f);
|
|||
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
|
||||
void **arg);
|
||||
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
|
||||
struct channel *lookup_chann_list(struct ksmbd_session *sess);
|
||||
struct channel *lookup_chann_list(struct ksmbd_session *sess,
|
||||
struct ksmbd_conn *conn);
|
||||
void smb3_preauth_hash_rsp(struct ksmbd_work *work);
|
||||
int smb3_is_transform_hdr(void *buf);
|
||||
int smb3_decrypt_req(struct ksmbd_work *work);
|
||||
|
|
|
@ -479,7 +479,7 @@ struct smb_version_ops {
|
|||
bool (*is_sign_req)(struct ksmbd_work *work, unsigned int command);
|
||||
int (*check_sign_req)(struct ksmbd_work *work);
|
||||
void (*set_sign_rsp)(struct ksmbd_work *work);
|
||||
int (*generate_signingkey)(struct ksmbd_session *sess);
|
||||
int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn);
|
||||
int (*generate_encryptionkey)(struct ksmbd_session *sess);
|
||||
int (*is_transform_hdr)(void *buf);
|
||||
int (*decrypt_req)(struct ksmbd_work *work);
|
||||
|
|
Loading…
Reference in New Issue