Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (32 commits)
[CIFS] Fix double list addition in cifs posix open code
[CIFS] Allow raw ntlmssp code to be enabled with sec=ntlmssp
[CIFS] Fix SMB uid in NTLMSSP authenticate request
[CIFS] NTLMSSP reenabled after move from connect.c to sess.c
[CIFS] Remove sparse warning
[CIFS] remove checkpatch warning
[CIFS] Fix final user of old string conversion code
[CIFS] remove cifs_strfromUCS_le
[CIFS] NTLMSSP support moving into new file, old dead code removed
[CIFS] Fix endian conversion of vcnum field
[CIFS] Remove trailing whitespace
[CIFS] Remove sparse endian warnings
[CIFS] Add remaining ntlmssp flags and standardize field names
[CIFS] Fix build warning
cifs: fix length handling in cifs_get_name_from_search_buf
[CIFS] Remove unneeded QuerySymlink call and fix mapping for unmapped status
[CIFS] rename cifs_strndup to cifs_strndup_from_ucs
Added loop check when mounting DFS tree.
Enable dfs submounts to handle remote referrals.
[CIFS] Remove older session setup implementation
...

+811 -1643
+13
fs/cifs/CHANGES
··· 1 + Version 1.58 2 + ------------ 3 + Guard against buffer overruns in various UCS-2 to UTF-8 string conversions 4 + when the UTF-8 string is composed of unusually long (more than 4 byte) converted 5 + characters. Add support for mounting root of a share which redirects immediately 6 + to DFS target. Convert string conversion functions from Unicode to more 7 + accurately mark string length before allocating memory (which may help the 8 + rare cases where a UTF-8 string is much larger than the UCS2 string that 9 + we converted from). Fix endianness of the vcnum field used during 10 + session setup to distinguish multiple mounts to same server from different 11 + userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental 12 + flag to be set to 2, and mount must enable krb5 to turn on extended security). 13 + 1 14 Version 1.57 2 15 ------------ 3 16 Improve support for multiple security contexts to the same server. We
+9 -1
fs/cifs/README
··· 651 651 signing turned on in case buffer was modified 652 652 just before it was sent, also this flag will 653 653 be used to use the new experimental directory change 654 - notification code). 654 + notification code). When set to 2 enables 655 + an additional experimental feature, "raw ntlmssp" 656 + session establishment support (which allows 657 + specifying "sec=ntlmssp" on mount). The Linux cifs 658 + module will use ntlmv2 authentication encapsulated 659 + in "raw ntlmssp" (not using SPNEGO) when 660 + "sec=ntlmssp" is specified on mount. 661 + This support also requires building cifs with 662 + the CONFIG_CIFS_EXPERIMENTAL configuration flag. 655 663 656 664 These experimental features and tracing can be enabled by changing flags in 657 665 /proc/fs/cifs (after the cifs module has been installed or built into the
+14 -18
fs/cifs/cifs_dfs_ref.c
··· 340 340 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 341 341 342 342 for (i = 0; i < num_referrals; i++) { 343 + int len; 343 344 dump_referral(referrals+i); 344 - /* connect to a storage node */ 345 - if (referrals[i].flags & DFSREF_STORAGE_SERVER) { 346 - int len; 347 - len = strlen(referrals[i].node_name); 348 - if (len < 2) { 349 - cERROR(1, ("%s: Net Address path too short: %s", 345 + /* connect to a node */ 346 + len = strlen(referrals[i].node_name); 347 + if (len < 2) { 348 + cERROR(1, ("%s: Net Address path too short: %s", 350 349 __func__, referrals[i].node_name)); 351 - rc = -EINVAL; 352 - goto out_err; 353 - } 354 - mnt = cifs_dfs_do_refmount(nd->path.mnt, 355 - nd->path.dentry, 356 - referrals + i); 357 - cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", 358 - __func__, 350 + rc = -EINVAL; 351 + goto out_err; 352 + } 353 + mnt = cifs_dfs_do_refmount(nd->path.mnt, 354 + nd->path.dentry, referrals + i); 355 + cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, 359 356 referrals[i].node_name, mnt)); 360 357 361 - /* complete mount procedure if we accured submount */ 362 - if (!IS_ERR(mnt)) 363 - break; 364 - } 358 + /* complete mount procedure if we accured submount */ 359 + if (!IS_ERR(mnt)) 360 + break; 365 361 } 366 362 367 363 /* we need it cause for() above could exit without valid submount */
+182 -18
fs/cifs/cifs_unicode.c
··· 1 1 /* 2 2 * fs/cifs/cifs_unicode.c 3 3 * 4 - * Copyright (c) International Business Machines Corp., 2000,2005 4 + * Copyright (c) International Business Machines Corp., 2000,2009 5 5 * Modified by Steve French (sfrench@us.ibm.com) 6 6 * 7 7 * This program is free software; you can redistribute it and/or modify ··· 26 26 #include "cifs_debug.h" 27 27 28 28 /* 29 - * NAME: cifs_strfromUCS() 29 + * cifs_ucs2_bytes - how long will a string be after conversion? 30 + * @ucs - pointer to input string 31 + * @maxbytes - don't go past this many bytes of input string 32 + * @codepage - destination codepage 30 33 * 31 - * FUNCTION: Convert little-endian unicode string to character string 32 - * 34 + * Walk a ucs2le string and return the number of bytes that the string will 35 + * be after being converted to the given charset, not including any null 36 + * termination required. Don't walk past maxbytes in the source buffer. 33 37 */ 34 38 int 35 - cifs_strfromUCS_le(char *to, const __le16 *from, 36 - int len, const struct nls_table *codepage) 39 + cifs_ucs2_bytes(const __le16 *from, int maxbytes, 40 + const struct nls_table *codepage) 37 41 { 38 42 int i; 39 - int outlen = 0; 43 + int charlen, outlen = 0; 44 + int maxwords = maxbytes / 2; 45 + char tmp[NLS_MAX_CHARSET_SIZE]; 40 46 41 - for (i = 0; (i < len) && from[i]; i++) { 42 - int charlen; 43 - /* 2.4.0 kernel or greater */ 44 - charlen = 45 - codepage->uni2char(le16_to_cpu(from[i]), &to[outlen], 46 - NLS_MAX_CHARSET_SIZE); 47 - if (charlen > 0) { 47 + for (i = 0; from[i] && i < maxwords; i++) { 48 + charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, 49 + NLS_MAX_CHARSET_SIZE); 50 + if (charlen > 0) 48 51 outlen += charlen; 49 - } else { 50 - to[outlen++] = '?'; 51 - } 52 + else 53 + outlen++; 52 54 } 53 - to[outlen] = 0; 55 + 56 + return outlen; 57 + } 58 + 59 + /* 60 + * cifs_mapchar - convert a little-endian char to proper char in codepage 61 + * @target - where converted character should be copied 62 + * @src_char - 2 byte little-endian source character 63 + * @cp - codepage to which character should be converted 64 + * @mapchar - should character be mapped according to mapchars mount option? 65 + * 66 + * This function handles the conversion of a single character. It is the 67 + * responsibility of the caller to ensure that the target buffer is large 68 + * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). 69 + */ 70 + static int 71 + cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, 72 + bool mapchar) 73 + { 74 + int len = 1; 75 + 76 + if (!mapchar) 77 + goto cp_convert; 78 + 79 + /* 80 + * BB: Cannot handle remapping UNI_SLASH until all the calls to 81 + * build_path_from_dentry are modified, as they use slash as 82 + * separator. 83 + */ 84 + switch (le16_to_cpu(src_char)) { 85 + case UNI_COLON: 86 + *target = ':'; 87 + break; 88 + case UNI_ASTERIK: 89 + *target = '*'; 90 + break; 91 + case UNI_QUESTION: 92 + *target = '?'; 93 + break; 94 + case UNI_PIPE: 95 + *target = '|'; 96 + break; 97 + case UNI_GRTRTHAN: 98 + *target = '>'; 99 + break; 100 + case UNI_LESSTHAN: 101 + *target = '<'; 102 + break; 103 + default: 104 + goto cp_convert; 105 + } 106 + 107 + out: 108 + return len; 109 + 110 + cp_convert: 111 + len = cp->uni2char(le16_to_cpu(src_char), target, 112 + NLS_MAX_CHARSET_SIZE); 113 + if (len <= 0) { 114 + *target = '?'; 115 + len = 1; 116 + } 117 + goto out; 118 + } 119 + 120 + /* 121 + * cifs_from_ucs2 - convert utf16le string to local charset 122 + * @to - destination buffer 123 + * @from - source buffer 124 + * @tolen - destination buffer size (in bytes) 125 + * @fromlen - source buffer size (in bytes) 126 + * @codepage - codepage to which characters should be converted 127 + * @mapchar - should characters be remapped according to the mapchars option? 128 + * 129 + * Convert a little-endian ucs2le string (as sent by the server) to a string 130 + * in the provided codepage. The tolen and fromlen parameters are to ensure 131 + * that the code doesn't walk off of the end of the buffer (which is always 132 + * a danger if the alignment of the source buffer is off). The destination 133 + * string is always properly null terminated and fits in the destination 134 + * buffer. Returns the length of the destination string in bytes (including 135 + * null terminator). 136 + * 137 + * Note that some windows versions actually send multiword UTF-16 characters 138 + * instead of straight UCS-2. The linux nls routines however aren't able to 139 + * deal with those characters properly. In the event that we get some of 140 + * those characters, they won't be translated properly. 141 + */ 142 + int 143 + cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, 144 + const struct nls_table *codepage, bool mapchar) 145 + { 146 + int i, charlen, safelen; 147 + int outlen = 0; 148 + int nullsize = nls_nullsize(codepage); 149 + int fromwords = fromlen / 2; 150 + char tmp[NLS_MAX_CHARSET_SIZE]; 151 + 152 + /* 153 + * because the chars can be of varying widths, we need to take care 154 + * not to overflow the destination buffer when we get close to the 155 + * end of it. Until we get to this offset, we don't need to check 156 + * for overflow however. 157 + */ 158 + safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); 159 + 160 + for (i = 0; i < fromwords && from[i]; i++) { 161 + /* 162 + * check to see if converting this character might make the 163 + * conversion bleed into the null terminator 164 + */ 165 + if (outlen >= safelen) { 166 + charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); 167 + if ((outlen + charlen) > (tolen - nullsize)) 168 + break; 169 + } 170 + 171 + /* put converted char into 'to' buffer */ 172 + charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); 173 + outlen += charlen; 174 + } 175 + 176 + /* properly null-terminate string */ 177 + for (i = 0; i < nullsize; i++) 178 + to[outlen++] = 0; 179 + 54 180 return outlen; 55 181 } 56 182 ··· 212 86 213 87 to[i] = 0; 214 88 return i; 89 + } 90 + 91 + /* 92 + * cifs_strndup_from_ucs - copy a string from wire format to the local codepage 93 + * @src - source string 94 + * @maxlen - don't walk past this many bytes in the source string 95 + * @is_unicode - is this a unicode string? 96 + * @codepage - destination codepage 97 + * 98 + * Take a string given by the server, convert it to the local codepage and 99 + * put it in a new buffer. Returns a pointer to the new string or NULL on 100 + * error. 101 + */ 102 + char * 103 + cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, 104 + const struct nls_table *codepage) 105 + { 106 + int len; 107 + char *dst; 108 + 109 + if (is_unicode) { 110 + len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage); 111 + len += nls_nullsize(codepage); 112 + dst = kmalloc(len, GFP_KERNEL); 113 + if (!dst) 114 + return NULL; 115 + cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage, 116 + false); 117 + } else { 118 + len = strnlen(src, maxlen); 119 + len++; 120 + dst = kmalloc(len, GFP_KERNEL); 121 + if (!dst) 122 + return NULL; 123 + strlcpy(dst, src, len); 124 + } 125 + 126 + return dst; 215 127 } 216 128
+21 -2
fs/cifs/cifs_unicode.h
··· 5 5 * Convert a unicode character to upper or lower case using 6 6 * compressed tables. 7 7 * 8 - * Copyright (c) International Business Machines Corp., 2000,2007 8 + * Copyright (c) International Business Machines Corp., 2000,2009 9 9 * 10 10 * This program is free software; you can redistribute it and/or modify 11 11 * it under the terms of the GNU General Public License as published by ··· 37 37 38 38 #define UNIUPR_NOLOWER /* Example to not expand lower case tables */ 39 39 40 + /* 41 + * Windows maps these to the user defined 16 bit Unicode range since they are 42 + * reserved symbols (along with \ and /), otherwise illegal to store 43 + * in filenames in NTFS 44 + */ 45 + #define UNI_ASTERIK (__u16) ('*' + 0xF000) 46 + #define UNI_QUESTION (__u16) ('?' + 0xF000) 47 + #define UNI_COLON (__u16) (':' + 0xF000) 48 + #define UNI_GRTRTHAN (__u16) ('>' + 0xF000) 49 + #define UNI_LESSTHAN (__u16) ('<' + 0xF000) 50 + #define UNI_PIPE (__u16) ('|' + 0xF000) 51 + #define UNI_SLASH (__u16) ('\\' + 0xF000) 52 + 40 53 /* Just define what we want from uniupr.h. We don't want to define the tables 41 54 * in each source file. 42 55 */ ··· 72 59 #endif /* UNIUPR_NOLOWER */ 73 60 74 61 #ifdef __KERNEL__ 75 - int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *); 62 + int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, 63 + const struct nls_table *codepage, bool mapchar); 64 + int cifs_ucs2_bytes(const __le16 *from, int maxbytes, 65 + const struct nls_table *codepage); 76 66 int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); 67 + char *cifs_strndup_from_ucs(const char *src, const int maxlen, 68 + const bool is_unicode, 69 + const struct nls_table *codepage); 77 70 #endif 78 71 79 72 /*
+1 -1
fs/cifs/cifsfs.h
··· 100 100 extern const struct export_operations cifs_export_ops; 101 101 #endif /* EXPERIMENTAL */ 102 102 103 - #define CIFS_VERSION "1.57" 103 + #define CIFS_VERSION "1.58" 104 104 #endif /* _CIFSFS_H */
+9 -7
fs/cifs/cifsglob.h
··· 82 82 LANMAN, /* Legacy LANMAN auth */ 83 83 NTLM, /* Legacy NTLM012 auth with NTLM hash */ 84 84 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 85 - RawNTLMSSP, /* NTLMSSP without SPNEGO */ 86 - NTLMSSP, /* NTLMSSP via SPNEGO */ 85 + RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ 86 + NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */ 87 87 Kerberos, /* Kerberos via SPNEGO */ 88 88 MSKerberos, /* MS Kerberos via SPNEGO */ 89 89 }; ··· 531 531 #define CIFSSEC_MAY_PLNTXT 0 532 532 #endif /* weak passwords */ 533 533 #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ 534 + #define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */ 534 535 535 536 #define CIFSSEC_MUST_SIGN 0x01001 536 537 /* note that only one of the following can be set so the ··· 544 543 #define CIFSSEC_MUST_LANMAN 0x10010 545 544 #define CIFSSEC_MUST_PLNTXT 0x20020 546 545 #ifdef CONFIG_CIFS_UPCALL 547 - #define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */ 546 + #define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */ 548 547 #else 549 - #define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ 548 + #define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */ 550 549 #endif /* UPCALL */ 551 550 #else /* do not allow weak pw hash */ 552 551 #ifdef CONFIG_CIFS_UPCALL 553 - #define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */ 552 + #define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ 554 553 #else 555 - #define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */ 554 + #define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */ 556 555 #endif /* UPCALL */ 557 556 #endif /* WEAK_PW_HASH */ 558 557 #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ 558 + #define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ 559 559 560 560 #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2) 561 561 #define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2) 562 - #define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5) 562 + #define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP) 563 563 /* 564 564 ***************************************************************** 565 565 * All constants go here
+1 -4
fs/cifs/cifsproto.h
··· 260 260 const struct nls_table *nls_codepage); 261 261 extern int CIFSSMBUnixQuerySymLink(const int xid, 262 262 struct cifsTconInfo *tcon, 263 - const unsigned char *searchName, 264 - char *syminfo, const int buflen, 263 + const unsigned char *searchName, char **syminfo, 265 264 const struct nls_table *nls_codepage); 266 265 extern int CIFSSMBQueryReparseLinkInfo(const int xid, 267 266 struct cifsTconInfo *tcon, ··· 306 307 const unsigned char *searchName, __u64 *inode_number, 307 308 const struct nls_table *nls_codepage, 308 309 int remap_special_chars); 309 - extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, 310 - const struct nls_table *codepage); 311 310 extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, 312 311 const struct nls_table *cp, int mapChars); 313 312
+83 -134
fs/cifs/cifssmb.c
··· 1 1 /* 2 2 * fs/cifs/cifssmb.c 3 3 * 4 - * Copyright (C) International Business Machines Corp., 2002,2008 4 + * Copyright (C) International Business Machines Corp., 2002,2009 5 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 6 * 7 7 * Contains the routines for constructing the SMB PDUs themselves ··· 80 80 #define CIFS_NUM_PROT 1 81 81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */ 82 82 #endif /* CIFS_POSIX */ 83 - 84 - /* Allocates buffer into dst and copies smb string from src to it. 85 - * caller is responsible for freeing dst if function returned 0. 86 - * returns: 87 - * on success - 0 88 - * on failure - errno 89 - */ 90 - static int 91 - cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, 92 - const bool is_unicode, const struct nls_table *nls_codepage) 93 - { 94 - int plen; 95 - 96 - if (is_unicode) { 97 - plen = UniStrnlen((wchar_t *)src, maxlen); 98 - *dst = kmalloc(plen + 2, GFP_KERNEL); 99 - if (!*dst) 100 - goto cifs_strncpy_to_host_ErrExit; 101 - cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); 102 - } else { 103 - plen = strnlen(src, maxlen); 104 - *dst = kmalloc(plen + 2, GFP_KERNEL); 105 - if (!*dst) 106 - goto cifs_strncpy_to_host_ErrExit; 107 - strncpy(*dst, src, plen); 108 - } 109 - (*dst)[plen] = 0; 110 - (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */ 111 - return 0; 112 - 113 - cifs_strncpy_to_host_ErrExit: 114 - cERROR(1, ("Failed to allocate buffer for string\n")); 115 - return -ENOMEM; 116 - } 117 - 118 83 119 84 /* Mark as invalid, all open files on tree connections since they 120 85 were closed when session to server was lost */ ··· 449 484 cFYI(1, ("Kerberos only mechanism, enable extended security")); 450 485 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 451 486 } 487 + #ifdef CONFIG_CIFS_EXPERIMENTAL 488 + else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) 489 + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 490 + else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { 491 + cFYI(1, ("NTLMSSP only mechanism, enable extended security")); 492 + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 493 + } 494 + #endif 452 495 453 496 count = 0; 454 497 for (i = 0; i < CIFS_NUM_PROT; i++) { ··· 593 620 server->secType = NTLMv2; 594 621 else if (secFlags & CIFSSEC_MAY_KRB5) 595 622 server->secType = Kerberos; 623 + else if (secFlags & CIFSSEC_MAY_NTLMSSP) 624 + server->secType = NTLMSSP; 596 625 else if (secFlags & CIFSSEC_MAY_LANMAN) 597 626 server->secType = LANMAN; 598 627 /* #ifdef CONFIG_CIFS_EXPERIMENTAL ··· 2392 2417 2393 2418 int 2394 2419 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, 2395 - const unsigned char *searchName, 2396 - char *symlinkinfo, const int buflen, 2420 + const unsigned char *searchName, char **symlinkinfo, 2397 2421 const struct nls_table *nls_codepage) 2398 2422 { 2399 2423 /* SMB_QUERY_FILE_UNIX_LINK */ ··· 2402 2428 int bytes_returned; 2403 2429 int name_len; 2404 2430 __u16 params, byte_count; 2431 + char *data_start; 2405 2432 2406 2433 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName)); 2407 2434 ··· 2457 2482 /* decode response */ 2458 2483 2459 2484 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 2460 - if (rc || (pSMBr->ByteCount < 2)) 2461 2485 /* BB also check enough total bytes returned */ 2462 - rc = -EIO; /* bad smb */ 2486 + if (rc || (pSMBr->ByteCount < 2)) 2487 + rc = -EIO; 2463 2488 else { 2464 - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 2465 - __u16 count = le16_to_cpu(pSMBr->t2.DataCount); 2489 + bool is_unicode; 2490 + u16 count = le16_to_cpu(pSMBr->t2.DataCount); 2466 2491 2467 - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 2468 - name_len = UniStrnlen((wchar_t *) ((char *) 2469 - &pSMBr->hdr.Protocol + data_offset), 2470 - min_t(const int, buflen, count) / 2); 2492 + data_start = ((char *) &pSMBr->hdr.Protocol) + 2493 + le16_to_cpu(pSMBr->t2.DataOffset); 2494 + 2495 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) 2496 + is_unicode = true; 2497 + else 2498 + is_unicode = false; 2499 + 2471 2500 /* BB FIXME investigate remapping reserved chars here */ 2472 - cifs_strfromUCS_le(symlinkinfo, 2473 - (__le16 *) ((char *)&pSMBr->hdr.Protocol 2474 - + data_offset), 2475 - name_len, nls_codepage); 2476 - } else { 2477 - strncpy(symlinkinfo, 2478 - (char *) &pSMBr->hdr.Protocol + 2479 - data_offset, 2480 - min_t(const int, buflen, count)); 2481 - } 2482 - symlinkinfo[buflen] = 0; 2483 - /* just in case so calling code does not go off the end of buffer */ 2501 + *symlinkinfo = cifs_strndup_from_ucs(data_start, count, 2502 + is_unicode, nls_codepage); 2503 + if (!symlinkinfo) 2504 + rc = -ENOMEM; 2484 2505 } 2485 2506 } 2486 2507 cifs_buf_release(pSMB); ··· 2574 2603 *pparmlen = parm_count; 2575 2604 return 0; 2576 2605 } 2577 - #endif /* CIFS_EXPERIMENTAL */ 2578 2606 2579 2607 int 2580 2608 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, ··· 2583 2613 { 2584 2614 int rc = 0; 2585 2615 int bytes_returned; 2586 - int name_len; 2587 2616 struct smb_com_transaction_ioctl_req *pSMB; 2588 2617 struct smb_com_transaction_ioctl_rsp *pSMBr; 2589 2618 ··· 2619 2650 } else { /* decode response */ 2620 2651 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); 2621 2652 __u32 data_count = le32_to_cpu(pSMBr->DataCount); 2622 - if ((pSMBr->ByteCount < 2) || (data_offset > 512)) 2653 + if ((pSMBr->ByteCount < 2) || (data_offset > 512)) { 2623 2654 /* BB also check enough total bytes returned */ 2624 2655 rc = -EIO; /* bad smb */ 2625 - else { 2626 - if (data_count && (data_count < 2048)) { 2627 - char *end_of_smb = 2 /* sizeof byte count */ + 2628 - pSMBr->ByteCount + 2629 - (char *)&pSMBr->ByteCount; 2656 + goto qreparse_out; 2657 + } 2658 + if (data_count && (data_count < 2048)) { 2659 + char *end_of_smb = 2 /* sizeof byte count */ + 2660 + pSMBr->ByteCount + (char *)&pSMBr->ByteCount; 2630 2661 2631 - struct reparse_data *reparse_buf = 2662 + struct reparse_data *reparse_buf = 2632 2663 (struct reparse_data *) 2633 2664 ((char *)&pSMBr->hdr.Protocol 2634 2665 + data_offset); 2635 - if ((char *)reparse_buf >= end_of_smb) { 2636 - rc = -EIO; 2637 - goto qreparse_out; 2638 - } 2639 - if ((reparse_buf->LinkNamesBuf + 2640 - reparse_buf->TargetNameOffset + 2641 - reparse_buf->TargetNameLen) > 2642 - end_of_smb) { 2643 - cFYI(1, ("reparse buf beyond SMB")); 2644 - rc = -EIO; 2645 - goto qreparse_out; 2646 - } 2666 + if ((char *)reparse_buf >= end_of_smb) { 2667 + rc = -EIO; 2668 + goto qreparse_out; 2669 + } 2670 + if ((reparse_buf->LinkNamesBuf + 2671 + reparse_buf->TargetNameOffset + 2672 + reparse_buf->TargetNameLen) > end_of_smb) { 2673 + cFYI(1, ("reparse buf beyond SMB")); 2674 + rc = -EIO; 2675 + goto qreparse_out; 2676 + } 2647 2677 2648 - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 2649 - name_len = UniStrnlen((wchar_t *) 2678 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 2679 + cifs_from_ucs2(symlinkinfo, (__le16 *) 2650 2680 (reparse_buf->LinkNamesBuf + 2651 2681 reparse_buf->TargetNameOffset), 2652 - min(buflen/2, 2653 - reparse_buf->TargetNameLen / 2)); 2654 - cifs_strfromUCS_le(symlinkinfo, 2655 - (__le16 *) (reparse_buf->LinkNamesBuf + 2656 - reparse_buf->TargetNameOffset), 2657 - name_len, nls_codepage); 2658 - } else { /* ASCII names */ 2659 - strncpy(symlinkinfo, 2660 - reparse_buf->LinkNamesBuf + 2661 - reparse_buf->TargetNameOffset, 2662 - min_t(const int, buflen, 2663 - reparse_buf->TargetNameLen)); 2664 - } 2665 - } else { 2666 - rc = -EIO; 2667 - cFYI(1, ("Invalid return data count on " 2668 - "get reparse info ioctl")); 2682 + buflen, 2683 + reparse_buf->TargetNameLen, 2684 + nls_codepage, 0); 2685 + } else { /* ASCII names */ 2686 + strncpy(symlinkinfo, 2687 + reparse_buf->LinkNamesBuf + 2688 + reparse_buf->TargetNameOffset, 2689 + min_t(const int, buflen, 2690 + reparse_buf->TargetNameLen)); 2669 2691 } 2670 - symlinkinfo[buflen] = 0; /* just in case so the caller 2671 - does not go off the end of the buffer */ 2672 - cFYI(1, ("readlink result - %s", symlinkinfo)); 2692 + } else { 2693 + rc = -EIO; 2694 + cFYI(1, ("Invalid return data count on " 2695 + "get reparse info ioctl")); 2673 2696 } 2697 + symlinkinfo[buflen] = 0; /* just in case so the caller 2698 + does not go off the end of the buffer */ 2699 + cFYI(1, ("readlink result - %s", symlinkinfo)); 2674 2700 } 2701 + 2675 2702 qreparse_out: 2676 2703 cifs_buf_release(pSMB); 2677 2704 ··· 2676 2711 2677 2712 return rc; 2678 2713 } 2714 + #endif /* CIFS_EXPERIMENTAL */ 2679 2715 2680 2716 #ifdef CONFIG_CIFS_POSIX 2681 2717 ··· 3894 3928 return rc; 3895 3929 } 3896 3930 3897 - /* computes length of UCS string converted to host codepage 3898 - * @src: UCS string 3899 - * @maxlen: length of the input string in UCS characters 3900 - * (not in bytes) 3901 - * 3902 - * return: size of input string in host codepage 3903 - */ 3904 - static int hostlen_fromUCS(const __le16 *src, const int maxlen, 3905 - const struct nls_table *nls_codepage) { 3906 - int i; 3907 - int hostlen = 0; 3908 - char to[4]; 3909 - int charlen; 3910 - for (i = 0; (i < maxlen) && src[i]; ++i) { 3911 - charlen = nls_codepage->uni2char(le16_to_cpu(src[i]), 3912 - to, NLS_MAX_CHARSET_SIZE); 3913 - hostlen += charlen > 0 ? charlen : 1; 3914 - } 3915 - return hostlen; 3916 - } 3917 - 3918 3931 /* parses DFS refferal V3 structure 3919 3932 * caller is responsible for freeing target_nodes 3920 3933 * returns: ··· 3939 3994 3940 3995 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", 3941 3996 *num_of_nodes, 3942 - le16_to_cpu(pSMBr->DFSFlags))); 3997 + le32_to_cpu(pSMBr->DFSFlags))); 3943 3998 3944 3999 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * 3945 4000 *num_of_nodes, GFP_KERNEL); ··· 3955 4010 int max_len; 3956 4011 struct dfs_info3_param *node = (*target_nodes)+i; 3957 4012 3958 - node->flags = le16_to_cpu(pSMBr->DFSFlags); 4013 + node->flags = le32_to_cpu(pSMBr->DFSFlags); 3959 4014 if (is_unicode) { 3960 4015 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, 3961 4016 GFP_KERNEL); 3962 4017 cifsConvertToUCS((__le16 *) tmp, searchName, 3963 4018 PATH_MAX, nls_codepage, remap); 3964 - node->path_consumed = hostlen_fromUCS(tmp, 3965 - le16_to_cpu(pSMBr->PathConsumed)/2, 4019 + node->path_consumed = cifs_ucs2_bytes(tmp, 4020 + le16_to_cpu(pSMBr->PathConsumed), 3966 4021 nls_codepage); 3967 4022 kfree(tmp); 3968 4023 } else ··· 3974 4029 /* copy DfsPath */ 3975 4030 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); 3976 4031 max_len = data_end - temp; 3977 - rc = cifs_strncpy_to_host(&(node->path_name), temp, 3978 - max_len, is_unicode, nls_codepage); 3979 - if (rc) 4032 + node->path_name = cifs_strndup_from_ucs(temp, max_len, 4033 + is_unicode, nls_codepage); 4034 + if (IS_ERR(node->path_name)) { 4035 + rc = PTR_ERR(node->path_name); 4036 + node->path_name = NULL; 3980 4037 goto parse_DFS_referrals_exit; 4038 + } 3981 4039 3982 4040 /* copy link target UNC */ 3983 4041 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); 3984 4042 max_len = data_end - temp; 3985 - rc = cifs_strncpy_to_host(&(node->node_name), temp, 3986 - max_len, is_unicode, nls_codepage); 3987 - if (rc) 4043 + node->node_name = cifs_strndup_from_ucs(temp, max_len, 4044 + is_unicode, nls_codepage); 4045 + if (IS_ERR(node->node_name)) { 4046 + rc = PTR_ERR(node->node_name); 4047 + node->node_name = NULL; 3988 4048 goto parse_DFS_referrals_exit; 3989 - 3990 - ref += le16_to_cpu(ref->Size); 4049 + } 3991 4050 } 3992 4051 3993 4052 parse_DFS_referrals_exit:
+47 -1143
fs/cifs/connect.c
··· 1 1 /* 2 2 * fs/cifs/connect.c 3 3 * 4 - * Copyright (C) International Business Machines Corp., 2002,2008 4 + * Copyright (C) International Business Machines Corp., 2002,2009 5 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 6 * 7 7 * This library is free software; you can redistribute it and/or modify ··· 32 32 #include <linux/kthread.h> 33 33 #include <linux/pagevec.h> 34 34 #include <linux/freezer.h> 35 + #include <linux/namei.h> 35 36 #include <asm/uaccess.h> 36 37 #include <asm/processor.h> 37 38 #include <net/ipv6.h> ··· 979 978 return 1; 980 979 } else if (strnicmp(value, "krb5", 4) == 0) { 981 980 vol->secFlg |= CIFSSEC_MAY_KRB5; 981 + #ifdef CONFIG_CIFS_EXPERIMENTAL 982 + } else if (strnicmp(value, "ntlmsspi", 8) == 0) { 983 + vol->secFlg |= CIFSSEC_MAY_NTLMSSP | 984 + CIFSSEC_MUST_SIGN; 985 + } else if (strnicmp(value, "ntlmssp", 7) == 0) { 986 + vol->secFlg |= CIFSSEC_MAY_NTLMSSP; 987 + #endif 982 988 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 983 989 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | 984 990 CIFSSEC_MUST_SIGN; ··· 2286 2278 #ifdef CONFIG_CIFS_DFS_UPCALL 2287 2279 struct dfs_info3_param *referrals = NULL; 2288 2280 unsigned int num_referrals = 0; 2281 + int referral_walks_count = 0; 2289 2282 try_mount_again: 2290 2283 #endif 2291 2284 full_path = NULL; ··· 2534 2525 /* get referral if needed */ 2535 2526 if (rc == -EREMOTE) { 2536 2527 #ifdef CONFIG_CIFS_DFS_UPCALL 2528 + if (referral_walks_count > MAX_NESTED_LINKS) { 2529 + /* 2530 + * BB: when we implement proper loop detection, 2531 + * we will remove this check. But now we need it 2532 + * to prevent an indefinite loop if 'DFS tree' is 2533 + * misconfigured (i.e. has loops). 2534 + */ 2535 + rc = -ELOOP; 2536 + goto mount_fail_check; 2537 + } 2537 2538 /* convert forward to back slashes in prepath here if needed */ 2538 2539 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) 2539 2540 convert_delimiter(cifs_sb->prepath, ··· 2577 2558 cleanup_volume_info(&volume_info); 2578 2559 FreeXid(xid); 2579 2560 kfree(full_path); 2561 + referral_walks_count++; 2580 2562 goto try_mount_again; 2581 2563 } 2582 2564 #else /* No DFS support, return error on mount */ ··· 2612 2592 return rc; 2613 2593 } 2614 2594 2615 - static int 2616 - CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, 2617 - char session_key[CIFS_SESS_KEY_SIZE], 2618 - const struct nls_table *nls_codepage) 2619 - { 2620 - struct smb_hdr *smb_buffer; 2621 - struct smb_hdr *smb_buffer_response; 2622 - SESSION_SETUP_ANDX *pSMB; 2623 - SESSION_SETUP_ANDX *pSMBr; 2624 - char *bcc_ptr; 2625 - char *user; 2626 - char *domain; 2627 - int rc = 0; 2628 - int remaining_words = 0; 2629 - int bytes_returned = 0; 2630 - int len; 2631 - __u32 capabilities; 2632 - __u16 count; 2633 - 2634 - cFYI(1, ("In sesssetup")); 2635 - if (ses == NULL) 2636 - return -EINVAL; 2637 - user = ses->userName; 2638 - domain = ses->domainName; 2639 - smb_buffer = cifs_buf_get(); 2640 - 2641 - if (smb_buffer == NULL) 2642 - return -ENOMEM; 2643 - 2644 - smb_buffer_response = smb_buffer; 2645 - pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; 2646 - 2647 - /* send SMBsessionSetup here */ 2648 - header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2649 - NULL /* no tCon exists yet */ , 13 /* wct */ ); 2650 - 2651 - smb_buffer->Mid = GetNextMid(ses->server); 2652 - pSMB->req_no_secext.AndXCommand = 0xFF; 2653 - pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 2654 - pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 2655 - 2656 - if (ses->server->secMode & 2657 - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 2658 - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 2659 - 2660 - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 2661 - CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; 2662 - if (ses->capabilities & CAP_UNICODE) { 2663 - smb_buffer->Flags2 |= SMBFLG2_UNICODE; 2664 - capabilities |= CAP_UNICODE; 2665 - } 2666 - if (ses->capabilities & CAP_STATUS32) { 2667 - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; 2668 - capabilities |= CAP_STATUS32; 2669 - } 2670 - if (ses->capabilities & CAP_DFS) { 2671 - smb_buffer->Flags2 |= SMBFLG2_DFS; 2672 - capabilities |= CAP_DFS; 2673 - } 2674 - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 2675 - 2676 - pSMB->req_no_secext.CaseInsensitivePasswordLength = 2677 - cpu_to_le16(CIFS_SESS_KEY_SIZE); 2678 - 2679 - pSMB->req_no_secext.CaseSensitivePasswordLength = 2680 - cpu_to_le16(CIFS_SESS_KEY_SIZE); 2681 - bcc_ptr = pByteArea(smb_buffer); 2682 - memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); 2683 - bcc_ptr += CIFS_SESS_KEY_SIZE; 2684 - memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); 2685 - bcc_ptr += CIFS_SESS_KEY_SIZE; 2686 - 2687 - if (ses->capabilities & CAP_UNICODE) { 2688 - if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ 2689 - *bcc_ptr = 0; 2690 - bcc_ptr++; 2691 - } 2692 - if (user == NULL) 2693 - bytes_returned = 0; /* skip null user */ 2694 - else 2695 - bytes_returned = 2696 - cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, 2697 - nls_codepage); 2698 - /* convert number of 16 bit words to bytes */ 2699 - bcc_ptr += 2 * bytes_returned; 2700 - bcc_ptr += 2; /* trailing null */ 2701 - if (domain == NULL) 2702 - bytes_returned = 2703 - cifs_strtoUCS((__le16 *) bcc_ptr, 2704 - "CIFS_LINUX_DOM", 32, nls_codepage); 2705 - else 2706 - bytes_returned = 2707 - cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, 2708 - nls_codepage); 2709 - bcc_ptr += 2 * bytes_returned; 2710 - bcc_ptr += 2; 2711 - bytes_returned = 2712 - cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 2713 - 32, nls_codepage); 2714 - bcc_ptr += 2 * bytes_returned; 2715 - bytes_returned = 2716 - cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 2717 - 32, nls_codepage); 2718 - bcc_ptr += 2 * bytes_returned; 2719 - bcc_ptr += 2; 2720 - bytes_returned = 2721 - cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 2722 - 64, nls_codepage); 2723 - bcc_ptr += 2 * bytes_returned; 2724 - bcc_ptr += 2; 2725 - } else { 2726 - if (user != NULL) { 2727 - strncpy(bcc_ptr, user, 200); 2728 - bcc_ptr += strnlen(user, 200); 2729 - } 2730 - *bcc_ptr = 0; 2731 - bcc_ptr++; 2732 - if (domain == NULL) { 2733 - strcpy(bcc_ptr, "CIFS_LINUX_DOM"); 2734 - bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; 2735 - } else { 2736 - strncpy(bcc_ptr, domain, 64); 2737 - bcc_ptr += strnlen(domain, 64); 2738 - *bcc_ptr = 0; 2739 - bcc_ptr++; 2740 - } 2741 - strcpy(bcc_ptr, "Linux version "); 2742 - bcc_ptr += strlen("Linux version "); 2743 - strcpy(bcc_ptr, utsname()->release); 2744 - bcc_ptr += strlen(utsname()->release) + 1; 2745 - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); 2746 - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; 2747 - } 2748 - count = (long) bcc_ptr - (long) pByteArea(smb_buffer); 2749 - smb_buffer->smb_buf_length += count; 2750 - pSMB->req_no_secext.ByteCount = cpu_to_le16(count); 2751 - 2752 - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, 2753 - &bytes_returned, CIFS_LONG_OP); 2754 - if (rc) { 2755 - /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ 2756 - } else if ((smb_buffer_response->WordCount == 3) 2757 - || (smb_buffer_response->WordCount == 4)) { 2758 - __u16 action = le16_to_cpu(pSMBr->resp.Action); 2759 - __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 2760 - if (action & GUEST_LOGIN) 2761 - cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ 2762 - ses->Suid = smb_buffer_response->Uid; /* UID left in wire format 2763 - (little endian) */ 2764 - cFYI(1, ("UID = %d ", ses->Suid)); 2765 - /* response can have either 3 or 4 word count - Samba sends 3 */ 2766 - bcc_ptr = pByteArea(smb_buffer_response); 2767 - if ((pSMBr->resp.hdr.WordCount == 3) 2768 - || ((pSMBr->resp.hdr.WordCount == 4) 2769 - && (blob_len < pSMBr->resp.ByteCount))) { 2770 - if (pSMBr->resp.hdr.WordCount == 4) 2771 - bcc_ptr += blob_len; 2772 - 2773 - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 2774 - if ((long) (bcc_ptr) % 2) { 2775 - remaining_words = 2776 - (BCC(smb_buffer_response) - 1) / 2; 2777 - /* Unicode strings must be word 2778 - aligned */ 2779 - bcc_ptr++; 2780 - } else { 2781 - remaining_words = 2782 - BCC(smb_buffer_response) / 2; 2783 - } 2784 - len = 2785 - UniStrnlen((wchar_t *) bcc_ptr, 2786 - remaining_words - 1); 2787 - /* We look for obvious messed up bcc or strings in response so we do not go off 2788 - the end since (at least) WIN2K and Windows XP have a major bug in not null 2789 - terminating last Unicode string in response */ 2790 - kfree(ses->serverOS); 2791 - ses->serverOS = kzalloc(2 * (len + 1), 2792 - GFP_KERNEL); 2793 - if (ses->serverOS == NULL) 2794 - goto sesssetup_nomem; 2795 - cifs_strfromUCS_le(ses->serverOS, 2796 - (__le16 *)bcc_ptr, 2797 - len, nls_codepage); 2798 - bcc_ptr += 2 * (len + 1); 2799 - remaining_words -= len + 1; 2800 - ses->serverOS[2 * len] = 0; 2801 - ses->serverOS[1 + (2 * len)] = 0; 2802 - if (remaining_words > 0) { 2803 - len = UniStrnlen((wchar_t *)bcc_ptr, 2804 - remaining_words-1); 2805 - kfree(ses->serverNOS); 2806 - ses->serverNOS = kzalloc(2 * (len + 1), 2807 - GFP_KERNEL); 2808 - if (ses->serverNOS == NULL) 2809 - goto sesssetup_nomem; 2810 - cifs_strfromUCS_le(ses->serverNOS, 2811 - (__le16 *)bcc_ptr, 2812 - len, nls_codepage); 2813 - bcc_ptr += 2 * (len + 1); 2814 - ses->serverNOS[2 * len] = 0; 2815 - ses->serverNOS[1 + (2 * len)] = 0; 2816 - if (strncmp(ses->serverNOS, 2817 - "NT LAN Manager 4", 16) == 0) { 2818 - cFYI(1, ("NT4 server")); 2819 - ses->flags |= CIFS_SES_NT4; 2820 - } 2821 - remaining_words -= len + 1; 2822 - if (remaining_words > 0) { 2823 - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2824 - /* last string is not always null terminated 2825 - (for e.g. for Windows XP & 2000) */ 2826 - kfree(ses->serverDomain); 2827 - ses->serverDomain = 2828 - kzalloc(2*(len+1), 2829 - GFP_KERNEL); 2830 - if (ses->serverDomain == NULL) 2831 - goto sesssetup_nomem; 2832 - cifs_strfromUCS_le(ses->serverDomain, 2833 - (__le16 *)bcc_ptr, 2834 - len, nls_codepage); 2835 - bcc_ptr += 2 * (len + 1); 2836 - ses->serverDomain[2*len] = 0; 2837 - ses->serverDomain[1+(2*len)] = 0; 2838 - } else { /* else no more room so create 2839 - dummy domain string */ 2840 - kfree(ses->serverDomain); 2841 - ses->serverDomain = 2842 - kzalloc(2, GFP_KERNEL); 2843 - } 2844 - } else { /* no room so create dummy domain 2845 - and NOS string */ 2846 - 2847 - /* if these kcallocs fail not much we 2848 - can do, but better to not fail the 2849 - sesssetup itself */ 2850 - kfree(ses->serverDomain); 2851 - ses->serverDomain = 2852 - kzalloc(2, GFP_KERNEL); 2853 - kfree(ses->serverNOS); 2854 - ses->serverNOS = 2855 - kzalloc(2, GFP_KERNEL); 2856 - } 2857 - } else { /* ASCII */ 2858 - len = strnlen(bcc_ptr, 1024); 2859 - if (((long) bcc_ptr + len) - (long) 2860 - pByteArea(smb_buffer_response) 2861 - <= BCC(smb_buffer_response)) { 2862 - kfree(ses->serverOS); 2863 - ses->serverOS = kzalloc(len + 1, 2864 - GFP_KERNEL); 2865 - if (ses->serverOS == NULL) 2866 - goto sesssetup_nomem; 2867 - strncpy(ses->serverOS, bcc_ptr, len); 2868 - 2869 - bcc_ptr += len; 2870 - /* null terminate the string */ 2871 - bcc_ptr[0] = 0; 2872 - bcc_ptr++; 2873 - 2874 - len = strnlen(bcc_ptr, 1024); 2875 - kfree(ses->serverNOS); 2876 - ses->serverNOS = kzalloc(len + 1, 2877 - GFP_KERNEL); 2878 - if (ses->serverNOS == NULL) 2879 - goto sesssetup_nomem; 2880 - strncpy(ses->serverNOS, bcc_ptr, len); 2881 - bcc_ptr += len; 2882 - bcc_ptr[0] = 0; 2883 - bcc_ptr++; 2884 - 2885 - len = strnlen(bcc_ptr, 1024); 2886 - kfree(ses->serverDomain); 2887 - ses->serverDomain = kzalloc(len + 1, 2888 - GFP_KERNEL); 2889 - if (ses->serverDomain == NULL) 2890 - goto sesssetup_nomem; 2891 - strncpy(ses->serverDomain, bcc_ptr, 2892 - len); 2893 - bcc_ptr += len; 2894 - bcc_ptr[0] = 0; 2895 - bcc_ptr++; 2896 - } else 2897 - cFYI(1, 2898 - ("Variable field of length %d " 2899 - "extends beyond end of smb ", 2900 - len)); 2901 - } 2902 - } else { 2903 - cERROR(1, ("Security Blob Length extends beyond " 2904 - "end of SMB")); 2905 - } 2906 - } else { 2907 - cERROR(1, ("Invalid Word count %d: ", 2908 - smb_buffer_response->WordCount)); 2909 - rc = -EIO; 2910 - } 2911 - sesssetup_nomem: /* do not return an error on nomem for the info strings, 2912 - since that could make reconnection harder, and 2913 - reconnection might be needed to free memory */ 2914 - cifs_buf_release(smb_buffer); 2915 - 2916 - return rc; 2917 - } 2918 - 2919 - static int 2920 - CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, 2921 - struct cifsSesInfo *ses, bool *pNTLMv2_flag, 2922 - const struct nls_table *nls_codepage) 2923 - { 2924 - struct smb_hdr *smb_buffer; 2925 - struct smb_hdr *smb_buffer_response; 2926 - SESSION_SETUP_ANDX *pSMB; 2927 - SESSION_SETUP_ANDX *pSMBr; 2928 - char *bcc_ptr; 2929 - char *domain; 2930 - int rc = 0; 2931 - int remaining_words = 0; 2932 - int bytes_returned = 0; 2933 - int len; 2934 - int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE); 2935 - PNEGOTIATE_MESSAGE SecurityBlob; 2936 - PCHALLENGE_MESSAGE SecurityBlob2; 2937 - __u32 negotiate_flags, capabilities; 2938 - __u16 count; 2939 - 2940 - cFYI(1, ("In NTLMSSP sesssetup (negotiate)")); 2941 - if (ses == NULL) 2942 - return -EINVAL; 2943 - domain = ses->domainName; 2944 - *pNTLMv2_flag = false; 2945 - smb_buffer = cifs_buf_get(); 2946 - if (smb_buffer == NULL) { 2947 - return -ENOMEM; 2948 - } 2949 - smb_buffer_response = smb_buffer; 2950 - pSMB = (SESSION_SETUP_ANDX *) smb_buffer; 2951 - pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; 2952 - 2953 - /* send SMBsessionSetup here */ 2954 - header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2955 - NULL /* no tCon exists yet */ , 12 /* wct */ ); 2956 - 2957 - smb_buffer->Mid = GetNextMid(ses->server); 2958 - pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2959 - pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2960 - 2961 - pSMB->req.AndXCommand = 0xFF; 2962 - pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 2963 - pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 2964 - 2965 - if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 2966 - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 2967 - 2968 - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 2969 - CAP_EXTENDED_SECURITY; 2970 - if (ses->capabilities & CAP_UNICODE) { 2971 - smb_buffer->Flags2 |= SMBFLG2_UNICODE; 2972 - capabilities |= CAP_UNICODE; 2973 - } 2974 - if (ses->capabilities & CAP_STATUS32) { 2975 - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; 2976 - capabilities |= CAP_STATUS32; 2977 - } 2978 - if (ses->capabilities & CAP_DFS) { 2979 - smb_buffer->Flags2 |= SMBFLG2_DFS; 2980 - capabilities |= CAP_DFS; 2981 - } 2982 - pSMB->req.Capabilities = cpu_to_le32(capabilities); 2983 - 2984 - bcc_ptr = (char *) &pSMB->req.SecurityBlob; 2985 - SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr; 2986 - strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); 2987 - SecurityBlob->MessageType = NtLmNegotiate; 2988 - negotiate_flags = 2989 - NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | 2990 - NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 2991 - NTLMSSP_NEGOTIATE_56 | 2992 - /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2993 - if (sign_CIFS_PDUs) 2994 - negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2995 - /* if (ntlmv2_support) 2996 - negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/ 2997 - /* setup pointers to domain name and workstation name */ 2998 - bcc_ptr += SecurityBlobLength; 2999 - 3000 - SecurityBlob->WorkstationName.Buffer = 0; 3001 - SecurityBlob->WorkstationName.Length = 0; 3002 - SecurityBlob->WorkstationName.MaximumLength = 0; 3003 - 3004 - /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent 3005 - along with username on auth request (ie the response to challenge) */ 3006 - SecurityBlob->DomainName.Buffer = 0; 3007 - SecurityBlob->DomainName.Length = 0; 3008 - SecurityBlob->DomainName.MaximumLength = 0; 3009 - if (ses->capabilities & CAP_UNICODE) { 3010 - if ((long) bcc_ptr % 2) { 3011 - *bcc_ptr = 0; 3012 - bcc_ptr++; 3013 - } 3014 - 3015 - bytes_returned = 3016 - cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 3017 - 32, nls_codepage); 3018 - bcc_ptr += 2 * bytes_returned; 3019 - bytes_returned = 3020 - cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, 3021 - nls_codepage); 3022 - bcc_ptr += 2 * bytes_returned; 3023 - bcc_ptr += 2; /* null terminate Linux version */ 3024 - bytes_returned = 3025 - cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 3026 - 64, nls_codepage); 3027 - bcc_ptr += 2 * bytes_returned; 3028 - *(bcc_ptr + 1) = 0; 3029 - *(bcc_ptr + 2) = 0; 3030 - bcc_ptr += 2; /* null terminate network opsys string */ 3031 - *(bcc_ptr + 1) = 0; 3032 - *(bcc_ptr + 2) = 0; 3033 - bcc_ptr += 2; /* null domain */ 3034 - } else { /* ASCII */ 3035 - strcpy(bcc_ptr, "Linux version "); 3036 - bcc_ptr += strlen("Linux version "); 3037 - strcpy(bcc_ptr, utsname()->release); 3038 - bcc_ptr += strlen(utsname()->release) + 1; 3039 - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); 3040 - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; 3041 - bcc_ptr++; /* empty domain field */ 3042 - *bcc_ptr = 0; 3043 - } 3044 - SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); 3045 - pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); 3046 - count = (long) bcc_ptr - (long) pByteArea(smb_buffer); 3047 - smb_buffer->smb_buf_length += count; 3048 - pSMB->req.ByteCount = cpu_to_le16(count); 3049 - 3050 - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, 3051 - &bytes_returned, CIFS_LONG_OP); 3052 - 3053 - if (smb_buffer_response->Status.CifsError == 3054 - cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) 3055 - rc = 0; 3056 - 3057 - if (rc) { 3058 - /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ 3059 - } else if ((smb_buffer_response->WordCount == 3) 3060 - || (smb_buffer_response->WordCount == 4)) { 3061 - __u16 action = le16_to_cpu(pSMBr->resp.Action); 3062 - __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 3063 - 3064 - if (action & GUEST_LOGIN) 3065 - cFYI(1, ("Guest login")); 3066 - /* Do we want to set anything in SesInfo struct when guest login? */ 3067 - 3068 - bcc_ptr = pByteArea(smb_buffer_response); 3069 - /* response can have either 3 or 4 word count - Samba sends 3 */ 3070 - 3071 - SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr; 3072 - if (SecurityBlob2->MessageType != NtLmChallenge) { 3073 - cFYI(1, ("Unexpected NTLMSSP message type received %d", 3074 - SecurityBlob2->MessageType)); 3075 - } else if (ses) { 3076 - ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ 3077 - cFYI(1, ("UID = %d", ses->Suid)); 3078 - if ((pSMBr->resp.hdr.WordCount == 3) 3079 - || ((pSMBr->resp.hdr.WordCount == 4) 3080 - && (blob_len < 3081 - pSMBr->resp.ByteCount))) { 3082 - 3083 - if (pSMBr->resp.hdr.WordCount == 4) { 3084 - bcc_ptr += blob_len; 3085 - cFYI(1, ("Security Blob Length %d", 3086 - blob_len)); 3087 - } 3088 - 3089 - cFYI(1, ("NTLMSSP Challenge rcvd")); 3090 - 3091 - memcpy(ses->server->cryptKey, 3092 - SecurityBlob2->Challenge, 3093 - CIFS_CRYPTO_KEY_SIZE); 3094 - if (SecurityBlob2->NegotiateFlags & 3095 - cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) 3096 - *pNTLMv2_flag = true; 3097 - 3098 - if ((SecurityBlob2->NegotiateFlags & 3099 - cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) 3100 - || (sign_CIFS_PDUs > 1)) 3101 - ses->server->secMode |= 3102 - SECMODE_SIGN_REQUIRED; 3103 - if ((SecurityBlob2->NegotiateFlags & 3104 - cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs)) 3105 - ses->server->secMode |= 3106 - SECMODE_SIGN_ENABLED; 3107 - 3108 - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 3109 - if ((long) (bcc_ptr) % 2) { 3110 - remaining_words = 3111 - (BCC(smb_buffer_response) 3112 - - 1) / 2; 3113 - /* Must word align unicode strings */ 3114 - bcc_ptr++; 3115 - } else { 3116 - remaining_words = 3117 - BCC 3118 - (smb_buffer_response) / 2; 3119 - } 3120 - len = 3121 - UniStrnlen((wchar_t *) bcc_ptr, 3122 - remaining_words - 1); 3123 - /* We look for obvious messed up bcc or strings in response so we do not go off 3124 - the end since (at least) WIN2K and Windows XP have a major bug in not null 3125 - terminating last Unicode string in response */ 3126 - kfree(ses->serverOS); 3127 - ses->serverOS = 3128 - kzalloc(2 * (len + 1), GFP_KERNEL); 3129 - cifs_strfromUCS_le(ses->serverOS, 3130 - (__le16 *) 3131 - bcc_ptr, len, 3132 - nls_codepage); 3133 - bcc_ptr += 2 * (len + 1); 3134 - remaining_words -= len + 1; 3135 - ses->serverOS[2 * len] = 0; 3136 - ses->serverOS[1 + (2 * len)] = 0; 3137 - if (remaining_words > 0) { 3138 - len = UniStrnlen((wchar_t *) 3139 - bcc_ptr, 3140 - remaining_words 3141 - - 1); 3142 - kfree(ses->serverNOS); 3143 - ses->serverNOS = 3144 - kzalloc(2 * (len + 1), 3145 - GFP_KERNEL); 3146 - cifs_strfromUCS_le(ses-> 3147 - serverNOS, 3148 - (__le16 *) 3149 - bcc_ptr, 3150 - len, 3151 - nls_codepage); 3152 - bcc_ptr += 2 * (len + 1); 3153 - ses->serverNOS[2 * len] = 0; 3154 - ses->serverNOS[1 + 3155 - (2 * len)] = 0; 3156 - remaining_words -= len + 1; 3157 - if (remaining_words > 0) { 3158 - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 3159 - /* last string not always null terminated 3160 - (for e.g. for Windows XP & 2000) */ 3161 - kfree(ses->serverDomain); 3162 - ses->serverDomain = 3163 - kzalloc(2 * 3164 - (len + 3165 - 1), 3166 - GFP_KERNEL); 3167 - cifs_strfromUCS_le 3168 - (ses->serverDomain, 3169 - (__le16 *)bcc_ptr, 3170 - len, nls_codepage); 3171 - bcc_ptr += 3172 - 2 * (len + 1); 3173 - ses->serverDomain[2*len] 3174 - = 0; 3175 - ses->serverDomain 3176 - [1 + (2 * len)] 3177 - = 0; 3178 - } /* else no more room so create dummy domain string */ 3179 - else { 3180 - kfree(ses->serverDomain); 3181 - ses->serverDomain = 3182 - kzalloc(2, 3183 - GFP_KERNEL); 3184 - } 3185 - } else { /* no room so create dummy domain and NOS string */ 3186 - kfree(ses->serverDomain); 3187 - ses->serverDomain = 3188 - kzalloc(2, GFP_KERNEL); 3189 - kfree(ses->serverNOS); 3190 - ses->serverNOS = 3191 - kzalloc(2, GFP_KERNEL); 3192 - } 3193 - } else { /* ASCII */ 3194 - len = strnlen(bcc_ptr, 1024); 3195 - if (((long) bcc_ptr + len) - (long) 3196 - pByteArea(smb_buffer_response) 3197 - <= BCC(smb_buffer_response)) { 3198 - kfree(ses->serverOS); 3199 - ses->serverOS = 3200 - kzalloc(len + 1, 3201 - GFP_KERNEL); 3202 - strncpy(ses->serverOS, 3203 - bcc_ptr, len); 3204 - 3205 - bcc_ptr += len; 3206 - bcc_ptr[0] = 0; /* null terminate string */ 3207 - bcc_ptr++; 3208 - 3209 - len = strnlen(bcc_ptr, 1024); 3210 - kfree(ses->serverNOS); 3211 - ses->serverNOS = 3212 - kzalloc(len + 1, 3213 - GFP_KERNEL); 3214 - strncpy(ses->serverNOS, bcc_ptr, len); 3215 - bcc_ptr += len; 3216 - bcc_ptr[0] = 0; 3217 - bcc_ptr++; 3218 - 3219 - len = strnlen(bcc_ptr, 1024); 3220 - kfree(ses->serverDomain); 3221 - ses->serverDomain = 3222 - kzalloc(len + 1, 3223 - GFP_KERNEL); 3224 - strncpy(ses->serverDomain, 3225 - bcc_ptr, len); 3226 - bcc_ptr += len; 3227 - bcc_ptr[0] = 0; 3228 - bcc_ptr++; 3229 - } else 3230 - cFYI(1, 3231 - ("field of length %d " 3232 - "extends beyond end of smb", 3233 - len)); 3234 - } 3235 - } else { 3236 - cERROR(1, ("Security Blob Length extends beyond" 3237 - " end of SMB")); 3238 - } 3239 - } else { 3240 - cERROR(1, ("No session structure passed in.")); 3241 - } 3242 - } else { 3243 - cERROR(1, ("Invalid Word count %d:", 3244 - smb_buffer_response->WordCount)); 3245 - rc = -EIO; 3246 - } 3247 - 3248 - cifs_buf_release(smb_buffer); 3249 - 3250 - return rc; 3251 - } 3252 - static int 3253 - CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, 3254 - char *ntlm_session_key, bool ntlmv2_flag, 3255 - const struct nls_table *nls_codepage) 3256 - { 3257 - struct smb_hdr *smb_buffer; 3258 - struct smb_hdr *smb_buffer_response; 3259 - SESSION_SETUP_ANDX *pSMB; 3260 - SESSION_SETUP_ANDX *pSMBr; 3261 - char *bcc_ptr; 3262 - char *user; 3263 - char *domain; 3264 - int rc = 0; 3265 - int remaining_words = 0; 3266 - int bytes_returned = 0; 3267 - int len; 3268 - int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE); 3269 - PAUTHENTICATE_MESSAGE SecurityBlob; 3270 - __u32 negotiate_flags, capabilities; 3271 - __u16 count; 3272 - 3273 - cFYI(1, ("In NTLMSSPSessSetup (Authenticate)")); 3274 - if (ses == NULL) 3275 - return -EINVAL; 3276 - user = ses->userName; 3277 - domain = ses->domainName; 3278 - smb_buffer = cifs_buf_get(); 3279 - if (smb_buffer == NULL) { 3280 - return -ENOMEM; 3281 - } 3282 - smb_buffer_response = smb_buffer; 3283 - pSMB = (SESSION_SETUP_ANDX *)smb_buffer; 3284 - pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response; 3285 - 3286 - /* send SMBsessionSetup here */ 3287 - header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 3288 - NULL /* no tCon exists yet */ , 12 /* wct */ ); 3289 - 3290 - smb_buffer->Mid = GetNextMid(ses->server); 3291 - pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 3292 - pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 3293 - pSMB->req.AndXCommand = 0xFF; 3294 - pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 3295 - pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 3296 - 3297 - pSMB->req.hdr.Uid = ses->Suid; 3298 - 3299 - if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 3300 - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 3301 - 3302 - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 3303 - CAP_EXTENDED_SECURITY; 3304 - if (ses->capabilities & CAP_UNICODE) { 3305 - smb_buffer->Flags2 |= SMBFLG2_UNICODE; 3306 - capabilities |= CAP_UNICODE; 3307 - } 3308 - if (ses->capabilities & CAP_STATUS32) { 3309 - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; 3310 - capabilities |= CAP_STATUS32; 3311 - } 3312 - if (ses->capabilities & CAP_DFS) { 3313 - smb_buffer->Flags2 |= SMBFLG2_DFS; 3314 - capabilities |= CAP_DFS; 3315 - } 3316 - pSMB->req.Capabilities = cpu_to_le32(capabilities); 3317 - 3318 - bcc_ptr = (char *)&pSMB->req.SecurityBlob; 3319 - SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr; 3320 - strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); 3321 - SecurityBlob->MessageType = NtLmAuthenticate; 3322 - bcc_ptr += SecurityBlobLength; 3323 - negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | 3324 - NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | 3325 - 0x80000000 | NTLMSSP_NEGOTIATE_128; 3326 - if (sign_CIFS_PDUs) 3327 - negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; 3328 - if (ntlmv2_flag) 3329 - negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; 3330 - 3331 - /* setup pointers to domain name and workstation name */ 3332 - 3333 - SecurityBlob->WorkstationName.Buffer = 0; 3334 - SecurityBlob->WorkstationName.Length = 0; 3335 - SecurityBlob->WorkstationName.MaximumLength = 0; 3336 - SecurityBlob->SessionKey.Length = 0; 3337 - SecurityBlob->SessionKey.MaximumLength = 0; 3338 - SecurityBlob->SessionKey.Buffer = 0; 3339 - 3340 - SecurityBlob->LmChallengeResponse.Length = 0; 3341 - SecurityBlob->LmChallengeResponse.MaximumLength = 0; 3342 - SecurityBlob->LmChallengeResponse.Buffer = 0; 3343 - 3344 - SecurityBlob->NtChallengeResponse.Length = 3345 - cpu_to_le16(CIFS_SESS_KEY_SIZE); 3346 - SecurityBlob->NtChallengeResponse.MaximumLength = 3347 - cpu_to_le16(CIFS_SESS_KEY_SIZE); 3348 - memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE); 3349 - SecurityBlob->NtChallengeResponse.Buffer = 3350 - cpu_to_le32(SecurityBlobLength); 3351 - SecurityBlobLength += CIFS_SESS_KEY_SIZE; 3352 - bcc_ptr += CIFS_SESS_KEY_SIZE; 3353 - 3354 - if (ses->capabilities & CAP_UNICODE) { 3355 - if (domain == NULL) { 3356 - SecurityBlob->DomainName.Buffer = 0; 3357 - SecurityBlob->DomainName.Length = 0; 3358 - SecurityBlob->DomainName.MaximumLength = 0; 3359 - } else { 3360 - __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, 3361 - nls_codepage); 3362 - ln *= 2; 3363 - SecurityBlob->DomainName.MaximumLength = 3364 - cpu_to_le16(ln); 3365 - SecurityBlob->DomainName.Buffer = 3366 - cpu_to_le32(SecurityBlobLength); 3367 - bcc_ptr += ln; 3368 - SecurityBlobLength += ln; 3369 - SecurityBlob->DomainName.Length = cpu_to_le16(ln); 3370 - } 3371 - if (user == NULL) { 3372 - SecurityBlob->UserName.Buffer = 0; 3373 - SecurityBlob->UserName.Length = 0; 3374 - SecurityBlob->UserName.MaximumLength = 0; 3375 - } else { 3376 - __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, 3377 - nls_codepage); 3378 - ln *= 2; 3379 - SecurityBlob->UserName.MaximumLength = 3380 - cpu_to_le16(ln); 3381 - SecurityBlob->UserName.Buffer = 3382 - cpu_to_le32(SecurityBlobLength); 3383 - bcc_ptr += ln; 3384 - SecurityBlobLength += ln; 3385 - SecurityBlob->UserName.Length = cpu_to_le16(ln); 3386 - } 3387 - 3388 - /* SecurityBlob->WorkstationName.Length = 3389 - cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage); 3390 - SecurityBlob->WorkstationName.Length *= 2; 3391 - SecurityBlob->WorkstationName.MaximumLength = 3392 - cpu_to_le16(SecurityBlob->WorkstationName.Length); 3393 - SecurityBlob->WorkstationName.Buffer = 3394 - cpu_to_le32(SecurityBlobLength); 3395 - bcc_ptr += SecurityBlob->WorkstationName.Length; 3396 - SecurityBlobLength += SecurityBlob->WorkstationName.Length; 3397 - SecurityBlob->WorkstationName.Length = 3398 - cpu_to_le16(SecurityBlob->WorkstationName.Length); */ 3399 - 3400 - if ((long) bcc_ptr % 2) { 3401 - *bcc_ptr = 0; 3402 - bcc_ptr++; 3403 - } 3404 - bytes_returned = 3405 - cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 3406 - 32, nls_codepage); 3407 - bcc_ptr += 2 * bytes_returned; 3408 - bytes_returned = 3409 - cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, 3410 - nls_codepage); 3411 - bcc_ptr += 2 * bytes_returned; 3412 - bcc_ptr += 2; /* null term version string */ 3413 - bytes_returned = 3414 - cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 3415 - 64, nls_codepage); 3416 - bcc_ptr += 2 * bytes_returned; 3417 - *(bcc_ptr + 1) = 0; 3418 - *(bcc_ptr + 2) = 0; 3419 - bcc_ptr += 2; /* null terminate network opsys string */ 3420 - *(bcc_ptr + 1) = 0; 3421 - *(bcc_ptr + 2) = 0; 3422 - bcc_ptr += 2; /* null domain */ 3423 - } else { /* ASCII */ 3424 - if (domain == NULL) { 3425 - SecurityBlob->DomainName.Buffer = 0; 3426 - SecurityBlob->DomainName.Length = 0; 3427 - SecurityBlob->DomainName.MaximumLength = 0; 3428 - } else { 3429 - __u16 ln; 3430 - negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; 3431 - strncpy(bcc_ptr, domain, 63); 3432 - ln = strnlen(domain, 64); 3433 - SecurityBlob->DomainName.MaximumLength = 3434 - cpu_to_le16(ln); 3435 - SecurityBlob->DomainName.Buffer = 3436 - cpu_to_le32(SecurityBlobLength); 3437 - bcc_ptr += ln; 3438 - SecurityBlobLength += ln; 3439 - SecurityBlob->DomainName.Length = cpu_to_le16(ln); 3440 - } 3441 - if (user == NULL) { 3442 - SecurityBlob->UserName.Buffer = 0; 3443 - SecurityBlob->UserName.Length = 0; 3444 - SecurityBlob->UserName.MaximumLength = 0; 3445 - } else { 3446 - __u16 ln; 3447 - strncpy(bcc_ptr, user, 63); 3448 - ln = strnlen(user, 64); 3449 - SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln); 3450 - SecurityBlob->UserName.Buffer = 3451 - cpu_to_le32(SecurityBlobLength); 3452 - bcc_ptr += ln; 3453 - SecurityBlobLength += ln; 3454 - SecurityBlob->UserName.Length = cpu_to_le16(ln); 3455 - } 3456 - /* BB fill in our workstation name if known BB */ 3457 - 3458 - strcpy(bcc_ptr, "Linux version "); 3459 - bcc_ptr += strlen("Linux version "); 3460 - strcpy(bcc_ptr, utsname()->release); 3461 - bcc_ptr += strlen(utsname()->release) + 1; 3462 - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); 3463 - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; 3464 - bcc_ptr++; /* null domain */ 3465 - *bcc_ptr = 0; 3466 - } 3467 - SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); 3468 - pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); 3469 - count = (long) bcc_ptr - (long) pByteArea(smb_buffer); 3470 - smb_buffer->smb_buf_length += count; 3471 - pSMB->req.ByteCount = cpu_to_le16(count); 3472 - 3473 - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, 3474 - &bytes_returned, CIFS_LONG_OP); 3475 - if (rc) { 3476 - /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ 3477 - } else if ((smb_buffer_response->WordCount == 3) || 3478 - (smb_buffer_response->WordCount == 4)) { 3479 - __u16 action = le16_to_cpu(pSMBr->resp.Action); 3480 - __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 3481 - if (action & GUEST_LOGIN) 3482 - cFYI(1, ("Guest login")); /* BB Should we set anything 3483 - in SesInfo struct ? */ 3484 - /* if (SecurityBlob2->MessageType != NtLm??) { 3485 - cFYI("Unexpected message type on auth response is %d")); 3486 - } */ 3487 - 3488 - if (ses) { 3489 - cFYI(1, 3490 - ("Check challenge UID %d vs auth response UID %d", 3491 - ses->Suid, smb_buffer_response->Uid)); 3492 - /* UID left in wire format */ 3493 - ses->Suid = smb_buffer_response->Uid; 3494 - bcc_ptr = pByteArea(smb_buffer_response); 3495 - /* response can have either 3 or 4 word count - Samba sends 3 */ 3496 - if ((pSMBr->resp.hdr.WordCount == 3) 3497 - || ((pSMBr->resp.hdr.WordCount == 4) 3498 - && (blob_len < 3499 - pSMBr->resp.ByteCount))) { 3500 - if (pSMBr->resp.hdr.WordCount == 4) { 3501 - bcc_ptr += 3502 - blob_len; 3503 - cFYI(1, 3504 - ("Security Blob Length %d ", 3505 - blob_len)); 3506 - } 3507 - 3508 - cFYI(1, 3509 - ("NTLMSSP response to Authenticate ")); 3510 - 3511 - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 3512 - if ((long) (bcc_ptr) % 2) { 3513 - remaining_words = 3514 - (BCC(smb_buffer_response) 3515 - - 1) / 2; 3516 - bcc_ptr++; /* Unicode strings must be word aligned */ 3517 - } else { 3518 - remaining_words = BCC(smb_buffer_response) / 2; 3519 - } 3520 - len = UniStrnlen((wchar_t *) bcc_ptr, 3521 - remaining_words - 1); 3522 - /* We look for obvious messed up bcc or strings in response so we do not go off 3523 - the end since (at least) WIN2K and Windows XP have a major bug in not null 3524 - terminating last Unicode string in response */ 3525 - kfree(ses->serverOS); 3526 - ses->serverOS = 3527 - kzalloc(2 * (len + 1), GFP_KERNEL); 3528 - cifs_strfromUCS_le(ses->serverOS, 3529 - (__le16 *) 3530 - bcc_ptr, len, 3531 - nls_codepage); 3532 - bcc_ptr += 2 * (len + 1); 3533 - remaining_words -= len + 1; 3534 - ses->serverOS[2 * len] = 0; 3535 - ses->serverOS[1 + (2 * len)] = 0; 3536 - if (remaining_words > 0) { 3537 - len = UniStrnlen((wchar_t *) 3538 - bcc_ptr, 3539 - remaining_words 3540 - - 1); 3541 - kfree(ses->serverNOS); 3542 - ses->serverNOS = 3543 - kzalloc(2 * (len + 1), 3544 - GFP_KERNEL); 3545 - cifs_strfromUCS_le(ses-> 3546 - serverNOS, 3547 - (__le16 *) 3548 - bcc_ptr, 3549 - len, 3550 - nls_codepage); 3551 - bcc_ptr += 2 * (len + 1); 3552 - ses->serverNOS[2 * len] = 0; 3553 - ses->serverNOS[1+(2*len)] = 0; 3554 - remaining_words -= len + 1; 3555 - if (remaining_words > 0) { 3556 - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 3557 - /* last string not always null terminated (e.g. for Windows XP & 2000) */ 3558 - kfree(ses->serverDomain); 3559 - ses->serverDomain = 3560 - kzalloc(2 * 3561 - (len + 3562 - 1), 3563 - GFP_KERNEL); 3564 - cifs_strfromUCS_le 3565 - (ses-> 3566 - serverDomain, 3567 - (__le16 *) 3568 - bcc_ptr, len, 3569 - nls_codepage); 3570 - bcc_ptr += 3571 - 2 * (len + 1); 3572 - ses-> 3573 - serverDomain[2 3574 - * len] 3575 - = 0; 3576 - ses-> 3577 - serverDomain[1 3578 - + 3579 - (2 3580 - * 3581 - len)] 3582 - = 0; 3583 - } /* else no more room so create dummy domain string */ 3584 - else { 3585 - kfree(ses->serverDomain); 3586 - ses->serverDomain = kzalloc(2,GFP_KERNEL); 3587 - } 3588 - } else { /* no room so create dummy domain and NOS string */ 3589 - kfree(ses->serverDomain); 3590 - ses->serverDomain = kzalloc(2, GFP_KERNEL); 3591 - kfree(ses->serverNOS); 3592 - ses->serverNOS = kzalloc(2, GFP_KERNEL); 3593 - } 3594 - } else { /* ASCII */ 3595 - len = strnlen(bcc_ptr, 1024); 3596 - if (((long) bcc_ptr + len) - 3597 - (long) pByteArea(smb_buffer_response) 3598 - <= BCC(smb_buffer_response)) { 3599 - kfree(ses->serverOS); 3600 - ses->serverOS = kzalloc(len + 1, GFP_KERNEL); 3601 - strncpy(ses->serverOS,bcc_ptr, len); 3602 - 3603 - bcc_ptr += len; 3604 - bcc_ptr[0] = 0; /* null terminate the string */ 3605 - bcc_ptr++; 3606 - 3607 - len = strnlen(bcc_ptr, 1024); 3608 - kfree(ses->serverNOS); 3609 - ses->serverNOS = kzalloc(len+1, 3610 - GFP_KERNEL); 3611 - strncpy(ses->serverNOS, 3612 - bcc_ptr, len); 3613 - bcc_ptr += len; 3614 - bcc_ptr[0] = 0; 3615 - bcc_ptr++; 3616 - 3617 - len = strnlen(bcc_ptr, 1024); 3618 - kfree(ses->serverDomain); 3619 - ses->serverDomain = 3620 - kzalloc(len+1, 3621 - GFP_KERNEL); 3622 - strncpy(ses->serverDomain, 3623 - bcc_ptr, len); 3624 - bcc_ptr += len; 3625 - bcc_ptr[0] = 0; 3626 - bcc_ptr++; 3627 - } else 3628 - cFYI(1, ("field of length %d " 3629 - "extends beyond end of smb ", 3630 - len)); 3631 - } 3632 - } else { 3633 - cERROR(1, ("Security Blob extends beyond end " 3634 - "of SMB")); 3635 - } 3636 - } else { 3637 - cERROR(1, ("No session structure passed in.")); 3638 - } 3639 - } else { 3640 - cERROR(1, ("Invalid Word count %d: ", 3641 - smb_buffer_response->WordCount)); 3642 - rc = -EIO; 3643 - } 3644 - 3645 - cifs_buf_release(smb_buffer); 3646 - 3647 - return rc; 3648 - } 3649 - 3650 2595 int 3651 2596 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, 3652 2597 const char *tree, struct cifsTconInfo *tcon, ··· 2623 3638 TCONX_RSP *pSMBr; 2624 3639 unsigned char *bcc_ptr; 2625 3640 int rc = 0; 2626 - int length; 3641 + int length, bytes_left; 2627 3642 __u16 count; 2628 3643 2629 3644 if (ses == NULL) ··· 2711 3726 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 2712 3727 CIFS_STD_OP); 2713 3728 2714 - /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ 2715 3729 /* above now done in SendReceive */ 2716 3730 if ((rc == 0) && (tcon != NULL)) { 3731 + bool is_unicode; 3732 + 2717 3733 tcon->tidStatus = CifsGood; 2718 3734 tcon->need_reconnect = false; 2719 3735 tcon->tid = smb_buffer_response->Tid; 2720 3736 bcc_ptr = pByteArea(smb_buffer_response); 2721 - length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 3737 + bytes_left = BCC(smb_buffer_response); 3738 + length = strnlen(bcc_ptr, bytes_left - 2); 3739 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) 3740 + is_unicode = true; 3741 + else 3742 + is_unicode = false; 3743 + 3744 + 2722 3745 /* skip service field (NB: this field is always ASCII) */ 2723 3746 if (length == 3) { 2724 3747 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && ··· 2741 3748 } 2742 3749 } 2743 3750 bcc_ptr += length + 1; 3751 + bytes_left -= (length + 1); 2744 3752 strncpy(tcon->treeName, tree, MAX_TREE_SIZE); 2745 - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 2746 - length = UniStrnlen((wchar_t *) bcc_ptr, 512); 2747 - if ((bcc_ptr + (2 * length)) - 2748 - pByteArea(smb_buffer_response) <= 2749 - BCC(smb_buffer_response)) { 2750 - kfree(tcon->nativeFileSystem); 2751 - tcon->nativeFileSystem = 2752 - kzalloc((4 * length) + 2, GFP_KERNEL); 2753 - if (tcon->nativeFileSystem) { 2754 - cifs_strfromUCS_le( 2755 - tcon->nativeFileSystem, 2756 - (__le16 *) bcc_ptr, 2757 - length, nls_codepage); 2758 - cFYI(1, ("nativeFileSystem=%s", 2759 - tcon->nativeFileSystem)); 2760 - } 2761 - } 2762 - /* else do not bother copying these information fields*/ 2763 - } else { 2764 - length = strnlen(bcc_ptr, 1024); 2765 - if ((bcc_ptr + length) - 2766 - pByteArea(smb_buffer_response) <= 2767 - BCC(smb_buffer_response)) { 2768 - kfree(tcon->nativeFileSystem); 2769 - tcon->nativeFileSystem = 2770 - kzalloc(length + 1, GFP_KERNEL); 2771 - if (tcon->nativeFileSystem) 2772 - strncpy(tcon->nativeFileSystem, bcc_ptr, 2773 - length); 2774 - } 2775 - /* else do not bother copying these information fields*/ 2776 - } 3753 + 3754 + /* mostly informational -- no need to fail on error here */ 3755 + tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, 3756 + bytes_left, is_unicode, 3757 + nls_codepage); 3758 + 3759 + cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem)); 3760 + 2777 3761 if ((smb_buffer_response->WordCount == 3) || 2778 3762 (smb_buffer_response->WordCount == 7)) 2779 3763 /* field is in same location */ ··· 2789 3819 struct nls_table *nls_info) 2790 3820 { 2791 3821 int rc = 0; 2792 - char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 2793 - bool ntlmv2_flag = false; 2794 3822 int first_time = 0; 2795 3823 struct TCP_Server_Info *server = pSesInfo->server; 2796 3824 ··· 2820 3852 pSesInfo->capabilities = server->capabilities; 2821 3853 if (linuxExtEnabled == 0) 2822 3854 pSesInfo->capabilities &= (~CAP_UNIX); 2823 - /* pSesInfo->sequence_number = 0;*/ 3855 + 2824 3856 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 2825 3857 server->secMode, server->capabilities, server->timeAdj)); 2826 3858 2827 - if (experimEnabled < 2) 2828 - rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); 2829 - else if (extended_security 2830 - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 2831 - && (server->secType == NTLMSSP)) { 2832 - rc = -EOPNOTSUPP; 2833 - } else if (extended_security 2834 - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 2835 - && (server->secType == RawNTLMSSP)) { 2836 - cFYI(1, ("NTLMSSP sesssetup")); 2837 - rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, 2838 - nls_info); 2839 - if (!rc) { 2840 - if (ntlmv2_flag) { 2841 - char *v2_response; 2842 - cFYI(1, ("more secure NTLM ver2 hash")); 2843 - if (CalcNTLMv2_partial_mac_key(pSesInfo, 2844 - nls_info)) { 2845 - rc = -ENOMEM; 2846 - goto ss_err_exit; 2847 - } else 2848 - v2_response = kmalloc(16 + 64 /* blob*/, 2849 - GFP_KERNEL); 2850 - if (v2_response) { 2851 - CalcNTLMv2_response(pSesInfo, 2852 - v2_response); 2853 - /* if (first_time) 2854 - cifs_calculate_ntlmv2_mac_key */ 2855 - kfree(v2_response); 2856 - /* BB Put dummy sig in SessSetup PDU? */ 2857 - } else { 2858 - rc = -ENOMEM; 2859 - goto ss_err_exit; 2860 - } 2861 - 2862 - } else { 2863 - SMBNTencrypt(pSesInfo->password, 2864 - server->cryptKey, 2865 - ntlm_session_key); 2866 - 2867 - if (first_time) 2868 - cifs_calculate_mac_key( 2869 - &server->mac_signing_key, 2870 - ntlm_session_key, 2871 - pSesInfo->password); 2872 - } 2873 - /* for better security the weaker lanman hash not sent 2874 - in AuthSessSetup so we no longer calculate it */ 2875 - 2876 - rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo, 2877 - ntlm_session_key, 2878 - ntlmv2_flag, 2879 - nls_info); 2880 - } 2881 - } else { /* old style NTLM 0.12 session setup */ 2882 - SMBNTencrypt(pSesInfo->password, server->cryptKey, 2883 - ntlm_session_key); 2884 - 2885 - if (first_time) 2886 - cifs_calculate_mac_key(&server->mac_signing_key, 2887 - ntlm_session_key, 2888 - pSesInfo->password); 2889 - 2890 - rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); 2891 - } 3859 + rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); 2892 3860 if (rc) { 2893 3861 cERROR(1, ("Send error in SessSetup = %d", rc)); 2894 3862 } else { 2895 3863 cFYI(1, ("CIFS Session Established successfully")); 2896 - spin_lock(&GlobalMid_Lock); 2897 - pSesInfo->status = CifsGood; 2898 - pSesInfo->need_reconnect = false; 2899 - spin_unlock(&GlobalMid_Lock); 3864 + spin_lock(&GlobalMid_Lock); 3865 + pSesInfo->status = CifsGood; 3866 + pSesInfo->need_reconnect = false; 3867 + spin_unlock(&GlobalMid_Lock); 2900 3868 } 2901 3869 2902 3870 ss_err_exit:
+9 -6
fs/cifs/dir.c
··· 281 281 int create_options = CREATE_NOT_DIR; 282 282 int oplock = 0; 283 283 int oflags; 284 + bool posix_create = false; 284 285 /* 285 286 * BB below access is probably too much for mknod to request 286 287 * but we have to do query and setpathinfo so requesting ··· 329 328 negotation. EREMOTE indicates DFS junction, which is not 330 329 handled in posix open */ 331 330 332 - if ((rc == 0) && (newinode == NULL)) 333 - goto cifs_create_get_file_info; /* query inode info */ 334 - else if (rc == 0) /* success, no need to query */ 335 - goto cifs_create_set_dentry; 336 - else if ((rc != -EIO) && (rc != -EREMOTE) && 331 + if (rc == 0) { 332 + posix_create = true; 333 + if (newinode == NULL) /* query inode info */ 334 + goto cifs_create_get_file_info; 335 + else /* success, no need to query */ 336 + goto cifs_create_set_dentry; 337 + } else if ((rc != -EIO) && (rc != -EREMOTE) && 337 338 (rc != -EOPNOTSUPP)) /* path not found or net err */ 338 339 goto cifs_create_out; 339 340 /* else fallthrough to retry, using older open call, this is ··· 467 464 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { 468 465 /* mknod case - do not leave file open */ 469 466 CIFSSMBClose(xid, tcon, fileHandle); 470 - } else if (newinode) { 467 + } else if (!(posix_create) && (newinode)) { 471 468 cifs_fill_fileinfo(newinode, fileHandle, 472 469 cifs_sb->tcon, write_only); 473 470 }
-14
fs/cifs/file.c
··· 129 129 struct file *file, struct cifsInodeInfo *pCifsInode, 130 130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) 131 131 { 132 - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 133 - /* struct timespec temp; */ /* BB REMOVEME BB */ 134 132 135 133 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 136 134 if (file->private_data == NULL) 137 135 return -ENOMEM; 138 136 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 139 137 write_lock(&GlobalSMBSeslock); 140 - list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); 141 138 142 139 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 143 140 if (pCifsInode == NULL) { 144 141 write_unlock(&GlobalSMBSeslock); 145 142 return -EINVAL; 146 - } 147 - 148 - /* want handles we can use to read with first 149 - in the list so we do not have to walk the 150 - list to search for one in write_begin */ 151 - if ((file->f_flags & O_ACCMODE) == O_WRONLY) { 152 - list_add_tail(&pCifsFile->flist, 153 - &pCifsInode->openFileList); 154 - } else { 155 - list_add(&pCifsFile->flist, 156 - &pCifsInode->openFileList); 157 143 } 158 144 159 145 if (pCifsInode->clientCanCacheRead) {
+15 -6
fs/cifs/inode.c
··· 962 962 goto out_close; 963 963 } 964 964 965 + 966 + /* 967 + * If dentry->d_inode is null (usually meaning the cached dentry 968 + * is a negative dentry) then we would attempt a standard SMB delete, but 969 + * if that fails we can not attempt the fall back mechanisms on EACESS 970 + * but will return the EACESS to the caller. Note that the VFS does not call 971 + * unlink on negative dentries currently. 972 + */ 965 973 int cifs_unlink(struct inode *dir, struct dentry *dentry) 966 974 { 967 975 int rc = 0; 968 976 int xid; 969 977 char *full_path = NULL; 970 978 struct inode *inode = dentry->d_inode; 971 - struct cifsInodeInfo *cifsInode = CIFS_I(inode); 979 + struct cifsInodeInfo *cifs_inode; 972 980 struct super_block *sb = dir->i_sb; 973 981 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 974 982 struct cifsTconInfo *tcon = cifs_sb->tcon; ··· 1020 1012 rc = cifs_rename_pending_delete(full_path, dentry, xid); 1021 1013 if (rc == 0) 1022 1014 drop_nlink(inode); 1023 - } else if (rc == -EACCES && dosattr == 0) { 1015 + } else if ((rc == -EACCES) && (dosattr == 0) && inode) { 1024 1016 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); 1025 1017 if (attrs == NULL) { 1026 1018 rc = -ENOMEM; ··· 1028 1020 } 1029 1021 1030 1022 /* try to reset dos attributes */ 1031 - origattr = cifsInode->cifsAttrs; 1023 + cifs_inode = CIFS_I(inode); 1024 + origattr = cifs_inode->cifsAttrs; 1032 1025 if (origattr == 0) 1033 1026 origattr |= ATTR_NORMAL; 1034 1027 dosattr = origattr & ~ATTR_READONLY; ··· 1050 1041 1051 1042 out_reval: 1052 1043 if (inode) { 1053 - cifsInode = CIFS_I(inode); 1054 - cifsInode->time = 0; /* will force revalidate to get info 1044 + cifs_inode = CIFS_I(inode); 1045 + cifs_inode->time = 0; /* will force revalidate to get info 1055 1046 when needed */ 1056 1047 inode->i_ctime = current_fs_time(sb); 1057 1048 } 1058 1049 dir->i_ctime = dir->i_mtime = current_fs_time(sb); 1059 - cifsInode = CIFS_I(dir); 1050 + cifs_inode = CIFS_I(dir); 1060 1051 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ 1061 1052 1062 1053 kfree(full_path);
+5 -109
fs/cifs/link.c
··· 119 119 full_path = build_path_from_dentry(direntry); 120 120 121 121 if (!full_path) 122 - goto out_no_free; 122 + goto out; 123 123 124 124 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); 125 125 cifs_sb = CIFS_SB(inode->i_sb); 126 126 pTcon = cifs_sb->tcon; 127 - target_path = kmalloc(PATH_MAX, GFP_KERNEL); 128 - if (!target_path) { 129 - target_path = ERR_PTR(-ENOMEM); 130 - goto out; 131 - } 132 127 133 128 /* We could change this to: 134 129 if (pTcon->unix_ext) ··· 133 138 134 139 if (pTcon->ses->capabilities & CAP_UNIX) 135 140 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, 136 - target_path, 137 - PATH_MAX-1, 141 + &target_path, 138 142 cifs_sb->local_nls); 139 143 else { 140 144 /* BB add read reparse point symlink code here */ ··· 142 148 /* BB Add MAC style xsymlink check here if enabled */ 143 149 } 144 150 145 - if (rc == 0) { 146 - 147 - /* BB Add special case check for Samba DFS symlinks */ 148 - 149 - target_path[PATH_MAX-1] = 0; 150 - } else { 151 + if (rc != 0) { 151 152 kfree(target_path); 152 153 target_path = ERR_PTR(rc); 153 154 } 154 155 155 - out: 156 156 kfree(full_path); 157 - out_no_free: 157 + out: 158 158 FreeXid(xid); 159 159 nd_set_link(nd, target_path); 160 - return NULL; /* No cookie */ 160 + return NULL; 161 161 } 162 162 163 163 int ··· 207 219 } 208 220 } 209 221 210 - kfree(full_path); 211 - FreeXid(xid); 212 - return rc; 213 - } 214 - 215 - int 216 - cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) 217 - { 218 - struct inode *inode = direntry->d_inode; 219 - int rc = -EACCES; 220 - int xid; 221 - int oplock = 0; 222 - struct cifs_sb_info *cifs_sb; 223 - struct cifsTconInfo *pTcon; 224 - char *full_path = NULL; 225 - char *tmpbuffer; 226 - int len; 227 - __u16 fid; 228 - 229 - xid = GetXid(); 230 - cifs_sb = CIFS_SB(inode->i_sb); 231 - pTcon = cifs_sb->tcon; 232 - 233 - /* BB would it be safe against deadlock to grab this sem 234 - even though rename itself grabs the sem and calls lookup? */ 235 - /* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ 236 - full_path = build_path_from_dentry(direntry); 237 - /* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ 238 - 239 - if (full_path == NULL) { 240 - FreeXid(xid); 241 - return -ENOMEM; 242 - } 243 - 244 - cFYI(1, 245 - ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", 246 - full_path, inode, pBuffer, buflen)); 247 - if (buflen > PATH_MAX) 248 - len = PATH_MAX; 249 - else 250 - len = buflen; 251 - tmpbuffer = kmalloc(len, GFP_KERNEL); 252 - if (tmpbuffer == NULL) { 253 - kfree(full_path); 254 - FreeXid(xid); 255 - return -ENOMEM; 256 - } 257 - 258 - /* BB add read reparse point symlink code and 259 - Unix extensions symlink code here BB */ 260 - /* We could disable this based on pTcon->unix_ext flag instead ... but why? */ 261 - if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) 262 - rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, 263 - tmpbuffer, 264 - len - 1, 265 - cifs_sb->local_nls); 266 - else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 267 - cERROR(1, ("SFU style symlinks not implemented yet")); 268 - /* add open and read as in fs/cifs/inode.c */ 269 - } else { 270 - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, 271 - OPEN_REPARSE_POINT, &fid, &oplock, NULL, 272 - cifs_sb->local_nls, 273 - cifs_sb->mnt_cifs_flags & 274 - CIFS_MOUNT_MAP_SPECIAL_CHR); 275 - if (!rc) { 276 - rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, 277 - tmpbuffer, 278 - len - 1, 279 - fid, 280 - cifs_sb->local_nls); 281 - if (CIFSSMBClose(xid, pTcon, fid)) { 282 - cFYI(1, ("Error closing junction point " 283 - "(open for ioctl)")); 284 - } 285 - /* If it is a DFS junction earlier we would have gotten 286 - PATH_NOT_COVERED returned from server so we do 287 - not need to request the DFS info here */ 288 - } 289 - } 290 - /* BB Anything else to do to handle recursive links? */ 291 - /* BB Should we be using page ops here? */ 292 - 293 - /* BB null terminate returned string in pBuffer? BB */ 294 - if (rc == 0) { 295 - rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer); 296 - cFYI(1, 297 - ("vfs_readlink called from cifs_readlink returned %d", 298 - rc)); 299 - } 300 - 301 - kfree(tmpbuffer); 302 222 kfree(full_path); 303 223 FreeXid(xid); 304 224 return rc;
-71
fs/cifs/misc.c
··· 635 635 return; 636 636 } 637 637 638 - /* Windows maps these to the user defined 16 bit Unicode range since they are 639 - reserved symbols (along with \ and /), otherwise illegal to store 640 - in filenames in NTFS */ 641 - #define UNI_ASTERIK (__u16) ('*' + 0xF000) 642 - #define UNI_QUESTION (__u16) ('?' + 0xF000) 643 - #define UNI_COLON (__u16) (':' + 0xF000) 644 - #define UNI_GRTRTHAN (__u16) ('>' + 0xF000) 645 - #define UNI_LESSTHAN (__u16) ('<' + 0xF000) 646 - #define UNI_PIPE (__u16) ('|' + 0xF000) 647 - #define UNI_SLASH (__u16) ('\\' + 0xF000) 648 - 649 - /* Convert 16 bit Unicode pathname from wire format to string in current code 650 - page. Conversion may involve remapping up the seven characters that are 651 - only legal in POSIX-like OS (if they are present in the string). Path 652 - names are little endian 16 bit Unicode on the wire */ 653 - int 654 - cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, 655 - const struct nls_table *cp) 656 - { 657 - int i, j, len; 658 - __u16 src_char; 659 - 660 - for (i = 0, j = 0; i < maxlen; i++) { 661 - src_char = le16_to_cpu(source[i]); 662 - switch (src_char) { 663 - case 0: 664 - goto cUCS_out; /* BB check this BB */ 665 - case UNI_COLON: 666 - target[j] = ':'; 667 - break; 668 - case UNI_ASTERIK: 669 - target[j] = '*'; 670 - break; 671 - case UNI_QUESTION: 672 - target[j] = '?'; 673 - break; 674 - /* BB We can not handle remapping slash until 675 - all the calls to build_path_from_dentry 676 - are modified, as they use slash as separator BB */ 677 - /* case UNI_SLASH: 678 - target[j] = '\\'; 679 - break;*/ 680 - case UNI_PIPE: 681 - target[j] = '|'; 682 - break; 683 - case UNI_GRTRTHAN: 684 - target[j] = '>'; 685 - break; 686 - case UNI_LESSTHAN: 687 - target[j] = '<'; 688 - break; 689 - default: 690 - len = cp->uni2char(src_char, &target[j], 691 - NLS_MAX_CHARSET_SIZE); 692 - if (len > 0) { 693 - j += len; 694 - continue; 695 - } else { 696 - target[j] = '?'; 697 - } 698 - } 699 - j++; 700 - /* make sure we do not overrun callers allocated temp buffer */ 701 - if (j >= (2 * NAME_MAX)) 702 - break; 703 - } 704 - cUCS_out: 705 - target[j] = 0; 706 - return j; 707 - } 708 - 709 638 /* Convert 16 bit Unicode pathname to wire format from string in current code 710 639 page. Conversion may involve remapping up the seven characters that are 711 640 only legal in POSIX-like OS (if they are present in the string). Path
+2
fs/cifs/netmisc.c
··· 79 79 {ErrQuota, -EDQUOT}, 80 80 {ErrNotALink, -ENOLINK}, 81 81 {ERRnetlogonNotStarted, -ENOPROTOOPT}, 82 + {ERRsymlink, -EOPNOTSUPP}, 82 83 {ErrTooManyLinks, -EMLINK}, 83 84 {0, 0} 84 85 }; ··· 715 714 ERRDOS, ERRnoaccess, 0xc000028f}, { 716 715 ERRDOS, ERRnoaccess, 0xc0000290}, { 717 716 ERRDOS, ERRbadfunc, 0xc000029c}, { 717 + ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { 718 718 ERRDOS, ERRinvlevel, 0x007c0001}, }; 719 719 720 720 /*****************************************************************************
+7 -2
fs/cifs/nterr.h
··· 35 35 extern const struct nt_err_code_struct nt_errs[]; 36 36 37 37 /* Win32 Status codes. */ 38 - 39 - #define STATUS_BUFFER_OVERFLOW 0x80000005 40 38 #define STATUS_MORE_ENTRIES 0x0105 41 39 #define ERROR_INVALID_PARAMETER 0x0057 42 40 #define ERROR_INSUFFICIENT_BUFFER 0x007a ··· 48 50 #define STATUS_SOME_UNMAPPED 0x0107 49 51 #define STATUS_BUFFER_OVERFLOW 0x80000005 50 52 #define NT_STATUS_NO_MORE_ENTRIES 0x8000001a 53 + #define NT_STATUS_MEDIA_CHANGED 0x8000001c 54 + #define NT_STATUS_END_OF_MEDIA 0x8000001e 55 + #define NT_STATUS_MEDIA_CHECK 0x80000020 56 + #define NT_STATUS_NO_DATA_DETECTED 0x8000001c 57 + #define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d 58 + #define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288 59 + #define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288 51 60 #define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001 52 61 #define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002 53 62 #define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
+42 -26
fs/cifs/ntlmssp.h
··· 27 27 #define UnknownMessage cpu_to_le32(8) 28 28 29 29 /* Negotiate Flags */ 30 - #define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */ 31 - #define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */ 32 - #define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */ 33 - #define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */ 34 - #define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */ 35 - #define NTLMSSP_NEGOTIATE_DGRAM 0x0040 36 - #define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */ 37 - #define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */ 38 - #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 30 + #define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */ 31 + #define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */ 32 + #define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */ 33 + /* define reserved9 0x08 */ 34 + #define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */ 35 + #define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */ 36 + #define NTLMSSP_NEGOTIATE_DGRAM 0x0040 37 + #define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */ 38 + /* defined reserved 8 0x0100 */ 39 + #define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */ 40 + #define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */ 41 + #define NTLMSSP_ANONYMOUS 0x0800 42 + #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */ 39 43 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 40 - #define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */ 41 - #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */ 42 - #define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 43 - #define NTLMSSP_TARGET_TYPE_SERVER 0x20000 44 - #define NTLMSSP_TARGET_TYPE_SHARE 0x40000 45 - #define NTLMSSP_NEGOTIATE_NTLMV2 0x80000 46 - #define NTLMSSP_REQUEST_INIT_RESP 0x100000 47 - #define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 48 - #define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000 44 + #define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */ 45 + #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */ 46 + #define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 47 + #define NTLMSSP_TARGET_TYPE_SERVER 0x20000 48 + #define NTLMSSP_TARGET_TYPE_SHARE 0x40000 49 + #define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/ 50 + /* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */ 51 + #define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000 52 + #define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */ 53 + #define NTLMSSP_REQUEST_NON_NT_KEY 0x400000 49 54 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 50 - #define NTLMSSP_NEGOTIATE_128 0x20000000 51 - #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 52 - #define NTLMSSP_NEGOTIATE_56 0x80000000 55 + /* #define reserved4 0x1000000 */ 56 + #define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */ 57 + /* #define reserved3 0x4000000 */ 58 + /* #define reserved2 0x8000000 */ 59 + /* #define reserved1 0x10000000 */ 60 + #define NTLMSSP_NEGOTIATE_128 0x20000000 61 + #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 62 + #define NTLMSSP_NEGOTIATE_56 0x80000000 53 63 54 64 /* Although typedefs are not commonly used for structure definitions */ 55 65 /* in the Linux kernel, in this particular case they are useful */ ··· 70 60 typedef struct _SECURITY_BUFFER { 71 61 __le16 Length; 72 62 __le16 MaximumLength; 73 - __le32 Buffer; /* offset to buffer */ 63 + __le32 BufferOffset; /* offset to buffer */ 74 64 } __attribute__((packed)) SECURITY_BUFFER; 75 65 76 66 typedef struct _NEGOTIATE_MESSAGE { 77 67 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 78 - __le32 MessageType; /* 1 */ 68 + __le32 MessageType; /* NtLmNegotiate = 1 */ 79 69 __le32 NegotiateFlags; 80 70 SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ 81 71 SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ 72 + /* SECURITY_BUFFER for version info not present since we 73 + do not set the version is present flag */ 82 74 char DomainString[0]; 83 75 /* followed by WorkstationString */ 84 76 } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; 85 77 86 78 typedef struct _CHALLENGE_MESSAGE { 87 79 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 88 - __le32 MessageType; /* 2 */ 80 + __le32 MessageType; /* NtLmChallenge = 2 */ 89 81 SECURITY_BUFFER TargetName; 90 82 __le32 NegotiateFlags; 91 83 __u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; 92 84 __u8 Reserved[8]; 93 85 SECURITY_BUFFER TargetInfoArray; 86 + /* SECURITY_BUFFER for version info not present since we 87 + do not set the version is present flag */ 94 88 } __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; 95 89 96 90 typedef struct _AUTHENTICATE_MESSAGE { 97 - __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 98 - __le32 MessageType; /* 3 */ 91 + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 92 + __le32 MessageType; /* NtLmsAuthenticate = 3 */ 99 93 SECURITY_BUFFER LmChallengeResponse; 100 94 SECURITY_BUFFER NtChallengeResponse; 101 95 SECURITY_BUFFER DomainName; ··· 107 93 SECURITY_BUFFER WorkstationName; 108 94 SECURITY_BUFFER SessionKey; 109 95 __le32 NegotiateFlags; 96 + /* SECURITY_BUFFER for version info not present since we 97 + do not set the version is present flag */ 110 98 char UserString[0]; 111 99 } __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+54 -18
fs/cifs/readdir.c
··· 31 31 #include "cifs_fs_sb.h" 32 32 #include "cifsfs.h" 33 33 34 + /* 35 + * To be safe - for UCS to UTF-8 with strings loaded with the rare long 36 + * characters alloc more to account for such multibyte target UTF-8 37 + * characters. 38 + */ 39 + #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) 40 + 34 41 #ifdef CONFIG_CIFS_DEBUG2 35 42 static void dump_cifs_file_struct(struct file *file, char *label) 36 43 { ··· 445 438 } 446 439 } 447 440 441 + /* BB eventually need to add the following helper function to 442 + resolve NT_STATUS_STOPPED_ON_SYMLINK return code when 443 + we try to do FindFirst on (NTFS) directory symlinks */ 444 + /* 445 + int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, 446 + int xid) 447 + { 448 + __u16 fid; 449 + int len; 450 + int oplock = 0; 451 + int rc; 452 + struct cifsTconInfo *ptcon = cifs_sb->tcon; 453 + char *tmpbuffer; 454 + 455 + rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, 456 + OPEN_REPARSE_POINT, &fid, &oplock, NULL, 457 + cifs_sb->local_nls, 458 + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 459 + if (!rc) { 460 + tmpbuffer = kmalloc(maxpath); 461 + rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, 462 + tmpbuffer, 463 + maxpath -1, 464 + fid, 465 + cifs_sb->local_nls); 466 + if (CIFSSMBClose(xid, ptcon, fid)) { 467 + cFYI(1, ("Error closing temporary reparsepoint open)")); 468 + } 469 + } 470 + } 471 + */ 472 + 448 473 static int initiate_cifs_search(const int xid, struct file *file) 449 474 { 450 475 int rc = 0; ··· 532 493 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); 533 494 if (rc == 0) 534 495 cifsFile->invalidHandle = false; 535 - if ((rc == -EOPNOTSUPP) && 496 + /* BB add following call to handle readdir on new NTFS symlink errors 497 + else if STATUS_STOPPED_ON_SYMLINK 498 + call get_symlink_reparse_path and retry with new path */ 499 + else if ((rc == -EOPNOTSUPP) && 536 500 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { 537 501 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; 538 502 goto ffirst_retry; ··· 864 822 /* inode num, inode type and filename returned */ 865 823 static int cifs_get_name_from_search_buf(struct qstr *pqst, 866 824 char *current_entry, __u16 level, unsigned int unicode, 867 - struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) 825 + struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum) 868 826 { 869 827 int rc = 0; 870 828 unsigned int len = 0; ··· 923 881 } 924 882 925 883 if (unicode) { 926 - /* BB fixme - test with long names */ 927 - /* Note converted filename can be longer than in unicode */ 928 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 929 - pqst->len = cifs_convertUCSpath((char *)pqst->name, 930 - (__le16 *)filename, len/2, nlt); 931 - else 932 - pqst->len = cifs_strfromUCS_le((char *)pqst->name, 933 - (__le16 *)filename, len/2, nlt); 884 + pqst->len = cifs_from_ucs2((char *) pqst->name, 885 + (__le16 *) filename, 886 + UNICODE_NAME_MAX, 887 + min(len, max_len), nlt, 888 + cifs_sb->mnt_cifs_flags & 889 + CIFS_MOUNT_MAP_SPECIAL_CHR); 934 890 } else { 935 891 pqst->name = filename; 936 892 pqst->len = len; ··· 938 898 return rc; 939 899 } 940 900 941 - static int cifs_filldir(char *pfindEntry, struct file *file, 942 - filldir_t filldir, void *direntry, char *scratch_buf, int max_len) 901 + static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, 902 + void *direntry, char *scratch_buf, unsigned int max_len) 943 903 { 944 904 int rc = 0; 945 905 struct qstr qstring; ··· 1036 996 int num_to_fill = 0; 1037 997 char *tmp_buf = NULL; 1038 998 char *end_of_smb; 1039 - int max_len; 999 + unsigned int max_len; 1040 1000 1041 1001 xid = GetXid(); 1042 1002 ··· 1110 1070 cifsFile->srch_inf.ntwrk_buf_start); 1111 1071 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 1112 1072 1113 - /* To be safe - for UCS to UTF-8 with strings loaded 1114 - with the rare long characters alloc more to account for 1115 - such multibyte target UTF-8 characters. cifs_unicode.c, 1116 - which actually does the conversion, has the same limit */ 1117 - tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); 1073 + tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 1118 1074 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 1119 1075 if (current_entry == NULL) { 1120 1076 /* evaluate whether this case is an error */
+277 -63
fs/cifs/sess.c
··· 3 3 * 4 4 * SMB/CIFS session setup handling routines 5 5 * 6 - * Copyright (c) International Business Machines Corp., 2006, 2007 6 + * Copyright (c) International Business Machines Corp., 2006, 2009 7 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 8 * 9 9 * This library is free software; you can redistribute it and/or modify ··· 111 111 get_vc_num_exit: 112 112 write_unlock(&cifs_tcp_ses_lock); 113 113 114 - return le16_to_cpu(vcnum); 114 + return cpu_to_le16(vcnum); 115 115 } 116 116 117 117 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) ··· 277 277 *pbcc_area = bcc_ptr; 278 278 } 279 279 280 - static int decode_unicode_ssetup(char **pbcc_area, int bleft, 281 - struct cifsSesInfo *ses, 282 - const struct nls_table *nls_cp) 280 + static void 281 + decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, 282 + const struct nls_table *nls_cp) 283 283 { 284 - int rc = 0; 285 - int words_left, len; 284 + int len; 286 285 char *data = *pbcc_area; 287 286 288 287 cFYI(1, ("bleft %d", bleft)); ··· 299 300 ++bleft; 300 301 } 301 302 302 - words_left = bleft / 2; 303 - 304 - /* save off server operating system */ 305 - len = UniStrnlen((wchar_t *) data, words_left); 306 - 307 - if (len >= words_left) 308 - return rc; 309 - 310 303 kfree(ses->serverOS); 311 - /* UTF-8 string will not grow more than four times as big as UCS-16 */ 312 - ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 313 - if (ses->serverOS != NULL) { 314 - cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 315 - cFYI(1, ("serverOS=%s", ses->serverOS)); 316 - } 317 - data += 2 * (len + 1); 318 - words_left -= len + 1; 319 - 320 - /* save off server network operating system */ 321 - len = UniStrnlen((wchar_t *) data, words_left); 322 - 323 - if (len >= words_left) 324 - return rc; 304 + ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); 305 + cFYI(1, ("serverOS=%s", ses->serverOS)); 306 + len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; 307 + data += len; 308 + bleft -= len; 309 + if (bleft <= 0) 310 + return; 325 311 326 312 kfree(ses->serverNOS); 327 - ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 328 - if (ses->serverNOS != NULL) { 329 - cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 330 - nls_cp); 331 - cFYI(1, ("serverNOS=%s", ses->serverNOS)); 332 - if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { 333 - cFYI(1, ("NT4 server")); 334 - ses->flags |= CIFS_SES_NT4; 335 - } 336 - } 337 - data += 2 * (len + 1); 338 - words_left -= len + 1; 339 - 340 - /* save off server domain */ 341 - len = UniStrnlen((wchar_t *) data, words_left); 342 - 343 - if (len > words_left) 344 - return rc; 313 + ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); 314 + cFYI(1, ("serverNOS=%s", ses->serverNOS)); 315 + len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; 316 + data += len; 317 + bleft -= len; 318 + if (bleft <= 0) 319 + return; 345 320 346 321 kfree(ses->serverDomain); 347 - ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL); 348 - if (ses->serverDomain != NULL) { 349 - cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, 350 - nls_cp); 351 - cFYI(1, ("serverDomain=%s", ses->serverDomain)); 352 - } 353 - data += 2 * (len + 1); 354 - words_left -= len + 1; 322 + ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp); 323 + cFYI(1, ("serverDomain=%s", ses->serverDomain)); 355 324 356 - cFYI(1, ("words left: %d", words_left)); 357 - 358 - return rc; 325 + return; 359 326 } 360 327 361 328 static int decode_ascii_ssetup(char **pbcc_area, int bleft, ··· 378 413 return rc; 379 414 } 380 415 416 + static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, 417 + struct cifsSesInfo *ses) 418 + { 419 + CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; 420 + 421 + if (blob_len < sizeof(CHALLENGE_MESSAGE)) { 422 + cERROR(1, ("challenge blob len %d too small", blob_len)); 423 + return -EINVAL; 424 + } 425 + 426 + if (memcmp(pblob->Signature, "NTLMSSP", 8)) { 427 + cERROR(1, ("blob signature incorrect %s", pblob->Signature)); 428 + return -EINVAL; 429 + } 430 + if (pblob->MessageType != NtLmChallenge) { 431 + cERROR(1, ("Incorrect message type %d", pblob->MessageType)); 432 + return -EINVAL; 433 + } 434 + 435 + memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); 436 + /* BB we could decode pblob->NegotiateFlags; some may be useful */ 437 + /* In particular we can examine sign flags */ 438 + /* BB spec says that if AvId field of MsvAvTimestamp is populated then 439 + we must set the MIC field of the AUTHENTICATE_MESSAGE */ 440 + 441 + return 0; 442 + } 443 + 444 + #ifdef CONFIG_CIFS_EXPERIMENTAL 445 + /* BB Move to ntlmssp.c eventually */ 446 + 447 + /* We do not malloc the blob, it is passed in pbuffer, because 448 + it is fixed size, and small, making this approach cleaner */ 449 + static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, 450 + struct cifsSesInfo *ses) 451 + { 452 + NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; 453 + __u32 flags; 454 + 455 + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 456 + sec_blob->MessageType = NtLmNegotiate; 457 + 458 + /* BB is NTLMV2 session security format easier to use here? */ 459 + flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | 460 + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 461 + NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; 462 + if (ses->server->secMode & 463 + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 464 + flags |= NTLMSSP_NEGOTIATE_SIGN; 465 + if (ses->server->secMode & SECMODE_SIGN_REQUIRED) 466 + flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 467 + 468 + sec_blob->NegotiateFlags |= cpu_to_le32(flags); 469 + 470 + sec_blob->WorkstationName.BufferOffset = 0; 471 + sec_blob->WorkstationName.Length = 0; 472 + sec_blob->WorkstationName.MaximumLength = 0; 473 + 474 + /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */ 475 + sec_blob->DomainName.BufferOffset = 0; 476 + sec_blob->DomainName.Length = 0; 477 + sec_blob->DomainName.MaximumLength = 0; 478 + } 479 + 480 + /* We do not malloc the blob, it is passed in pbuffer, because its 481 + maximum possible size is fixed and small, making this approach cleaner. 482 + This function returns the length of the data in the blob */ 483 + static int build_ntlmssp_auth_blob(unsigned char *pbuffer, 484 + struct cifsSesInfo *ses, 485 + const struct nls_table *nls_cp, int first) 486 + { 487 + AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 488 + __u32 flags; 489 + unsigned char *tmp; 490 + char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 491 + 492 + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 493 + sec_blob->MessageType = NtLmAuthenticate; 494 + 495 + flags = NTLMSSP_NEGOTIATE_56 | 496 + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | 497 + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 498 + NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; 499 + if (ses->server->secMode & 500 + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 501 + flags |= NTLMSSP_NEGOTIATE_SIGN; 502 + if (ses->server->secMode & SECMODE_SIGN_REQUIRED) 503 + flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 504 + 505 + tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); 506 + sec_blob->NegotiateFlags |= cpu_to_le32(flags); 507 + 508 + sec_blob->LmChallengeResponse.BufferOffset = 509 + cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); 510 + sec_blob->LmChallengeResponse.Length = 0; 511 + sec_blob->LmChallengeResponse.MaximumLength = 0; 512 + 513 + /* calculate session key, BB what about adding similar ntlmv2 path? */ 514 + SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); 515 + if (first) 516 + cifs_calculate_mac_key(&ses->server->mac_signing_key, 517 + ntlm_session_key, ses->password); 518 + 519 + memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); 520 + sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 521 + sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); 522 + sec_blob->NtChallengeResponse.MaximumLength = 523 + cpu_to_le16(CIFS_SESS_KEY_SIZE); 524 + 525 + tmp += CIFS_SESS_KEY_SIZE; 526 + 527 + if (ses->domainName == NULL) { 528 + sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 529 + sec_blob->DomainName.Length = 0; 530 + sec_blob->DomainName.MaximumLength = 0; 531 + tmp += 2; 532 + } else { 533 + int len; 534 + len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, 535 + MAX_USERNAME_SIZE, nls_cp); 536 + len *= 2; /* unicode is 2 bytes each */ 537 + len += 2; /* trailing null */ 538 + sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 539 + sec_blob->DomainName.Length = cpu_to_le16(len); 540 + sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 541 + tmp += len; 542 + } 543 + 544 + if (ses->userName == NULL) { 545 + sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 546 + sec_blob->UserName.Length = 0; 547 + sec_blob->UserName.MaximumLength = 0; 548 + tmp += 2; 549 + } else { 550 + int len; 551 + len = cifs_strtoUCS((__le16 *)tmp, ses->userName, 552 + MAX_USERNAME_SIZE, nls_cp); 553 + len *= 2; /* unicode is 2 bytes each */ 554 + len += 2; /* trailing null */ 555 + sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 556 + sec_blob->UserName.Length = cpu_to_le16(len); 557 + sec_blob->UserName.MaximumLength = cpu_to_le16(len); 558 + tmp += len; 559 + } 560 + 561 + sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer); 562 + sec_blob->WorkstationName.Length = 0; 563 + sec_blob->WorkstationName.MaximumLength = 0; 564 + tmp += 2; 565 + 566 + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 567 + sec_blob->SessionKey.Length = 0; 568 + sec_blob->SessionKey.MaximumLength = 0; 569 + return tmp - pbuffer; 570 + } 571 + 572 + 573 + static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, 574 + struct cifsSesInfo *ses) 575 + { 576 + build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses); 577 + pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE)); 578 + 579 + return; 580 + } 581 + 582 + static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, 583 + struct cifsSesInfo *ses, 584 + const struct nls_table *nls, int first_time) 585 + { 586 + int bloblen; 587 + 588 + bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, 589 + first_time); 590 + pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); 591 + 592 + return bloblen; 593 + } 594 + #endif 595 + 381 596 int 382 597 CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, 383 598 const struct nls_table *nls_cp) ··· 576 431 __u16 action; 577 432 int bytes_remaining; 578 433 struct key *spnego_key = NULL; 434 + __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 579 435 580 436 if (ses == NULL) 581 437 return -EINVAL; ··· 584 438 type = ses->server->secType; 585 439 586 440 cFYI(1, ("sess setup type %d", type)); 441 + ssetup_ntlmssp_authenticate: 442 + if (phase == NtLmChallenge) 443 + phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ 444 + 587 445 if (type == LANMAN) { 588 446 #ifndef CONFIG_CIFS_WEAK_PW_HASH 589 447 /* LANMAN and plaintext are less secure and off by default. ··· 801 651 goto ssetup_exit; 802 652 #endif /* CONFIG_CIFS_UPCALL */ 803 653 } else { 654 + #ifdef CONFIG_CIFS_EXPERIMENTAL 655 + if ((experimEnabled > 1) && (type == RawNTLMSSP)) { 656 + if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { 657 + cERROR(1, ("NTLMSSP requires Unicode support")); 658 + rc = -ENOSYS; 659 + goto ssetup_exit; 660 + } 661 + 662 + cFYI(1, ("ntlmssp session setup phase %d", phase)); 663 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 664 + capabilities |= CAP_EXTENDED_SECURITY; 665 + pSMB->req.Capabilities |= cpu_to_le32(capabilities); 666 + if (phase == NtLmNegotiate) { 667 + setup_ntlmssp_neg_req(pSMB, ses); 668 + iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 669 + } else if (phase == NtLmAuthenticate) { 670 + int blob_len; 671 + blob_len = setup_ntlmssp_auth_req(pSMB, ses, 672 + nls_cp, 673 + first_time); 674 + iov[1].iov_len = blob_len; 675 + /* Make sure that we tell the server that we 676 + are using the uid that it just gave us back 677 + on the response (challenge) */ 678 + smb_buf->Uid = ses->Suid; 679 + } else { 680 + cERROR(1, ("invalid phase %d", phase)); 681 + rc = -ENOSYS; 682 + goto ssetup_exit; 683 + } 684 + iov[1].iov_base = &pSMB->req.SecurityBlob[0]; 685 + /* unicode strings must be word aligned */ 686 + if ((iov[0].iov_len + iov[1].iov_len) % 2) { 687 + *bcc_ptr = 0; 688 + bcc_ptr++; 689 + } 690 + unicode_oslm_strings(&bcc_ptr, nls_cp); 691 + } else { 692 + cERROR(1, ("secType %d not supported!", type)); 693 + rc = -ENOSYS; 694 + goto ssetup_exit; 695 + } 696 + #else 804 697 cERROR(1, ("secType %d not supported!", type)); 805 698 rc = -ENOSYS; 806 699 goto ssetup_exit; 700 + #endif 807 701 } 808 702 809 703 iov[2].iov_base = str_area; ··· 863 669 /* SMB request buf freed in SendReceive2 */ 864 670 865 671 cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); 866 - if (rc) 867 - goto ssetup_exit; 868 672 869 673 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; 870 674 smb_buf = (struct smb_hdr *)iov[0].iov_base; 675 + 676 + if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError == 677 + cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) { 678 + if (phase != NtLmNegotiate) { 679 + cERROR(1, ("Unexpected more processing error")); 680 + goto ssetup_exit; 681 + } 682 + /* NTLMSSP Negotiate sent now processing challenge (response) */ 683 + phase = NtLmChallenge; /* process ntlmssp challenge */ 684 + rc = 0; /* MORE_PROC rc is not an error here, but expected */ 685 + } 686 + if (rc) 687 + goto ssetup_exit; 871 688 872 689 if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { 873 690 rc = -EIO; ··· 898 693 if (smb_buf->WordCount == 4) { 899 694 __u16 blob_len; 900 695 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); 901 - bcc_ptr += blob_len; 902 696 if (blob_len > bytes_remaining) { 903 697 cERROR(1, ("bad security blob length %d", blob_len)); 904 698 rc = -EINVAL; 905 699 goto ssetup_exit; 906 700 } 701 + if (phase == NtLmChallenge) { 702 + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); 703 + /* now goto beginning for ntlmssp authenticate phase */ 704 + if (rc) 705 + goto ssetup_exit; 706 + } 707 + bcc_ptr += blob_len; 907 708 bytes_remaining -= blob_len; 908 709 } 909 710 ··· 920 709 ++bcc_ptr; 921 710 --bytes_remaining; 922 711 } 923 - rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, 924 - ses, nls_cp); 712 + decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); 925 713 } else { 926 714 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, 927 715 ses, nls_cp); ··· 937 727 cifs_small_buf_release(iov[0].iov_base); 938 728 } else if (resp_buf_type == CIFS_LARGE_BUFFER) 939 729 cifs_buf_release(iov[0].iov_base); 730 + 731 + /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */ 732 + if ((phase == NtLmChallenge) && (rc == 0)) 733 + goto ssetup_ntlmssp_authenticate; 940 734 941 735 return rc; 942 736 }
+1
fs/cifs/smberr.h
··· 110 110 111 111 /* Below errors are used internally (do not come over the wire) for passthrough 112 112 from STATUS codes to POSIX only */ 113 + #define ERRsymlink 0xFFFD 113 114 #define ErrTooManyLinks 0xFFFE 114 115 115 116 /* Following error codes may be generated with the ERRSRV error class.*/
+19
include/linux/nls.h
··· 58 58 return 0; 59 59 } 60 60 61 + /* 62 + * nls_nullsize - return length of null character for codepage 63 + * @codepage - codepage for which to return length of NULL terminator 64 + * 65 + * Since we can't guarantee that the null terminator will be a particular 66 + * length, we have to check against the codepage. If there's a problem 67 + * determining it, assume a single-byte NULL terminator. 68 + */ 69 + static inline int 70 + nls_nullsize(const struct nls_table *codepage) 71 + { 72 + int charlen; 73 + char tmp[NLS_MAX_CHARSET_SIZE]; 74 + 75 + charlen = codepage->uni2char(0, tmp, NLS_MAX_CHARSET_SIZE); 76 + 77 + return charlen > 0 ? charlen : 1; 78 + } 79 + 61 80 #define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name)) 62 81 63 82 #endif /* _LINUX_NLS_H */