cifs: Fix encoding of SMB1 Session Setup Kerberos Request in non-UNICODE mode
authorPali Rohár <pali@kernel.org>
Sun, 6 Oct 2024 17:20:13 +0000 (19:20 +0200)
committerSteve French <stfrench@microsoft.com>
Wed, 9 Apr 2025 18:34:32 +0000 (13:34 -0500)
Like in UNICODE mode, SMB1 Session Setup Kerberos Request contains oslm and
domain strings.

Extract common code into ascii_oslm_strings() and ascii_domain_string()
functions (similar to unicode variants) and use these functions in
non-UNICODE code path in sess_auth_kerberos().

Decision if non-UNICODE or UNICODE mode is used is based on the
SMBFLG2_UNICODE flag in Flags2 packed field, and not based on the
capabilities of server. Fix this check too.

Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/sess.c

index f2ca5963cd9d24d5ce753cfb759d1aa55a2939f1..b3fa9ee2691272709e1b1de32a48d05baca1d69d 100644 (file)
@@ -680,6 +680,22 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
        *pbcc_area = bcc_ptr;
 }
 
+static void
+ascii_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
+{
+       char *bcc_ptr = *pbcc_area;
+
+       strcpy(bcc_ptr, "Linux version ");
+       bcc_ptr += strlen("Linux version ");
+       strcpy(bcc_ptr, init_utsname()->release);
+       bcc_ptr += strlen(init_utsname()->release) + 1;
+
+       strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+       bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+
+       *pbcc_area = bcc_ptr;
+}
+
 static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
                                   const struct nls_table *nls_cp)
 {
@@ -704,6 +720,25 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
        *pbcc_area = bcc_ptr;
 }
 
+static void ascii_domain_string(char **pbcc_area, struct cifs_ses *ses,
+                               const struct nls_table *nls_cp)
+{
+       char *bcc_ptr = *pbcc_area;
+       int len;
+
+       /* copy domain */
+       if (ses->domainName != NULL) {
+               len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+               if (WARN_ON_ONCE(len < 0))
+                       len = CIFS_MAX_DOMAINNAME_LEN - 1;
+               bcc_ptr += len;
+       } /* else we send a null domain name so server will default to its own domain */
+       *bcc_ptr = 0;
+       bcc_ptr++;
+
+       *pbcc_area = bcc_ptr;
+}
+
 static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
                                   const struct nls_table *nls_cp)
 {
@@ -749,25 +784,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
        *bcc_ptr = 0;
        bcc_ptr++; /* account for null termination */
 
-       /* copy domain */
-       if (ses->domainName != NULL) {
-               len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
-               if (WARN_ON_ONCE(len < 0))
-                       len = CIFS_MAX_DOMAINNAME_LEN - 1;
-               bcc_ptr += len;
-       } /* else we send a null domain name so server will default to its own domain */
-       *bcc_ptr = 0;
-       bcc_ptr++;
-
        /* BB check for overflow here */
 
-       strcpy(bcc_ptr, "Linux version ");
-       bcc_ptr += strlen("Linux version ");
-       strcpy(bcc_ptr, init_utsname()->release);
-       bcc_ptr += strlen(init_utsname()->release) + 1;
-
-       strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
-       bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+       ascii_domain_string(&bcc_ptr, ses, nls_cp);
+       ascii_oslm_strings(&bcc_ptr, nls_cp);
 
        *pbcc_area = bcc_ptr;
 }
@@ -1570,7 +1590,7 @@ sess_auth_kerberos(struct sess_data *sess_data)
        sess_data->iov[1].iov_len = msg->secblob_len;
        pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
 
-       if (ses->capabilities & CAP_UNICODE) {
+       if (pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) {
                /* unicode strings must be word aligned */
                if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
                        *bcc_ptr = 0;
@@ -1579,8 +1599,8 @@ sess_auth_kerberos(struct sess_data *sess_data)
                unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
                unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
        } else {
-               /* BB: is this right? */
-               ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
+               ascii_oslm_strings(&bcc_ptr, sess_data->nls_cp);
+               ascii_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
        }
 
        sess_data->iov[2].iov_len = (long) bcc_ptr -