cifs: fix unicode string area word alignment in session setup
[deliverable/linux.git] / fs / cifs / sess.c
index 5c68b4282be917bc48ba04e77b0af2120952d50a..70d04d08293bdcf756ee8f1de61906e8f2d141aa 100644 (file)
@@ -285,27 +285,26 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
        int words_left, len;
        char *data = *pbcc_area;
 
-
-
        cFYI(1, ("bleft %d", bleft));
 
-
-       /* SMB header is unaligned, so cifs servers word align start of
-          Unicode strings */
-       data++;
-       bleft--; /* Windows servers do not always double null terminate
-                   their final Unicode string - in which case we
-                   now will not attempt to decode the byte of junk
-                   which follows it */
+       /*
+        * Windows servers do not always double null terminate their final
+        * Unicode string. Check to see if there are an uneven number of bytes
+        * left. If so, then add an extra NULL pad byte to the end of the
+        * response.
+        *
+        * See section 2.7.2 in "Implementing CIFS" for details
+        */
+       if (bleft % 2) {
+               data[bleft] = 0;
+               ++bleft;
+       }
 
        words_left = bleft / 2;
 
        /* save off server operating system */
        len = UniStrnlen((wchar_t *) data, words_left);
 
-/* We look for obvious messed up bcc or strings in response so we do not go off
-   the end since (at least) WIN2K and Windows XP have a major bug in not null
-   terminating last Unicode string in response  */
        if (len >= words_left)
                return rc;
 
@@ -343,13 +342,10 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
                return rc;
 
        kfree(ses->serverDomain);
-       ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
-       if (ses->serverDomain != NULL) {
+       ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL);
+       if (ses->serverDomain != NULL)
                cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
                                   nls_cp);
-               ses->serverDomain[2*len] = 0;
-               ses->serverDomain[(2*len) + 1] = 0;
-       }
        data += 2 * (len + 1);
        words_left -= len + 1;
 
@@ -702,12 +698,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
        }
 
        /* BB check if Unicode and decode strings */
-       if (smb_buf->Flags2 & SMBFLG2_UNICODE)
+       if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+               /* unicode string area must be word-aligned */
+               if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
+                       ++bcc_ptr;
+                       --bytes_remaining;
+               }
                rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
-                                                  ses, nls_cp);
-       else
+                                          ses, nls_cp);
+       } else {
                rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
                                         ses, nls_cp);
+       }
 
 ssetup_exit:
        if (spnego_key) {
This page took 0.0385 seconds and 5 git commands to generate.