mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
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
This commit is contained in:
commit
7908b3ef68
@ -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 @@ cp_convert:
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 @@ cp_convert:
|
||||
* @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 @@ cp_convert:
|
||||
* 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
|
||||
|
@ -821,8 +821,8 @@ PsxDelete:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB add path length overrun check */
|
||||
@ -893,8 +893,8 @@ DelFileRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve check for buffer overruns BB */
|
||||
@ -938,8 +938,8 @@ RmDirRetry:
|
||||
return rc;
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve check for buffer overruns BB */
|
||||
@ -981,8 +981,8 @@ MkDirRetry:
|
||||
return rc;
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve check for buffer overruns BB */
|
||||
@ -1030,8 +1030,8 @@ PsxCreat:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, name,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -1197,8 +1197,8 @@ OldOpenRetry:
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
count = 1; /* account for one byte pad to word boundary */
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
|
||||
fileName, PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
|
||||
fileName, PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve check for buffer overruns BB */
|
||||
@ -1304,8 +1304,8 @@ openRetry:
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
count = 1; /* account for one byte pad to word boundary */
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
|
||||
fileName, PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
|
||||
fileName, PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
pSMB->NameLength = cpu_to_le16(name_len);
|
||||
@ -2649,16 +2649,16 @@ renameRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
||||
/* protocol requires ASCII signature byte on Unicode string */
|
||||
pSMB->OldFileName[name_len + 1] = 0x00;
|
||||
name_len2 =
|
||||
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
||||
toName, PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
|
||||
toName, PATH_MAX, nls_codepage, remap);
|
||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||
name_len2 *= 2; /* convert to bytes */
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -2738,10 +2738,12 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
|
||||
/* unicode only call */
|
||||
if (target_name == NULL) {
|
||||
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);
|
||||
} 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,
|
||||
remap);
|
||||
}
|
||||
@ -2795,17 +2797,17 @@ copyRetry:
|
||||
pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
|
||||
fromName, PATH_MAX, nls_codepage,
|
||||
remap);
|
||||
name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
|
||||
fromName, PATH_MAX, nls_codepage,
|
||||
remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
||||
/* protocol requires ASCII signature byte on Unicode string */
|
||||
pSMB->OldFileName[name_len + 1] = 0x00;
|
||||
name_len2 =
|
||||
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
||||
toName, PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
|
||||
toName, PATH_MAX, nls_codepage, remap);
|
||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||
name_len2 *= 2; /* convert to bytes */
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -2861,9 +2863,9 @@ createSymLinkRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
|
||||
/* find define for this maxpathcomponent */
|
||||
, nls_codepage);
|
||||
cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
|
||||
/* find define for this maxpathcomponent */
|
||||
PATH_MAX, nls_codepage);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
|
||||
@ -2885,9 +2887,9 @@ createSymLinkRetry:
|
||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len_target =
|
||||
cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
|
||||
/* find define for this maxpathcomponent */
|
||||
, nls_codepage);
|
||||
cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
|
||||
/* find define for this maxpathcomponent */
|
||||
, nls_codepage);
|
||||
name_len_target++; /* trailing null */
|
||||
name_len_target *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -2949,8 +2951,8 @@ createHardLinkRetry:
|
||||
return rc;
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
|
||||
@ -2972,8 +2974,8 @@ createHardLinkRetry:
|
||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len_target =
|
||||
cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
|
||||
nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) data_offset, fromName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len_target++; /* trailing null */
|
||||
name_len_target *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -3042,8 +3044,8 @@ winCreateHardLinkRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
|
||||
@ -3051,8 +3053,8 @@ winCreateHardLinkRetry:
|
||||
pSMB->OldFileName[name_len] = 0x04;
|
||||
pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
|
||||
name_len2 =
|
||||
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
||||
toName, PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
|
||||
toName, PATH_MAX, nls_codepage, remap);
|
||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||
name_len2 *= 2; /* convert to bytes */
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -3108,8 +3110,8 @@ querySymLinkRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage);
|
||||
cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -3166,8 +3168,8 @@ querySymLinkRetry:
|
||||
is_unicode = false;
|
||||
|
||||
/* BB FIXME investigate remapping reserved chars here */
|
||||
*symlinkinfo = cifs_strndup_from_ucs(data_start, count,
|
||||
is_unicode, nls_codepage);
|
||||
*symlinkinfo = cifs_strndup_from_utf16(data_start,
|
||||
count, is_unicode, nls_codepage);
|
||||
if (!*symlinkinfo)
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
@ -3450,8 +3452,9 @@ queryAclRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName,
|
||||
searchName, PATH_MAX, nls_codepage,
|
||||
remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
pSMB->FileName[name_len] = 0;
|
||||
@ -3537,8 +3540,8 @@ setAclRetry:
|
||||
return rc;
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -3948,8 +3951,9 @@ QInfRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName,
|
||||
searchName, PATH_MAX, nls_codepage,
|
||||
remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else {
|
||||
@ -4086,8 +4090,8 @@ QPathInfoRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -4255,8 +4259,8 @@ UnixQPathInfoRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -4344,8 +4348,8 @@ findFirstRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
/* We can not add the asterik earlier in case
|
||||
it got remapped to 0xF03A as if it were part of the
|
||||
directory name instead of a wildcard */
|
||||
@ -4656,8 +4660,9 @@ GetInodeNumberRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName,
|
||||
searchName, PATH_MAX, nls_codepage,
|
||||
remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -4794,9 +4799,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
|
||||
rc = -ENOMEM;
|
||||
goto parse_DFS_referrals_exit;
|
||||
}
|
||||
cifsConvertToUCS((__le16 *) tmp, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
node->path_consumed = cifs_ucs2_bytes(tmp,
|
||||
cifsConvertToUTF16((__le16 *) tmp, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
node->path_consumed = cifs_utf16_bytes(tmp,
|
||||
le16_to_cpu(pSMBr->PathConsumed),
|
||||
nls_codepage);
|
||||
kfree(tmp);
|
||||
@ -4809,8 +4814,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
|
||||
/* copy DfsPath */
|
||||
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
|
||||
max_len = data_end - temp;
|
||||
node->path_name = cifs_strndup_from_ucs(temp, max_len,
|
||||
is_unicode, nls_codepage);
|
||||
node->path_name = cifs_strndup_from_utf16(temp, max_len,
|
||||
is_unicode, nls_codepage);
|
||||
if (!node->path_name) {
|
||||
rc = -ENOMEM;
|
||||
goto parse_DFS_referrals_exit;
|
||||
@ -4819,8 +4824,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
|
||||
/* copy link target UNC */
|
||||
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
|
||||
max_len = data_end - temp;
|
||||
node->node_name = cifs_strndup_from_ucs(temp, max_len,
|
||||
is_unicode, nls_codepage);
|
||||
node->node_name = cifs_strndup_from_utf16(temp, max_len,
|
||||
is_unicode, nls_codepage);
|
||||
if (!node->node_name)
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
@ -4873,8 +4878,9 @@ getDFSRetry:
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
|
||||
searchName, PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
|
||||
searchName, PATH_MAX, nls_codepage,
|
||||
remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -5506,8 +5512,8 @@ SetEOFRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -5796,8 +5802,8 @@ SetTimesRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -5877,8 +5883,8 @@ SetAttrLgcyRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
ConvertToUCS((__le16 *) pSMB->fileName, fileName,
|
||||
PATH_MAX, nls_codepage);
|
||||
ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
|
||||
PATH_MAX, nls_codepage);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -6030,8 +6036,8 @@ setPermsRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -6123,8 +6129,8 @@ QAllEAsRetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
list_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
list_len++; /* trailing null */
|
||||
list_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
@ -6301,8 +6307,8 @@ SetEARetry:
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/module.h>
|
||||
#include <keys/user-type.h>
|
||||
#include <net/ipv6.h>
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB)
|
||||
|
||||
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;
|
||||
char *data_area_of_target;
|
||||
char *data_area_of_buf2;
|
||||
char *data_area_of_tgt;
|
||||
char *data_area_of_src;
|
||||
int remaining;
|
||||
unsigned int byte_count, total_in_buf;
|
||||
__u16 total_data_size, total_in_buf2;
|
||||
unsigned int byte_count, total_in_tgt;
|
||||
__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 !=
|
||||
get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount))
|
||||
cFYI(1, "total data size of primary and secondary t2 differ");
|
||||
if (tgt_total_cnt != src_total_cnt)
|
||||
cFYI(1, "total data count 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;
|
||||
|
||||
if (remaining == 0) /* nothing to do, ignore */
|
||||
return 0;
|
||||
|
||||
total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount);
|
||||
if (remaining < total_in_buf2) {
|
||||
cFYI(1, "transact2 2nd response contains too much data");
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
/* nothing to do, ignore */
|
||||
cFYI(1, "no more data remains");
|
||||
return 0;
|
||||
}
|
||||
|
||||
total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
|
||||
if (remaining < total_in_src)
|
||||
cFYI(1, "transact2 2nd response contains too much data");
|
||||
|
||||
/* 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);
|
||||
|
||||
/* validate target area */
|
||||
data_area_of_src = (char *)&pSMBs->hdr.Protocol +
|
||||
get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
|
||||
|
||||
data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol +
|
||||
get_unaligned_le16(&pSMB2->t2_rsp.DataOffset);
|
||||
data_area_of_tgt += total_in_tgt;
|
||||
|
||||
data_area_of_target += total_in_buf;
|
||||
|
||||
/* copy second buffer into end of first buffer */
|
||||
total_in_buf += total_in_buf2;
|
||||
total_in_tgt += total_in_src;
|
||||
/* 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;
|
||||
put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
|
||||
}
|
||||
put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
|
||||
|
||||
/* fix up the BCC */
|
||||
byte_count = get_bcc(pTargetSMB);
|
||||
byte_count += total_in_buf2;
|
||||
byte_count += total_in_src;
|
||||
/* 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;
|
||||
}
|
||||
put_bcc(byte_count, pTargetSMB);
|
||||
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
cFYI(1, "found the last secondary response");
|
||||
return 0; /* we are done */
|
||||
} else /* more responses to go */
|
||||
if (remaining != total_in_src) {
|
||||
/* more responses to go */
|
||||
cFYI(1, "waiting for more secondary responses");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* we are done */
|
||||
cFYI(1, "found the last secondary response");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1578,11 +1595,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||
}
|
||||
}
|
||||
|
||||
if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
|
||||
cERROR(1, "Multiuser mounts currently require krb5 "
|
||||
"authentication!");
|
||||
#ifndef CONFIG_KEYS
|
||||
/* Muliuser mounts require CONFIG_KEYS support */
|
||||
if (vol->multiuser) {
|
||||
cERROR(1, "Multiuser mounts require kernels with "
|
||||
"CONFIG_KEYS enabled.");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vol->UNCip == NULL)
|
||||
vol->UNCip = &vol->UNC[2];
|
||||
@ -1981,10 +2001,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
/* NULL username means anonymous session */
|
||||
if (ses->user_name == NULL) {
|
||||
if (!vol->nullauth)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* anything else takes username/password */
|
||||
if (ses->user_name == NULL)
|
||||
return 0;
|
||||
if (strncmp(ses->user_name, vol->username,
|
||||
if (strncmp(ses->user_name,
|
||||
vol->username ? vol->username : "",
|
||||
MAX_USERNAME_SIZE))
|
||||
return 0;
|
||||
if (strlen(vol->username) != 0 &&
|
||||
@ -2039,6 +2065,132 @@ cifs_put_smb_ses(struct cifs_ses *ses)
|
||||
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 struct cifs_ses *
|
||||
@ -2914,18 +3066,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
|
||||
#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
|
||||
|
||||
/*
|
||||
* Windows only supports a max of 60k reads. Default to that when posix
|
||||
* extensions aren't in force.
|
||||
* Windows only supports a max of 60kb reads and 65535 byte writes. Default to
|
||||
* 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_WSIZE (65536)
|
||||
|
||||
static unsigned int
|
||||
cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
|
||||
{
|
||||
__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
|
||||
CIFS_DEFAULT_IOSIZE;
|
||||
unsigned int wsize;
|
||||
|
||||
/* 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) */
|
||||
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,
|
||||
return -EINVAL;
|
||||
|
||||
if (volume_info->nullauth) {
|
||||
cFYI(1, "null user");
|
||||
volume_info->username = kzalloc(1, GFP_KERNEL);
|
||||
if (volume_info->username == NULL)
|
||||
return -ENOMEM;
|
||||
cFYI(1, "Anonymous login");
|
||||
kfree(volume_info->username);
|
||||
volume_info->username = NULL;
|
||||
} else if (volume_info->username) {
|
||||
/* BB fixme parse for domain name here */
|
||||
cFYI(1, "Username: %s", volume_info->username);
|
||||
@ -3478,7 +3644,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
|
||||
length =
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, tree,
|
||||
cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
|
||||
6 /* max utf8 char length in bytes */ *
|
||||
(/* server len*/ + 256 /* share len */), nls_codepage);
|
||||
bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
|
||||
@ -3533,7 +3699,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
/* mostly informational -- no need to fail on error here */
|
||||
kfree(tcon->nativeFileSystem);
|
||||
tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
|
||||
tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
|
||||
bytes_left, is_unicode,
|
||||
nls_codepage);
|
||||
|
||||
@ -3657,16 +3823,38 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
|
||||
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 *
|
||||
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_ses *ses;
|
||||
struct cifs_tcon *tcon = NULL;
|
||||
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);
|
||||
if (vol_info == NULL) {
|
||||
@ -3674,8 +3862,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(username, sizeof(username), "krb50x%x", fsuid);
|
||||
vol_info->username = username;
|
||||
vol_info->local_nls = cifs_sb->local_nls;
|
||||
vol_info->linux_uid = fsuid;
|
||||
vol_info->cred_uid = 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->no_linux_ext = !master_tcon->unix_ext;
|
||||
|
||||
/* FIXME: allow for other secFlg settings */
|
||||
vol_info->secFlg = CIFSSEC_MUST_KRB5;
|
||||
rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
|
||||
if (rc) {
|
||||
tcon = ERR_PTR(rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get a reference for the same TCP session */
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
@ -3709,6 +3898,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
|
||||
if (ses->capabilities & CAP_UNIX)
|
||||
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
|
||||
out:
|
||||
kfree(vol_info->username);
|
||||
kfree(vol_info->password);
|
||||
kfree(vol_info);
|
||||
|
||||
return tcon;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user