diff options
Diffstat (limited to 'fs/cifs/sess.c')
| -rw-r--r-- | fs/cifs/sess.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 5c68b4282be9..c652c73760dd 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -285,35 +285,36 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
| 285 | int words_left, len; | 285 | int words_left, len; |
| 286 | char *data = *pbcc_area; | 286 | char *data = *pbcc_area; |
| 287 | 287 | ||
| 288 | |||
| 289 | |||
| 290 | cFYI(1, ("bleft %d", bleft)); | 288 | cFYI(1, ("bleft %d", bleft)); |
| 291 | 289 | ||
| 292 | 290 | /* | |
| 293 | /* SMB header is unaligned, so cifs servers word align start of | 291 | * Windows servers do not always double null terminate their final |
| 294 | Unicode strings */ | 292 | * Unicode string. Check to see if there are an uneven number of bytes |
| 295 | data++; | 293 | * left. If so, then add an extra NULL pad byte to the end of the |
| 296 | bleft--; /* Windows servers do not always double null terminate | 294 | * response. |
| 297 | their final Unicode string - in which case we | 295 | * |
| 298 | now will not attempt to decode the byte of junk | 296 | * See section 2.7.2 in "Implementing CIFS" for details |
| 299 | which follows it */ | 297 | */ |
| 298 | if (bleft % 2) { | ||
| 299 | data[bleft] = 0; | ||
| 300 | ++bleft; | ||
| 301 | } | ||
| 300 | 302 | ||
| 301 | words_left = bleft / 2; | 303 | words_left = bleft / 2; |
| 302 | 304 | ||
| 303 | /* save off server operating system */ | 305 | /* save off server operating system */ |
| 304 | len = UniStrnlen((wchar_t *) data, words_left); | 306 | len = UniStrnlen((wchar_t *) data, words_left); |
| 305 | 307 | ||
| 306 | /* We look for obvious messed up bcc or strings in response so we do not go off | ||
| 307 | the end since (at least) WIN2K and Windows XP have a major bug in not null | ||
| 308 | terminating last Unicode string in response */ | ||
| 309 | if (len >= words_left) | 308 | if (len >= words_left) |
| 310 | return rc; | 309 | return rc; |
| 311 | 310 | ||
| 312 | kfree(ses->serverOS); | 311 | kfree(ses->serverOS); |
| 313 | /* UTF-8 string will not grow more than four times as big as UCS-16 */ | 312 | /* UTF-8 string will not grow more than four times as big as UCS-16 */ |
| 314 | ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); | 313 | ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); |
| 315 | if (ses->serverOS != NULL) | 314 | if (ses->serverOS != NULL) { |
| 316 | cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); | 315 | cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); |
| 316 | cFYI(1, ("serverOS=%s", ses->serverOS)); | ||
| 317 | } | ||
| 317 | data += 2 * (len + 1); | 318 | data += 2 * (len + 1); |
| 318 | words_left -= len + 1; | 319 | words_left -= len + 1; |
| 319 | 320 | ||
| @@ -328,6 +329,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
| 328 | if (ses->serverNOS != NULL) { | 329 | if (ses->serverNOS != NULL) { |
| 329 | cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, | 330 | cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, |
| 330 | nls_cp); | 331 | nls_cp); |
| 332 | cFYI(1, ("serverNOS=%s", ses->serverNOS)); | ||
| 331 | if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { | 333 | if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { |
| 332 | cFYI(1, ("NT4 server")); | 334 | cFYI(1, ("NT4 server")); |
| 333 | ses->flags |= CIFS_SES_NT4; | 335 | ses->flags |= CIFS_SES_NT4; |
| @@ -343,12 +345,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
| 343 | return rc; | 345 | return rc; |
| 344 | 346 | ||
| 345 | kfree(ses->serverDomain); | 347 | kfree(ses->serverDomain); |
| 346 | ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ | 348 | ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL); |
| 347 | if (ses->serverDomain != NULL) { | 349 | if (ses->serverDomain != NULL) { |
| 348 | cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, | 350 | cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, |
| 349 | nls_cp); | 351 | nls_cp); |
| 350 | ses->serverDomain[2*len] = 0; | 352 | cFYI(1, ("serverDomain=%s", ses->serverDomain)); |
| 351 | ses->serverDomain[(2*len) + 1] = 0; | ||
| 352 | } | 353 | } |
| 353 | data += 2 * (len + 1); | 354 | data += 2 * (len + 1); |
| 354 | words_left -= len + 1; | 355 | words_left -= len + 1; |
| @@ -702,12 +703,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
| 702 | } | 703 | } |
| 703 | 704 | ||
| 704 | /* BB check if Unicode and decode strings */ | 705 | /* BB check if Unicode and decode strings */ |
| 705 | if (smb_buf->Flags2 & SMBFLG2_UNICODE) | 706 | if (smb_buf->Flags2 & SMBFLG2_UNICODE) { |
| 707 | /* unicode string area must be word-aligned */ | ||
| 708 | if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { | ||
| 709 | ++bcc_ptr; | ||
| 710 | --bytes_remaining; | ||
| 711 | } | ||
| 706 | rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, | 712 | rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, |
| 707 | ses, nls_cp); | 713 | ses, nls_cp); |
| 708 | else | 714 | } else { |
| 709 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, | 715 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, |
| 710 | ses, nls_cp); | 716 | ses, nls_cp); |
| 717 | } | ||
| 711 | 718 | ||
| 712 | ssetup_exit: | 719 | ssetup_exit: |
| 713 | if (spnego_key) { | 720 | if (spnego_key) { |
