Commit 7908b3ef authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.samba.org/sfrench/cifs-2.6

* git://git.samba.org/sfrench/cifs-2.6:
  CIFS: Rename *UCS* functions to *UTF16*
  [CIFS] ACL and FSCACHE support no longer EXPERIMENTAL
  [CIFS] Fix build break with multiuser patch when LANMAN disabled
  cifs: warn about impending deprecation of legacy MultiuserMount code
  cifs: fetch credentials out of keyring for non-krb5 auth multiuser mounts
  cifs: sanitize username handling
  keys: add a "logon" key type
  cifs: lower default wsize when unix extensions are not used
  cifs: better instrumentation for coalesce_t2
  cifs: integer overflow in parse_dacl()
  cifs: Fix sparse warning when calling cifs_strtoUCS
  CIFS: Add descriptions to the brlock cache functions
parents dcd6c922 acbbb76a
...@@ -140,7 +140,6 @@ config CIFS_DFS_UPCALL ...@@ -140,7 +140,6 @@ config CIFS_DFS_UPCALL
config CIFS_FSCACHE config CIFS_FSCACHE
bool "Provide CIFS client caching support (EXPERIMENTAL)" bool "Provide CIFS client caching support (EXPERIMENTAL)"
depends on EXPERIMENTAL
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
help help
Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
...@@ -149,7 +148,7 @@ config CIFS_FSCACHE ...@@ -149,7 +148,7 @@ config CIFS_FSCACHE
config CIFS_ACL config CIFS_ACL
bool "Provide CIFS ACL support (EXPERIMENTAL)" bool "Provide CIFS ACL support (EXPERIMENTAL)"
depends on EXPERIMENTAL && CIFS_XATTR && KEYS depends on CIFS_XATTR && KEYS
help help
Allows to fetch CIFS/NTFS ACL from the server. The DACL blob Allows to fetch CIFS/NTFS ACL from the server. The DACL blob
is handed over to the application/caller. is handed over to the application/caller.
......
...@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file, ...@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
{ {
char c; char c;
int rc; int rc;
static bool warned;
rc = get_user(c, buffer); rc = get_user(c, buffer);
if (rc) if (rc)
return rc; return rc;
if (c == '0' || c == 'n' || c == 'N') if (c == '0' || c == 'n' || c == 'N')
multiuser_mount = 0; multiuser_mount = 0;
else if (c == '1' || c == 'y' || c == 'Y') else if (c == '1' || c == 'y' || c == 'Y') {
multiuser_mount = 1; multiuser_mount = 1;
if (!warned) {
warned = true;
printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
"mount code is scheduled to be deprecated in "
"3.5. Please switch to using the multiuser "
"mount option.");
}
}
return count; return count;
} }
......
...@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) ...@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
MAX_MECH_STR_LEN + MAX_MECH_STR_LEN +
UID_KEY_LEN + (sizeof(uid_t) * 2) + UID_KEY_LEN + (sizeof(uid_t) * 2) +
CREDUID_KEY_LEN + (sizeof(uid_t) * 2) + CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
USER_KEY_LEN + strlen(sesInfo->user_name) +
PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
if (sesInfo->user_name)
desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
spnego_key = ERR_PTR(-ENOMEM); spnego_key = ERR_PTR(-ENOMEM);
description = kzalloc(desc_len, GFP_KERNEL); description = kzalloc(desc_len, GFP_KERNEL);
if (description == NULL) if (description == NULL)
...@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) ...@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
dp = description + strlen(description); dp = description + strlen(description);
sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid); sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
dp = description + strlen(description); if (sesInfo->user_name) {
sprintf(dp, ";user=%s", sesInfo->user_name); dp = description + strlen(description);
sprintf(dp, ";user=%s", sesInfo->user_name);
}
dp = description + strlen(description); dp = description + strlen(description);
sprintf(dp, ";pid=0x%x", current->pid); sprintf(dp, ";pid=0x%x", current->pid);
......
...@@ -27,17 +27,17 @@ ...@@ -27,17 +27,17 @@
#include "cifs_debug.h" #include "cifs_debug.h"
/* /*
* cifs_ucs2_bytes - how long will a string be after conversion? * cifs_utf16_bytes - how long will a string be after conversion?
* @ucs - pointer to input string * @utf16 - pointer to input string
* @maxbytes - don't go past this many bytes of input string * @maxbytes - don't go past this many bytes of input string
* @codepage - destination codepage * @codepage - destination codepage
* *
* Walk a ucs2le string and return the number of bytes that the string will * Walk a utf16le string and return the number of bytes that the string will
* be after being converted to the given charset, not including any null * be after being converted to the given charset, not including any null
* termination required. Don't walk past maxbytes in the source buffer. * termination required. Don't walk past maxbytes in the source buffer.
*/ */
int int
cifs_ucs2_bytes(const __le16 *from, int maxbytes, cifs_utf16_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage) const struct nls_table *codepage)
{ {
int i; int i;
...@@ -122,7 +122,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, ...@@ -122,7 +122,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
} }
/* /*
* cifs_from_ucs2 - convert utf16le string to local charset * cifs_from_utf16 - convert utf16le string to local charset
* @to - destination buffer * @to - destination buffer
* @from - source buffer * @from - source buffer
* @tolen - destination buffer size (in bytes) * @tolen - destination buffer size (in bytes)
...@@ -130,7 +130,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, ...@@ -130,7 +130,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
* @codepage - codepage to which characters should be converted * @codepage - codepage to which characters should be converted
* @mapchar - should characters be remapped according to the mapchars option? * @mapchar - should characters be remapped according to the mapchars option?
* *
* Convert a little-endian ucs2le string (as sent by the server) to a string * Convert a little-endian utf16le string (as sent by the server) to a string
* in the provided codepage. The tolen and fromlen parameters are to ensure * in the provided codepage. The tolen and fromlen parameters are to ensure
* that the code doesn't walk off of the end of the buffer (which is always * that the code doesn't walk off of the end of the buffer (which is always
* a danger if the alignment of the source buffer is off). The destination * a danger if the alignment of the source buffer is off). The destination
...@@ -139,12 +139,12 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, ...@@ -139,12 +139,12 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
* null terminator). * null terminator).
* *
* Note that some windows versions actually send multiword UTF-16 characters * Note that some windows versions actually send multiword UTF-16 characters
* instead of straight UCS-2. The linux nls routines however aren't able to * instead of straight UTF16-2. The linux nls routines however aren't able to
* deal with those characters properly. In the event that we get some of * deal with those characters properly. In the event that we get some of
* those characters, they won't be translated properly. * those characters, they won't be translated properly.
*/ */
int int
cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *codepage, bool mapchar) const struct nls_table *codepage, bool mapchar)
{ {
int i, charlen, safelen; int i, charlen, safelen;
...@@ -190,13 +190,13 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, ...@@ -190,13 +190,13 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
} }
/* /*
* NAME: cifs_strtoUCS() * NAME: cifs_strtoUTF16()
* *
* FUNCTION: Convert character string to unicode string * FUNCTION: Convert character string to unicode string
* *
*/ */
int int
cifs_strtoUCS(__le16 *to, const char *from, int len, cifs_strtoUTF16(__le16 *to, const char *from, int len,
const struct nls_table *codepage) const struct nls_table *codepage)
{ {
int charlen; int charlen;
...@@ -206,7 +206,7 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, ...@@ -206,7 +206,7 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
for (i = 0; len && *from; i++, from += charlen, len -= charlen) { for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
charlen = codepage->char2uni(from, len, &wchar_to); charlen = codepage->char2uni(from, len, &wchar_to);
if (charlen < 1) { if (charlen < 1) {
cERROR(1, "strtoUCS: char2uni of 0x%x returned %d", cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d",
*from, charlen); *from, charlen);
/* A question mark */ /* A question mark */
wchar_to = 0x003f; wchar_to = 0x003f;
...@@ -220,7 +220,8 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, ...@@ -220,7 +220,8 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
} }
/* /*
* cifs_strndup_from_ucs - copy a string from wire format to the local codepage * cifs_strndup_from_utf16 - copy a string from wire format to the local
* codepage
* @src - source string * @src - source string
* @maxlen - don't walk past this many bytes in the source string * @maxlen - don't walk past this many bytes in the source string
* @is_unicode - is this a unicode string? * @is_unicode - is this a unicode string?
...@@ -231,19 +232,19 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, ...@@ -231,19 +232,19 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
* error. * error.
*/ */
char * char *
cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, cifs_strndup_from_utf16(const char *src, const int maxlen,
const struct nls_table *codepage) const bool is_unicode, const struct nls_table *codepage)
{ {
int len; int len;
char *dst; char *dst;
if (is_unicode) { if (is_unicode) {
len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage); len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
len += nls_nullsize(codepage); len += nls_nullsize(codepage);
dst = kmalloc(len, GFP_KERNEL); dst = kmalloc(len, GFP_KERNEL);
if (!dst) if (!dst)
return NULL; return NULL;
cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage, cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
false); false);
} else { } else {
len = strnlen(src, maxlen); len = strnlen(src, maxlen);
...@@ -264,7 +265,7 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, ...@@ -264,7 +265,7 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
* names are little endian 16 bit Unicode on the wire * names are little endian 16 bit Unicode on the wire
*/ */
int int
cifsConvertToUCS(__le16 *target, const char *source, int srclen, cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapChars) const struct nls_table *cp, int mapChars)
{ {
int i, j, charlen; int i, j, charlen;
...@@ -273,7 +274,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen, ...@@ -273,7 +274,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
wchar_t tmp; wchar_t tmp;
if (!mapChars) if (!mapChars)
return cifs_strtoUCS(target, source, PATH_MAX, cp); return cifs_strtoUTF16(target, source, PATH_MAX, cp);
for (i = 0, j = 0; i < srclen; j++) { for (i = 0, j = 0; i < srclen; j++) {
src_char = source[i]; src_char = source[i];
...@@ -281,7 +282,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen, ...@@ -281,7 +282,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
switch (src_char) { switch (src_char) {
case 0: case 0:
put_unaligned(0, &target[j]); put_unaligned(0, &target[j]);
goto ctoUCS_out; goto ctoUTF16_out;
case ':': case ':':
dst_char = cpu_to_le16(UNI_COLON); dst_char = cpu_to_le16(UNI_COLON);
break; break;
...@@ -326,7 +327,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen, ...@@ -326,7 +327,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
put_unaligned(dst_char, &target[j]); put_unaligned(dst_char, &target[j]);
} }
ctoUCS_out: ctoUTF16_out:
return i; return i;
} }
...@@ -74,16 +74,16 @@ extern const struct UniCaseRange CifsUniLowerRange[]; ...@@ -74,16 +74,16 @@ extern const struct UniCaseRange CifsUniLowerRange[];
#endif /* UNIUPR_NOLOWER */ #endif /* UNIUPR_NOLOWER */
#ifdef __KERNEL__ #ifdef __KERNEL__
int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *codepage, bool mapchar); const struct nls_table *codepage, bool mapchar);
int cifs_ucs2_bytes(const __le16 *from, int maxbytes, int cifs_utf16_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage); const struct nls_table *codepage);
int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
char *cifs_strndup_from_ucs(const char *src, const int maxlen, char *cifs_strndup_from_utf16(const char *src, const int maxlen,
const bool is_unicode, const bool is_unicode,
const struct nls_table *codepage); const struct nls_table *codepage);
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars); const struct nls_table *cp, int mapChars);
#endif #endif
......
...@@ -909,6 +909,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, ...@@ -909,6 +909,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
umode_t group_mask = S_IRWXG; umode_t group_mask = S_IRWXG;
umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO; umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
return;
ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
GFP_KERNEL); GFP_KERNEL);
if (!ppace) { if (!ppace) {
......
...@@ -327,7 +327,7 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -327,7 +327,7 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
attrptr->length = cpu_to_le16(2 * dlen); attrptr->length = cpu_to_le16(2 * dlen);
blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp); cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
return 0; return 0;
} }
...@@ -376,7 +376,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -376,7 +376,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
kmalloc(attrsize + 1, GFP_KERNEL); kmalloc(attrsize + 1, GFP_KERNEL);
if (!ses->domainName) if (!ses->domainName)
return -ENOMEM; return -ENOMEM;
cifs_from_ucs2(ses->domainName, cifs_from_utf16(ses->domainName,
(__le16 *)blobptr, attrsize, attrsize, (__le16 *)blobptr, attrsize, attrsize,
nls_cp, false); nls_cp, false);
break; break;
...@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, ...@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
} }
/* convert ses->user_name to unicode and uppercase */ /* convert ses->user_name to unicode and uppercase */
len = strlen(ses->user_name); len = ses->user_name ? strlen(ses->user_name) : 0;
user = kmalloc(2 + (len * 2), GFP_KERNEL); user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL) { if (user == NULL) {
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
rc = -ENOMEM; rc = -ENOMEM;
return rc; return rc;
} }
len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
UniStrupr(user); if (len) {
len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp);
UniStrupr(user);
} else {
memset(user, '\0', 2);
}
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
(char *)user, 2 * len); (char *)user, 2 * len);
...@@ -448,8 +453,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, ...@@ -448,8 +453,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
rc = -ENOMEM; rc = -ENOMEM;
return rc; return rc;
} }
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
nls_cp); nls_cp);
rc = rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
(char *)domain, 2 * len); (char *)domain, 2 * len);
...@@ -468,7 +473,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, ...@@ -468,7 +473,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
rc = -ENOMEM; rc = -ENOMEM;
return rc; return rc;
} }
len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
nls_cp); nls_cp);
rc = rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
......
...@@ -879,6 +879,8 @@ require use of the stronger protocol */ ...@@ -879,6 +879,8 @@ require use of the stronger protocol */
#define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */ #define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */
#endif /* UPCALL */ #endif /* UPCALL */
#else /* do not allow weak pw hash */ #else /* do not allow weak pw hash */
#define CIFSSEC_MUST_LANMAN 0
#define CIFSSEC_MUST_PLNTXT 0
#ifdef CONFIG_CIFS_UPCALL #ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ #define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
#else #else
......
...@@ -821,8 +821,8 @@ CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, ...@@ -821,8 +821,8 @@ CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB add path length overrun check */ } else { /* BB add path length overrun check */
...@@ -893,8 +893,8 @@ CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, ...@@ -893,8 +893,8 @@ CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->fileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
...@@ -938,8 +938,8 @@ CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName, ...@@ -938,8 +938,8 @@ CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
return rc; return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName, name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
...@@ -981,8 +981,8 @@ CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon, ...@@ -981,8 +981,8 @@ CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
return rc; return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name, name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
...@@ -1030,8 +1030,8 @@ CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags, ...@@ -1030,8 +1030,8 @@ CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, name, cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -1197,8 +1197,8 @@ SMBLegacyOpen(const int xid, struct cifs_tcon *tcon, ...@@ -1197,8 +1197,8 @@ SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
count = 1; /* account for one byte pad to word boundary */ count = 1; /* account for one byte pad to word boundary */
name_len = name_len =
cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
fileName, PATH_MAX, nls_codepage, remap); fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
...@@ -1304,8 +1304,8 @@ CIFSSMBOpen(const int xid, struct cifs_tcon *tcon, ...@@ -1304,8 +1304,8 @@ CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
count = 1; /* account for one byte pad to word boundary */ count = 1; /* account for one byte pad to word boundary */
name_len = name_len =
cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
fileName, PATH_MAX, nls_codepage, remap); fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->NameLength = cpu_to_le16(name_len); pSMB->NameLength = cpu_to_le16(name_len);
...@@ -2649,16 +2649,16 @@ CIFSSMBRename(const int xid, struct cifs_tcon *tcon, ...@@ -2649,16 +2649,16 @@ CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->OldFileName[name_len] = 0x04; /* pad */ pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */ /* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00; pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 = name_len2 =
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
toName, PATH_MAX, nls_codepage, remap); toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */ name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -2738,10 +2738,12 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon, ...@@ -2738,10 +2738,12 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
/* unicode only call */ /* unicode only call */
if (target_name == NULL) { if (target_name == NULL) {
sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid); sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, len_of_str =
cifsConvertToUTF16((__le16 *)rename_info->target_name,
dummy_string, 24, nls_codepage, remap); dummy_string, 24, nls_codepage, remap);
} else { } else {
len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, len_of_str =
cifsConvertToUTF16((__le16 *)rename_info->target_name,
target_name, PATH_MAX, nls_codepage, target_name, PATH_MAX, nls_codepage,
remap); remap);
} }
...@@ -2795,17 +2797,17 @@ CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName, ...@@ -2795,17 +2797,17 @@ CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
pSMB->Flags = cpu_to_le16(flags & COPY_TREE); pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName, name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
fromName, PATH_MAX, nls_codepage, fromName, PATH_MAX, nls_codepage,
remap); remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->OldFileName[name_len] = 0x04; /* pad */ pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */ /* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00; pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 = name_len2 =
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
toName, PATH_MAX, nls_codepage, remap); toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */ name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -2861,9 +2863,9 @@ CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon, ...@@ -2861,9 +2863,9 @@ CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
/* find define for this maxpathcomponent */ /* find define for this maxpathcomponent */
, nls_codepage); PATH_MAX, nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
...@@ -2885,9 +2887,9 @@ CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon, ...@@ -2885,9 +2887,9 @@ CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
data_offset = (char *) (&pSMB->hdr.Protocol) + offset; data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target = name_len_target =
cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
/* find define for this maxpathcomponent */ /* find define for this maxpathcomponent */
, nls_codepage); , nls_codepage);
name_len_target++; /* trailing null */ name_len_target++; /* trailing null */
name_len_target *= 2; name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -2949,8 +2951,8 @@ CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon, ...@@ -2949,8 +2951,8 @@ CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
return rc; return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName, name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
...@@ -2972,8 +2974,8 @@ CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon, ...@@ -2972,8 +2974,8 @@ CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
data_offset = (char *) (&pSMB->hdr.Protocol) + offset; data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target = name_len_target =
cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX, cifsConvertToUTF16((__le16 *) data_offset, fromName,
nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len_target++; /* trailing null */ name_len_target++; /* trailing null */
name_len_target *= 2; name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -3042,8 +3044,8 @@ CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon, ...@@ -3042,8 +3044,8 @@ CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
...@@ -3051,8 +3053,8 @@ CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon, ...@@ -3051,8 +3053,8 @@ CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
pSMB->OldFileName[name_len] = 0x04; pSMB->OldFileName[name_len] = 0x04;
pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
name_len2 = name_len2 =
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
toName, PATH_MAX, nls_codepage, remap); toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */ name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -3108,8 +3110,8 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon, ...@@ -3108,8 +3110,8 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage); PATH_MAX, nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -3166,8 +3168,8 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon, ...@@ -3166,8 +3168,8 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
is_unicode = false; is_unicode = false;
/* BB FIXME investigate remapping reserved chars here */ /* BB FIXME investigate remapping reserved chars here */
*symlinkinfo = cifs_strndup_from_ucs(data_start, count, *symlinkinfo = cifs_strndup_from_utf16(data_start,
is_unicode, nls_codepage); count, is_unicode, nls_codepage);
if (!*symlinkinfo) if (!*symlinkinfo)
rc = -ENOMEM; rc = -ENOMEM;
} }
...@@ -3450,8 +3452,9 @@ CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, ...@@ -3450,8 +3452,9 @@ CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName,
PATH_MAX, nls_codepage, remap); searchName, PATH_MAX, nls_codepage,
remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->FileName[name_len] = 0; pSMB->FileName[name_len] = 0;
...@@ -3537,8 +3540,8 @@ CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon, ...@@ -3537,8 +3540,8 @@ CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
return rc; return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -3948,8 +3951,9 @@ int SMBQueryInformation(const int xid, struct cifs_tcon *tcon, ...@@ -3948,8 +3951,9 @@ int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName,
PATH_MAX, nls_codepage, remap); searchName, PATH_MAX, nls_codepage,
remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { } else {
...@@ -4086,8 +4090,8 @@ CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon, ...@@ -4086,8 +4090,8 @@ CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -4255,8 +4259,8 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon, ...@@ -4255,8 +4259,8 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -4344,8 +4348,8 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon, ...@@ -4344,8 +4348,8 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
/* We can not add the asterik earlier in case /* We can not add the asterik earlier in case
it got remapped to 0xF03A as if it were part of the it got remapped to 0xF03A as if it were part of the
directory name instead of a wildcard */ directory name instead of a wildcard */
...@@ -4656,8 +4660,9 @@ CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, ...@@ -4656,8 +4660,9 @@ CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName,
PATH_MAX, nls_codepage, remap); searchName, PATH_MAX, nls_codepage,
remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -4794,9 +4799,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, ...@@ -4794,9 +4799,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
rc = -ENOMEM; rc = -ENOMEM;
goto parse_DFS_referrals_exit; goto parse_DFS_referrals_exit;
} }
cifsConvertToUCS((__le16 *) tmp, searchName, cifsConvertToUTF16((__le16 *) tmp, searchName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
node->path_consumed = cifs_ucs2_bytes(tmp, node->path_consumed = cifs_utf16_bytes(tmp,
le16_to_cpu(pSMBr->PathConsumed), le16_to_cpu(pSMBr->PathConsumed),
nls_codepage); nls_codepage);
kfree(tmp); kfree(tmp);
...@@ -4809,8 +4814,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, ...@@ -4809,8 +4814,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
/* copy DfsPath */ /* copy DfsPath */
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
max_len = data_end - temp; max_len = data_end - temp;
node->path_name = cifs_strndup_from_ucs(temp, max_len, node->path_name = cifs_strndup_from_utf16(temp, max_len,
is_unicode, nls_codepage); is_unicode, nls_codepage);
if (!node->path_name) { if (!node->path_name) {
rc = -ENOMEM; rc = -ENOMEM;
goto parse_DFS_referrals_exit; goto parse_DFS_referrals_exit;
...@@ -4819,8 +4824,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, ...@@ -4819,8 +4824,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
/* copy link target UNC */ /* copy link target UNC */
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
max_len = data_end - temp; max_len = data_end - temp;
node->node_name = cifs_strndup_from_ucs(temp, max_len, node->node_name = cifs_strndup_from_utf16(temp, max_len,
is_unicode, nls_codepage); is_unicode, nls_codepage);
if (!node->node_name) if (!node->node_name)
rc = -ENOMEM; rc = -ENOMEM;
} }
...@@ -4873,8 +4878,9 @@ CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, ...@@ -4873,8 +4878,9 @@ CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->RequestFileName, cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
searchName, PATH_MAX, nls_codepage, remap); searchName, PATH_MAX, nls_codepage,
remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -5506,8 +5512,8 @@ CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName, ...@@ -5506,8 +5512,8 @@ CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -5796,8 +5802,8 @@ CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon, ...@@ -5796,8 +5802,8 @@ CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -5877,8 +5883,8 @@ CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName, ...@@ -5877,8 +5883,8 @@ CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
ConvertToUCS((__le16 *) pSMB->fileName, fileName, ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
PATH_MAX, nls_codepage); PATH_MAX, nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -6030,8 +6036,8 @@ CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName, ...@@ -6030,8 +6036,8 @@ CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -6123,8 +6129,8 @@ CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, ...@@ -6123,8 +6129,8 @@ CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
list_len = list_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
list_len++; /* trailing null */ list_len++; /* trailing null */
list_len *= 2; list_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -6301,8 +6307,8 @@ CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName, ...@@ -6301,8 +6307,8 @@ CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <linux/inet.h> #include <linux/inet.h>
#include <linux/module.h> #include <linux/module.h>
#include <keys/user-type.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
...@@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB) ...@@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB)
static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
{ {
struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond;
struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
char *data_area_of_target; char *data_area_of_tgt;
char *data_area_of_buf2; char *data_area_of_src;
int remaining; int remaining;
unsigned int byte_count, total_in_buf; unsigned int byte_count, total_in_tgt;
__u16 total_data_size, total_in_buf2; __u16 tgt_total_cnt, src_total_cnt, total_in_src;
total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
if (total_data_size != if (tgt_total_cnt != src_total_cnt)
get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount)) cFYI(1, "total data count of primary and secondary t2 differ "
cFYI(1, "total data size of primary and secondary t2 differ"); "source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
remaining = total_data_size - total_in_buf; remaining = tgt_total_cnt - total_in_tgt;
if (remaining < 0) if (remaining < 0) {
cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
"total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
return -EPROTO; return -EPROTO;
}
if (remaining == 0) /* nothing to do, ignore */ if (remaining == 0) {
/* nothing to do, ignore */
cFYI(1, "no more data remains");
return 0; return 0;
}
total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount); total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
if (remaining < total_in_buf2) { if (remaining < total_in_src)
cFYI(1, "transact2 2nd response contains too much data"); cFYI(1, "transact2 2nd response contains too much data");
}
/* find end of first SMB data area */ /* find end of first SMB data area */
data_area_of_target = (char *)&pSMBt->hdr.Protocol + data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
/* validate target area */
data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol + /* validate target area */
get_unaligned_le16(&pSMB2->t2_rsp.DataOffset); data_area_of_src = (char *)&pSMBs->hdr.Protocol +
get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
data_area_of_target += total_in_buf; data_area_of_tgt += total_in_tgt;
/* copy second buffer into end of first buffer */ total_in_tgt += total_in_src;
total_in_buf += total_in_buf2;
/* is the result too big for the field? */ /* is the result too big for the field? */
if (total_in_buf > USHRT_MAX) if (total_in_tgt > USHRT_MAX) {
cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
return -EPROTO; return -EPROTO;
put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); }
put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
/* fix up the BCC */ /* fix up the BCC */
byte_count = get_bcc(pTargetSMB); byte_count = get_bcc(pTargetSMB);
byte_count += total_in_buf2; byte_count += total_in_src;
/* is the result too big for the field? */ /* is the result too big for the field? */
if (byte_count > USHRT_MAX) if (byte_count > USHRT_MAX) {
cFYI(1, "coalesced BCC too large (%u)", byte_count);
return -EPROTO; return -EPROTO;
}
put_bcc(byte_count, pTargetSMB); put_bcc(byte_count, pTargetSMB);
byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
byte_count += total_in_buf2; byte_count += total_in_src;
/* don't allow buffer to overflow */ /* don't allow buffer to overflow */
if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
return -ENOBUFS; return -ENOBUFS;
}
pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); /* copy second buffer into end of first buffer */
memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
if (remaining == total_in_buf2) { if (remaining != total_in_src) {
cFYI(1, "found the last secondary response"); /* more responses to go */
return 0; /* we are done */ cFYI(1, "waiting for more secondary responses");
} else /* more responses to go */
return 1; return 1;
}
/* we are done */
cFYI(1, "found the last secondary response");
return 0;
} }
static void static void
...@@ -1578,11 +1595,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1578,11 +1595,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
} }
} }
if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { #ifndef CONFIG_KEYS
cERROR(1, "Multiuser mounts currently require krb5 " /* Muliuser mounts require CONFIG_KEYS support */
"authentication!"); if (vol->multiuser) {
cERROR(1, "Multiuser mounts require kernels with "
"CONFIG_KEYS enabled.");
goto cifs_parse_mount_err; goto cifs_parse_mount_err;
} }
#endif
if (vol->UNCip == NULL) if (vol->UNCip == NULL)
vol->UNCip = &vol->UNC[2]; vol->UNCip = &vol->UNC[2];
...@@ -1981,10 +2001,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) ...@@ -1981,10 +2001,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
return 0; return 0;
break; break;
default: default:
/* NULL username means anonymous session */
if (ses->user_name == NULL) {
if (!vol->nullauth)
return 0;
break;
}
/* anything else takes username/password */ /* anything else takes username/password */
if (ses->user_name == NULL) if (strncmp(ses->user_name,
return 0; vol->username ? vol->username : "",
if (strncmp(ses->user_name, vol->username,
MAX_USERNAME_SIZE)) MAX_USERNAME_SIZE))
return 0; return 0;
if (strlen(vol->username) != 0 && if (strlen(vol->username) != 0 &&
...@@ -2039,6 +2065,132 @@ cifs_put_smb_ses(struct cifs_ses *ses) ...@@ -2039,6 +2065,132 @@ cifs_put_smb_ses(struct cifs_ses *ses)
cifs_put_tcp_session(server); cifs_put_tcp_session(server);
} }
#ifdef CONFIG_KEYS
/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
/* Populate username and pw fields from keyring if possible */
static int
cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
{
int rc = 0;
char *desc, *delim, *payload;
ssize_t len;
struct key *key;
struct TCP_Server_Info *server = ses->server;
struct sockaddr_in *sa;
struct sockaddr_in6 *sa6;
struct user_key_payload *upayload;
desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
if (!desc)
return -ENOMEM;
/* try to find an address key first */
switch (server->dstaddr.ss_family) {
case AF_INET:
sa = (struct sockaddr_in *)&server->dstaddr;
sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
break;
case AF_INET6:
sa6 = (struct sockaddr_in6 *)&server->dstaddr;
sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
break;
default:
cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
rc = -EINVAL;
goto out_err;
}
cFYI(1, "%s: desc=%s", __func__, desc);
key = request_key(&key_type_logon, desc, "");
if (IS_ERR(key)) {
if (!ses->domainName) {
cFYI(1, "domainName is NULL");
rc = PTR_ERR(key);
goto out_err;
}
/* didn't work, try to find a domain key */
sprintf(desc, "cifs:d:%s", ses->domainName);
cFYI(1, "%s: desc=%s", __func__, desc);
key = request_key(&key_type_logon, desc, "");
if (IS_ERR(key)) {
rc = PTR_ERR(key);
goto out_err;
}
}
down_read(&key->sem);
upayload = key->payload.data;
if (IS_ERR_OR_NULL(upayload)) {
rc = PTR_ERR(key);
goto out_key_put;
}
/* find first : in payload */
payload = (char *)upayload->data;
delim = strnchr(payload, upayload->datalen, ':');
cFYI(1, "payload=%s", payload);
if (!delim) {
cFYI(1, "Unable to find ':' in payload (datalen=%d)",
upayload->datalen);
rc = -EINVAL;
goto out_key_put;
}
len = delim - payload;
if (len > MAX_USERNAME_SIZE || len <= 0) {
cFYI(1, "Bad value from username search (len=%ld)", len);
rc = -EINVAL;
goto out_key_put;
}
vol->username = kstrndup(payload, len, GFP_KERNEL);
if (!vol->username) {
cFYI(1, "Unable to allocate %ld bytes for username", len);
rc = -ENOMEM;
goto out_key_put;
}
cFYI(1, "%s: username=%s", __func__, vol->username);
len = key->datalen - (len + 1);
if (len > MAX_PASSWORD_SIZE || len <= 0) {
cFYI(1, "Bad len for password search (len=%ld)", len);
rc = -EINVAL;
kfree(vol->username);
vol->username = NULL;
goto out_key_put;
}
++delim;
vol->password = kstrndup(delim, len, GFP_KERNEL);
if (!vol->password) {
cFYI(1, "Unable to allocate %ld bytes for password", len);
rc = -ENOMEM;
kfree(vol->username);
vol->username = NULL;
goto out_key_put;
}
out_key_put:
up_read(&key->sem);
key_put(key);
out_err:
kfree(desc);
cFYI(1, "%s: returning %d", __func__, rc);
return rc;
}
#else /* ! CONFIG_KEYS */
static inline int
cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
struct cifs_ses *ses __attribute__((unused)))
{
return -ENOSYS;
}
#endif /* CONFIG_KEYS */
static bool warned_on_ntlm; /* globals init to false automatically */ static bool warned_on_ntlm; /* globals init to false automatically */
static struct cifs_ses * static struct cifs_ses *
...@@ -2914,18 +3066,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, ...@@ -2914,18 +3066,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
#define CIFS_DEFAULT_IOSIZE (1024 * 1024) #define CIFS_DEFAULT_IOSIZE (1024 * 1024)
/* /*
* Windows only supports a max of 60k reads. Default to that when posix * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
* extensions aren't in force. * those values when posix extensions aren't in force. In actuality here, we
* use 65536 to allow for a write that is a multiple of 4k. Most servers seem
* to be ok with the extra byte even though Windows doesn't send writes that
* are that large.
*
* Citation:
*
* http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
*/ */
#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
static unsigned int static unsigned int
cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
{ {
__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
struct TCP_Server_Info *server = tcon->ses->server; struct TCP_Server_Info *server = tcon->ses->server;
unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize : unsigned int wsize;
CIFS_DEFAULT_IOSIZE;
/* start with specified wsize, or default */
if (pvolume_info->wsize)
wsize = pvolume_info->wsize;
else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
wsize = CIFS_DEFAULT_IOSIZE;
else
wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
/* can server support 24-bit write sizes? (via UNIX extensions) */ /* can server support 24-bit write sizes? (via UNIX extensions) */
if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
...@@ -3136,10 +3303,9 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, ...@@ -3136,10 +3303,9 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
return -EINVAL; return -EINVAL;
if (volume_info->nullauth) { if (volume_info->nullauth) {
cFYI(1, "null user"); cFYI(1, "Anonymous login");
volume_info->username = kzalloc(1, GFP_KERNEL); kfree(volume_info->username);
if (volume_info->username == NULL) volume_info->username = NULL;
return -ENOMEM;
} else if (volume_info->username) { } else if (volume_info->username) {
/* BB fixme parse for domain name here */ /* BB fixme parse for domain name here */
cFYI(1, "Username: %s", volume_info->username); cFYI(1, "Username: %s", volume_info->username);
...@@ -3478,7 +3644,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, ...@@ -3478,7 +3644,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE; smb_buffer->Flags2 |= SMBFLG2_UNICODE;
length = length =
cifs_strtoUCS((__le16 *) bcc_ptr, tree, cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
6 /* max utf8 char length in bytes */ * 6 /* max utf8 char length in bytes */ *
(/* server len*/ + 256 /* share len */), nls_codepage); (/* server len*/ + 256 /* share len */), nls_codepage);
bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
...@@ -3533,7 +3699,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, ...@@ -3533,7 +3699,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
/* mostly informational -- no need to fail on error here */ /* mostly informational -- no need to fail on error here */
kfree(tcon->nativeFileSystem); kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
bytes_left, is_unicode, bytes_left, is_unicode,
nls_codepage); nls_codepage);
...@@ -3657,16 +3823,38 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses, ...@@ -3657,16 +3823,38 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
return rc; return rc;
} }
static int
cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
{
switch (ses->server->secType) {
case Kerberos:
vol->secFlg = CIFSSEC_MUST_KRB5;
return 0;
case NTLMv2:
vol->secFlg = CIFSSEC_MUST_NTLMV2;
break;
case NTLM:
vol->secFlg = CIFSSEC_MUST_NTLM;
break;
case RawNTLMSSP:
vol->secFlg = CIFSSEC_MUST_NTLMSSP;
break;
case LANMAN:
vol->secFlg = CIFSSEC_MUST_LANMAN;
break;
}
return cifs_set_cifscreds(vol, ses);
}
static struct cifs_tcon * static struct cifs_tcon *
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
{ {
int rc;
struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
struct cifs_ses *ses; struct cifs_ses *ses;
struct cifs_tcon *tcon = NULL; struct cifs_tcon *tcon = NULL;
struct smb_vol *vol_info; struct smb_vol *vol_info;
char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
/* We used to have this as MAX_USERNAME which is */
/* way too big now (256 instead of 32) */
vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
if (vol_info == NULL) { if (vol_info == NULL) {
...@@ -3674,8 +3862,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) ...@@ -3674,8 +3862,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
goto out; goto out;
} }
snprintf(username, sizeof(username), "krb50x%x", fsuid);
vol_info->username = username;
vol_info->local_nls = cifs_sb->local_nls; vol_info->local_nls = cifs_sb->local_nls;
vol_info->linux_uid = fsuid; vol_info->linux_uid = fsuid;
vol_info->cred_uid = fsuid; vol_info->cred_uid = fsuid;
...@@ -3685,8 +3871,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) ...@@ -3685,8 +3871,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
vol_info->local_lease = master_tcon->local_lease; vol_info->local_lease = master_tcon->local_lease;
vol_info->no_linux_ext = !master_tcon->unix_ext; vol_info->no_linux_ext = !master_tcon->unix_ext;
/* FIXME: allow for other secFlg settings */ rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
vol_info->secFlg = CIFSSEC_MUST_KRB5; if (rc) {
tcon = ERR_PTR(rc);
goto out;
}
/* get a reference for the same TCP session */ /* get a reference for the same TCP session */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
...@@ -3709,6 +3898,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) ...@@ -3709,6 +3898,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
if (ses->capabilities & CAP_UNIX) if (ses->capabilities & CAP_UNIX)
reset_cifs_unix_caps(0, tcon, NULL, vol_info); reset_cifs_unix_caps(0, tcon, NULL, vol_info);
out: out:
kfree(vol_info->username);
kfree(vol_info->password);
kfree(vol_info); kfree(vol_info);
return tcon; return tcon;
......
...@@ -647,10 +647,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, ...@@ -647,10 +647,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
name.name = scratch_buf; name.name = scratch_buf;
name.len = name.len =
cifs_from_ucs2((char *)name.name, (__le16 *)de.name, cifs_from_utf16((char *)name.name, (__le16 *)de.name,
UNICODE_NAME_MAX, UNICODE_NAME_MAX,
min(de.namelen, (size_t)max_len), nlt, min_t(size_t, de.namelen,
cifs_sb->mnt_cifs_flags & (size_t)max_len), nlt,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
name.len -= nls_nullsize(nlt); name.len -= nls_nullsize(nlt);
} else { } else {
......
...@@ -167,16 +167,16 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp) ...@@ -167,16 +167,16 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
int bytes_ret = 0; int bytes_ret = 0;
/* Copy OS version */ /* Copy OS version */
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp); nls_cp);
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp); 32, nls_cp);
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */ bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp); 32, nls_cp);
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */ bcc_ptr += 2; /* trailing null */
...@@ -197,8 +197,8 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, ...@@ -197,8 +197,8 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
*(bcc_ptr+1) = 0; *(bcc_ptr+1) = 0;
bytes_ret = 0; bytes_ret = 0;
} else } else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp); 256, nls_cp);
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */ bcc_ptr += 2; /* account for null terminator */
...@@ -226,8 +226,8 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, ...@@ -226,8 +226,8 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
*bcc_ptr = 0; *bcc_ptr = 0;
*(bcc_ptr+1) = 0; *(bcc_ptr+1) = 0;
} else { } else {
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name, bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
MAX_USERNAME_SIZE, nls_cp); MAX_USERNAME_SIZE, nls_cp);
} }
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */ bcc_ptr += 2; /* account for null termination */
...@@ -287,7 +287,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, ...@@ -287,7 +287,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
cFYI(1, "bleft %d", bleft); cFYI(1, "bleft %d", bleft);
kfree(ses->serverOS); kfree(ses->serverOS);
ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
cFYI(1, "serverOS=%s", ses->serverOS); cFYI(1, "serverOS=%s", ses->serverOS);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len; data += len;
...@@ -296,7 +296,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, ...@@ -296,7 +296,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
return; return;
kfree(ses->serverNOS); kfree(ses->serverNOS);
ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
cFYI(1, "serverNOS=%s", ses->serverNOS); cFYI(1, "serverNOS=%s", ses->serverNOS);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len; data += len;
...@@ -305,7 +305,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, ...@@ -305,7 +305,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
return; return;
kfree(ses->serverDomain); kfree(ses->serverDomain);
ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp); ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
cFYI(1, "serverDomain=%s", ses->serverDomain); cFYI(1, "serverDomain=%s", ses->serverDomain);
return; return;
...@@ -502,8 +502,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -502,8 +502,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
tmp += 2; tmp += 2;
} else { } else {
int len; int len;
len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
MAX_USERNAME_SIZE, nls_cp); MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */ len *= 2; /* unicode is 2 bytes each */
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->DomainName.Length = cpu_to_le16(len); sec_blob->DomainName.Length = cpu_to_le16(len);
...@@ -518,8 +518,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -518,8 +518,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
tmp += 2; tmp += 2;
} else { } else {
int len; int len;
len = cifs_strtoUCS((__le16 *)tmp, ses->user_name, len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
MAX_USERNAME_SIZE, nls_cp); MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */ len *= 2; /* unicode is 2 bytes each */
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->UserName.Length = cpu_to_le16(len); sec_blob->UserName.Length = cpu_to_le16(len);
......
...@@ -213,7 +213,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16, ...@@ -213,7 +213,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16,
/* Password cannot be longer than 128 characters */ /* Password cannot be longer than 128 characters */
if (passwd) /* Password must be converted to NT unicode */ if (passwd) /* Password must be converted to NT unicode */
len = cifs_strtoUCS(wpwd, passwd, 128, codepage); len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
else { else {
len = 0; len = 0;
*wpwd = 0; /* Ensure string is null terminated */ *wpwd = 0; /* Ensure string is null terminated */
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/*****************************************************************************/ /*****************************************************************************/
/* /*
* the payload for a key of type "user" * the payload for a key of type "user" or "logon"
* - once filled in and attached to a key: * - once filled in and attached to a key:
* - the payload struct is invariant may not be changed, only replaced * - the payload struct is invariant may not be changed, only replaced
* - the payload must be read with RCU procedures or with the key semaphore * - the payload must be read with RCU procedures or with the key semaphore
...@@ -33,6 +33,7 @@ struct user_key_payload { ...@@ -33,6 +33,7 @@ struct user_key_payload {
}; };
extern struct key_type key_type_user; extern struct key_type key_type_user;
extern struct key_type key_type_logon;
extern int user_instantiate(struct key *key, const void *data, size_t datalen); extern int user_instantiate(struct key *key, const void *data, size_t datalen);
extern int user_update(struct key *key, const void *data, size_t datalen); extern int user_update(struct key *key, const void *data, size_t datalen);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
extern struct key_type key_type_dead; extern struct key_type key_type_dead;
extern struct key_type key_type_user; extern struct key_type key_type_user;
extern struct key_type key_type_logon;
/*****************************************************************************/ /*****************************************************************************/
/* /*
......
...@@ -999,6 +999,7 @@ void __init key_init(void) ...@@ -999,6 +999,7 @@ void __init key_init(void)
list_add_tail(&key_type_keyring.link, &key_types_list); list_add_tail(&key_type_keyring.link, &key_types_list);
list_add_tail(&key_type_dead.link, &key_types_list); list_add_tail(&key_type_dead.link, &key_types_list);
list_add_tail(&key_type_user.link, &key_types_list); list_add_tail(&key_type_user.link, &key_types_list);
list_add_tail(&key_type_logon.link, &key_types_list);
/* record the root user tracking */ /* record the root user tracking */
rb_link_node(&root_key_user.node, rb_link_node(&root_key_user.node,
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "internal.h" #include "internal.h"
static int logon_vet_description(const char *desc);
/* /*
* user defined keys take an arbitrary string as the description and an * user defined keys take an arbitrary string as the description and an
* arbitrary blob of data as the payload * arbitrary blob of data as the payload
...@@ -35,6 +37,24 @@ struct key_type key_type_user = { ...@@ -35,6 +37,24 @@ struct key_type key_type_user = {
EXPORT_SYMBOL_GPL(key_type_user); EXPORT_SYMBOL_GPL(key_type_user);
/*
* This key type is essentially the same as key_type_user, but it does
* not define a .read op. This is suitable for storing username and
* password pairs in the keyring that you do not want to be readable
* from userspace.
*/
struct key_type key_type_logon = {
.name = "logon",
.instantiate = user_instantiate,
.update = user_update,
.match = user_match,
.revoke = user_revoke,
.destroy = user_destroy,
.describe = user_describe,
.vet_description = logon_vet_description,
};
EXPORT_SYMBOL_GPL(key_type_logon);
/* /*
* instantiate a user defined key * instantiate a user defined key
*/ */
...@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) ...@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
} }
EXPORT_SYMBOL_GPL(user_read); EXPORT_SYMBOL_GPL(user_read);
/* Vet the description for a "logon" key */
static int logon_vet_description(const char *desc)
{
char *p;
/* require a "qualified" description string */
p = strchr(desc, ':');
if (!p)
return -EINVAL;
/* also reject description with ':' as first char */
if (p == desc)
return -EINVAL;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment