]> exis.tech > repos - linux.git/blobdiff - fs/smb/server/auth.c
Merge tag 'hwmon-for-v7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groec...
[linux.git] / fs / smb / server / auth.c
index 86f521e849d5e235ea8e53551b0977cac5075f22..4e7b6f0e6b8cd88f67e1c41eda826dd3601a679c 100644 (file)
@@ -133,16 +133,17 @@ out:
  * @blen:              NTLMv2 blob length
  * @domain_name:       domain name
  * @cryptkey:          session crypto key
+ * @sess_key:          derived session key output buffer
  *
  * Return:     0 on success, error number on error
  */
 int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                      struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
-                     char *cryptkey)
+                     char *cryptkey, char *sess_key)
 {
        char ntlmv2_hash[CIFS_ENCPWD_SIZE];
        char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
-       char sess_key[SMB2_NTLMV2_SESSKEY_SIZE];
+       char base_key[SMB2_NTLMV2_SESSKEY_SIZE];
        struct hmac_md5_ctx ctx;
        int rc;
 
@@ -165,7 +166,7 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
        /* Generate the session key */
        hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
                             ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE,
-                            sess_key);
+                            base_key);
 
        if (crypto_memneq(ntlmv2->ntlmv2_hash, ntlmv2_rsp,
                          CIFS_HMAC_MD5_HASH_SIZE)) {
@@ -173,12 +174,12 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                goto out;
        }
 
-       memcpy(sess->sess_key, sess_key, sizeof(sess_key));
+       memcpy(sess_key, base_key, sizeof(base_key));
        rc = 0;
 out:
        memzero_explicit(ntlmv2_hash, sizeof(ntlmv2_hash));
        memzero_explicit(ntlmv2_rsp, sizeof(ntlmv2_rsp));
-       memzero_explicit(sess_key, sizeof(sess_key));
+       memzero_explicit(base_key, sizeof(base_key));
        return rc;
 }
 
@@ -189,12 +190,13 @@ out:
  * @blob_len:  length of the @authblob message
  * @conn:      connection
  * @sess:      session of connection
+ * @sess_key:  derived session key output buffer
  *
  * Return:     0 on success, error number on error
  */
 int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
                                   int blob_len, struct ksmbd_conn *conn,
-                                  struct ksmbd_session *sess)
+                                  struct ksmbd_session *sess, char *sess_key)
 {
        char *domain_name;
        unsigned int nt_off, dn_off;
@@ -234,7 +236,7 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
        ret = ksmbd_auth_ntlmv2(conn, sess,
                                (struct ntlmv2_resp *)((char *)authblob + nt_off),
                                nt_len - CIFS_ENCPWD_SIZE,
-                               domain_name, conn->ntlmssp.cryptkey);
+                               domain_name, conn->ntlmssp.cryptkey, sess_key);
        kfree(domain_name);
        if (ret)
                return ret;
@@ -257,8 +259,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
                if (!ctx_arc4)
                        return -ENOMEM;
 
-               arc4_setkey(ctx_arc4, sess->sess_key, SMB2_NTLMV2_SESSKEY_SIZE);
-               arc4_crypt(ctx_arc4, sess->sess_key,
+               arc4_setkey(ctx_arc4, sess_key, SMB2_NTLMV2_SESSKEY_SIZE);
+               arc4_crypt(ctx_arc4, sess_key,
                           (char *)authblob + sess_key_off, sess_key_len);
                kfree_sensitive(ctx_arc4);
        }
@@ -400,7 +402,8 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
 
 #ifdef CONFIG_SMB_SERVER_KERBEROS5
 int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
-                           int in_len, char *out_blob, int *out_len)
+                           int in_len, char *out_blob, int *out_len,
+                           char *sess_key)
 {
        struct ksmbd_spnego_authen_response *resp;
        struct ksmbd_login_response_ext *resp_ext = NULL;
@@ -448,14 +451,14 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
        } else {
                if (!ksmbd_compare_user(sess->user, user)) {
                        ksmbd_debug(AUTH, "different user tried to reuse session\n");
-                       retval = -EPERM;
+                       retval = -EKEYREJECTED;
                        ksmbd_free_user(user);
                        goto out;
                }
                ksmbd_free_user(user);
        }
 
-       memcpy(sess->sess_key, resp->payload, resp->session_key_len);
+       memcpy(sess_key, resp->payload, resp->session_key_len);
        memcpy(out_blob, resp->payload + resp->session_key_len,
               resp->spnego_blob_len);
        *out_len = resp->spnego_blob_len;
@@ -466,7 +469,8 @@ out:
 }
 #else
 int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
-                           int in_len, char *out_blob, int *out_len)
+                           int in_len, char *out_blob, int *out_len,
+                           char *sess_key)
 {
        return -EOPNOTSUPP;
 }
@@ -525,7 +529,7 @@ struct derivation {
        bool binding;
 };
 
-static void generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+static void generate_key(struct ksmbd_conn *conn, const char *sess_key,
                         struct kvec label, struct kvec context, __u8 *key,
                         unsigned int key_size)
 {
@@ -536,7 +540,7 @@ static void generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
        unsigned char prfhash[SMB2_HMACSHA256_SIZE];
        struct hmac_sha256_ctx ctx;
 
-       hmac_sha256_init_usingrawkey(&ctx, sess->sess_key,
+       hmac_sha256_init_usingrawkey(&ctx, sess_key,
                                     SMB2_NTLMV2_SESSKEY_SIZE);
        hmac_sha256_update(&ctx, i, 4);
        hmac_sha256_update(&ctx, label.iov_base, label.iov_len);
@@ -559,18 +563,21 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
                                   const struct derivation *signing)
 {
        struct channel *chann;
-       char *key;
+       char *key, *sess_key;
 
        chann = lookup_chann_list(sess, conn);
        if (!chann)
                return 0;
 
-       if (conn->dialect >= SMB30_PROT_ID && signing->binding)
+       if (conn->dialect >= SMB30_PROT_ID && signing->binding) {
                key = chann->smb3signingkey;
-       else
+               sess_key = chann->sess_key;
+       } else {
                key = sess->smb3signingkey;
+               sess_key = sess->sess_key;
+       }
 
-       generate_key(conn, sess, signing->label, signing->context, key,
+       generate_key(conn, sess_key, signing->label, signing->context, key,
                     SMB3_SIGN_KEY_SIZE);
 
        if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
@@ -627,11 +634,11 @@ static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
                                       struct ksmbd_session *sess,
                                       const struct derivation_twin *ptwin)
 {
-       generate_key(conn, sess, ptwin->encryption.label,
+       generate_key(conn, sess->sess_key, ptwin->encryption.label,
                     ptwin->encryption.context, sess->smb3encryptionkey,
                     SMB3_ENC_DEC_KEY_SIZE);
 
-       generate_key(conn, sess, ptwin->decryption.label,
+       generate_key(conn, sess->sess_key, ptwin->decryption.label,
                     ptwin->decryption.context,
                     sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);