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
config CIFS_FSCACHE
bool "Provide CIFS client caching support (EXPERIMENTAL)"
depends on EXPERIMENTAL
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
help
Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
......@@ -149,7 +148,7 @@ config CIFS_FSCACHE
config CIFS_ACL
bool "Provide CIFS ACL support (EXPERIMENTAL)"
depends on EXPERIMENTAL && CIFS_XATTR && KEYS
depends on CIFS_XATTR && KEYS
help
Allows to fetch CIFS/NTFS ACL from the server. The DACL blob
is handed over to the application/caller.
......
......@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
{
char c;
int rc;
static bool warned;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
multiuser_mount = 0;
else if (c == '1' || c == 'y' || c == 'Y')
else if (c == '1' || c == 'y' || c == 'Y') {
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;
}
......
......@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
MAX_MECH_STR_LEN +
UID_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;
if (sesInfo->user_name)
desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
spnego_key = ERR_PTR(-ENOMEM);
description = kzalloc(desc_len, GFP_KERNEL);
if (description == NULL)
......@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
dp = description + strlen(description);
sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
dp = description + strlen(description);
sprintf(dp, ";user=%s", sesInfo->user_name);
if (sesInfo->user_name) {
dp = description + strlen(description);
sprintf(dp, ";user=%s", sesInfo->user_name);
}
dp = description + strlen(description);
sprintf(dp, ";pid=0x%x", current->pid);
......
......@@ -27,17 +27,17 @@
#include "cifs_debug.h"
/*
* cifs_ucs2_bytes - how long will a string be after conversion?
* @ucs - pointer to input string
* cifs_utf16_bytes - how long will a string be after conversion?
* @utf16 - pointer to input string
* @maxbytes - don't go past this many bytes of input string
* @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
* termination required. Don't walk past maxbytes in the source buffer.
*/
int
cifs_ucs2_bytes(const __le16 *from, int maxbytes,
cifs_utf16_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage)
{
int i;
......@@ -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
* @from - source buffer
* @tolen - destination buffer size (in bytes)
......@@ -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
* @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
* 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
......@@ -139,12 +139,12 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
* null terminator).
*
* 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
* those characters, they won't be translated properly.
*/
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)
{
int i, charlen, safelen;
......@@ -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
*
*/
int
cifs_strtoUCS(__le16 *to, const char *from, int len,
cifs_strtoUTF16(__le16 *to, const char *from, int len,
const struct nls_table *codepage)
{
int charlen;
......@@ -206,7 +206,7 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
charlen = codepage->char2uni(from, len, &wchar_to);
if (charlen < 1) {
cERROR(1, "strtoUCS: char2uni of 0x%x returned %d",
cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d",
*from, charlen);
/* A question mark */
wchar_to = 0x003f;
......@@ -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
* @maxlen - don't walk past this many bytes in the source string
* @is_unicode - is this a unicode string?
......@@ -231,19 +232,19 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
* error.
*/
char *
cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
const struct nls_table *codepage)
cifs_strndup_from_utf16(const char *src, const int maxlen,
const bool is_unicode, const struct nls_table *codepage)
{
int len;
char *dst;
if (is_unicode) {
len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
len += nls_nullsize(codepage);
dst = kmalloc(len, GFP_KERNEL);
if (!dst)
return NULL;
cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
false);
} else {
len = strnlen(src, maxlen);
......@@ -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
*/
int
cifsConvertToUCS(__le16 *target, const char *source, int srclen,
cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapChars)
{
int i, j, charlen;
......@@ -273,7 +274,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
wchar_t tmp;
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++) {
src_char = source[i];
......@@ -281,7 +282,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
switch (src_char) {
case 0:
put_unaligned(0, &target[j]);
goto ctoUCS_out;
goto ctoUTF16_out;
case ':':
dst_char = cpu_to_le16(UNI_COLON);
break;
......@@ -326,7 +327,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
put_unaligned(dst_char, &target[j]);
}
ctoUCS_out:
ctoUTF16_out:
return i;
}
......@@ -74,16 +74,16 @@ extern const struct UniCaseRange CifsUniLowerRange[];
#endif /* UNIUPR_NOLOWER */
#ifdef __KERNEL__
int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *codepage, bool mapchar);
int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage);
int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
char *cifs_strndup_from_ucs(const char *src, const int maxlen,
const bool is_unicode,
const struct nls_table *codepage);
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars);
int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *codepage, bool mapchar);
int cifs_utf16_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage);
int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
char *cifs_strndup_from_utf16(const char *src, const int maxlen,
const bool is_unicode,
const struct nls_table *codepage);
extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars);
#endif
......
......@@ -909,6 +909,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
umode_t group_mask = S_IRWXG;
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 *),
GFP_KERNEL);
if (!ppace) {
......
......@@ -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->length = cpu_to_le16(2 * dlen);
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;
}
......@@ -376,7 +376,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
kmalloc(attrsize + 1, GFP_KERNEL);
if (!ses->domainName)
return -ENOMEM;
cifs_from_ucs2(ses->domainName,
cifs_from_utf16(ses->domainName,
(__le16 *)blobptr, attrsize, attrsize,
nls_cp, false);
break;
......@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
}
/* 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);
if (user == NULL) {
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
rc = -ENOMEM;
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,
(char *)user, 2 * len);
......@@ -448,8 +453,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
rc = -ENOMEM;
return rc;
}
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
nls_cp);
len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
nls_cp);
rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
(char *)domain, 2 * len);
......@@ -468,7 +473,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
rc = -ENOMEM;
return rc;
}
len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
nls_cp);
rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
......
......@@ -879,6 +879,8 @@ require use of the stronger protocol */
#define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */
#endif /* UPCALL */
#else /* do not allow weak pw hash */
#define CIFSSEC_MUST_LANMAN 0
#define CIFSSEC_MUST_PLNTXT 0
#ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
#else
......
This diff is collapsed.
This diff is collapsed.
......@@ -647,10 +647,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
name.name = scratch_buf;
name.len =
cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
UNICODE_NAME_MAX,
min(de.namelen, (size_t)max_len), nlt,
cifs_sb->mnt_cifs_flags &
cifs_from_utf16((char *)name.name, (__le16 *)de.name,
UNICODE_NAME_MAX,
min_t(size_t, de.namelen,
(size_t)max_len), nlt,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
name.len -= nls_nullsize(nlt);
} else {
......
......@@ -167,16 +167,16 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
int bytes_ret = 0;
/* Copy OS version */
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp);
bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp);
bcc_ptr += 2 * bytes_ret;
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp);
bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp);
bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
......@@ -197,8 +197,8 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
*(bcc_ptr+1) = 0;
bytes_ret = 0;
} else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */
......@@ -226,8 +226,8 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
} else {
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name,
MAX_USERNAME_SIZE, nls_cp);
bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
MAX_USERNAME_SIZE, nls_cp);
}
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */
......@@ -287,7 +287,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
cFYI(1, "bleft %d", bleft);
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);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len;
......@@ -296,7 +296,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
return;
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);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len;
......@@ -305,7 +305,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
return;
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);
return;
......@@ -502,8 +502,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
tmp += 2;
} else {
int len;
len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
MAX_USERNAME_SIZE, nls_cp);
len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->DomainName.Length = cpu_to_le16(len);
......@@ -518,8 +518,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
tmp += 2;
} else {
int len;
len = cifs_strtoUCS((__le16 *)tmp, ses->user_name,
MAX_USERNAME_SIZE, nls_cp);
len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->UserName.Length = cpu_to_le16(len);
......
......@@ -213,7 +213,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16,
/* Password cannot be longer than 128 characters */
if (passwd) /* Password must be converted to NT unicode */
len = cifs_strtoUCS(wpwd, passwd, 128, codepage);
len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
else {
len = 0;
*wpwd = 0; /* Ensure string is null terminated */
......
......@@ -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:
* - the payload struct is invariant may not be changed, only replaced
* - the payload must be read with RCU procedures or with the key semaphore
......@@ -33,6 +33,7 @@ struct user_key_payload {
};
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_update(struct key *key, const void *data, size_t datalen);
......
......@@ -33,6 +33,7 @@
extern struct key_type key_type_dead;
extern struct key_type key_type_user;
extern struct key_type key_type_logon;
/*****************************************************************************/
/*
......
......@@ -999,6 +999,7 @@ void __init key_init(void)
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_user.link, &key_types_list);
list_add_tail(&key_type_logon.link, &key_types_list);
/* record the root user tracking */
rb_link_node(&root_key_user.node,
......
......@@ -18,6 +18,8 @@
#include <asm/uaccess.h>
#include "internal.h"
static int logon_vet_description(const char *desc);
/*
* user defined keys take an arbitrary string as the description and an
* arbitrary blob of data as the payload
......@@ -35,6 +37,24 @@ struct key_type 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
*/
......@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
}
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