ksmbd: add support for SMB3 multichannel
authorNamjae Jeon <namjae.jeon@samsung.com>
Fri, 18 Jun 2021 01:04:19 +0000 (10:04 +0900)
committerNamjae Jeon <namjae.jeon@samsung.com>
Fri, 18 Jun 2021 23:34:23 +0000 (08:34 +0900)
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>
fs/cifsd/auth.c
fs/cifsd/auth.h
fs/cifsd/connection.h
fs/cifsd/ksmbd_server.h
fs/cifsd/mgmt/user_session.c
fs/cifsd/mgmt/user_session.h
fs/cifsd/smb2ops.c
fs/cifsd/smb2pdu.c
fs/cifsd/smb2pdu.h
fs/cifsd/smb_common.h

index 5f47de4..1ba03a7 100644 (file)
@@ -921,13 +921,14 @@ smb3signkey_ret:
 }
 
 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;
+       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;
 
index 650bd7d..9c2d4ba 100644 (file)
@@ -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,
index 1658442..98108b4 100644 (file)
@@ -106,6 +106,7 @@ struct ksmbd_conn {
        __le16                          cipher_type;
        __le16                          compress_algorithm;
        bool                            posix_ext_supported;
+       bool                            binding;
 };
 
 struct ksmbd_conn_ops {
index 442077a..5ae3fe9 100644 (file)
@@ -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;
index 739588a..c3487b1 100644 (file)
@@ -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);
index 761bf47..82289c3 100644 (file)
@@ -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);
index 8999c3f..f7e5f21 100644 (file)
@@ -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;
 }
index ac15a92..12c954d 100644 (file)
@@ -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));
index 0d5349e..0eac40e 100644 (file)
@@ -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);
index 6e7404b..084166b 100644 (file)
@@ -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);