mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: Cleanup: check return codes of crypto api calls CIFS: Fix oops while mounting with prefixpath [CIFS] Redundant null check after dereference cifs: use cifs_dirent in cifs_save_resume_key cifs: use cifs_dirent to replace cifs_get_name_from_search_buf cifs: introduce cifs_dirent cifs: cleanup cifs_filldir
This commit is contained in:
commit
1d87c28e68
@ -52,19 +52,29 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
||||
|
||||
rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Oould not init md5\n", __func__);
|
||||
cERROR(1, "%s: Could not init md5\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
server->session_key.response, server->session_key.len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with payload\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* must be called with server->srv_mutex held */
|
||||
@ -112,12 +122,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
||||
|
||||
rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Oould not init md5\n", __func__);
|
||||
cERROR(1, "%s: Could not init md5\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
server->session_key.response, server->session_key.len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_vec; i++) {
|
||||
if (iov[i].iov_len == 0)
|
||||
@ -131,14 +145,24 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
||||
if (i == 0) {
|
||||
if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
|
||||
break; /* nothing to sign or corrupt header */
|
||||
rc =
|
||||
crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
iov[i].iov_base + 4, iov[i].iov_len - 4);
|
||||
} else
|
||||
} else {
|
||||
rc =
|
||||
crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with payload\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -463,8 +487,12 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
/* calculate md4 hash of password */
|
||||
E_md4hash(ses->password, nt_hash);
|
||||
|
||||
crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
|
||||
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
|
||||
CIFS_NTHASH_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not set NT Hash as a key", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
@ -478,13 +506,18 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
if (user == NULL) {
|
||||
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
|
||||
rc = -ENOMEM;
|
||||
goto calc_exit_2;
|
||||
return rc;
|
||||
}
|
||||
len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
|
||||
UniStrupr(user);
|
||||
|
||||
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
(char *)user, 2 * len);
|
||||
kfree(user);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with user\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* convert ses->domainName to unicode and uppercase */
|
||||
if (ses->domainName) {
|
||||
@ -494,13 +527,19 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
if (domain == NULL) {
|
||||
cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
|
||||
rc = -ENOMEM;
|
||||
goto calc_exit_1;
|
||||
return rc;
|
||||
}
|
||||
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
|
||||
nls_cp);
|
||||
rc =
|
||||
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
(char *)domain, 2 * len);
|
||||
kfree(domain);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with domain\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
} else if (ses->serverName) {
|
||||
len = strlen(ses->serverName);
|
||||
|
||||
@ -508,21 +547,26 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
if (server == NULL) {
|
||||
cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
|
||||
rc = -ENOMEM;
|
||||
goto calc_exit_1;
|
||||
return rc;
|
||||
}
|
||||
len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
|
||||
nls_cp);
|
||||
rc =
|
||||
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
(char *)server, 2 * len);
|
||||
kfree(server);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with server\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ntlmv2_hash);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
|
||||
calc_exit_1:
|
||||
kfree(user);
|
||||
calc_exit_2:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -537,8 +581,12 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
|
||||
return -1;
|
||||
}
|
||||
|
||||
crypto_shash_setkey(ses->server->secmech.hmacmd5,
|
||||
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
|
||||
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
@ -552,11 +600,17 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
|
||||
else
|
||||
memcpy(ses->auth_key.response + offset,
|
||||
ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
|
||||
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response + offset, ses->auth_key.len - offset);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response + CIFS_SESS_KEY_SIZE);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -626,8 +680,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
||||
}
|
||||
|
||||
/* now calculate the session key for NTLMv2 */
|
||||
crypto_shash_setkey(ses->server->secmech.hmacmd5,
|
||||
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
|
||||
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
@ -635,12 +693,18 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
|
||||
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response + CIFS_SESS_KEY_SIZE,
|
||||
CIFS_HMAC_MD5_HASH_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
|
||||
setup_ntlmv2_rsp_ret:
|
||||
kfree(tiblob);
|
||||
@ -668,8 +732,12 @@ calc_seckey(struct cifs_ses *ses)
|
||||
|
||||
desc.tfm = tfm_arc4;
|
||||
|
||||
crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
|
||||
rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
|
||||
CIFS_SESS_KEY_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not set response as a key", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
|
||||
sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
|
||||
@ -688,7 +756,7 @@ calc_seckey(struct cifs_ses *ses)
|
||||
|
||||
crypto_free_blkcipher(tfm_arc4);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -501,7 +501,7 @@ struct cifs_search_info {
|
||||
char *ntwrk_buf_start;
|
||||
char *srch_entries_start;
|
||||
char *last_entry;
|
||||
char *presume_name;
|
||||
const char *presume_name;
|
||||
unsigned int resume_name_len;
|
||||
bool endOfSearch:1;
|
||||
bool emptyDir:1;
|
||||
|
@ -57,11 +57,6 @@ build_path_from_dentry(struct dentry *direntry)
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
unsigned seq;
|
||||
|
||||
if (direntry == NULL)
|
||||
return NULL; /* not much we can do if dentry is freed and
|
||||
we need to reopen the file after it was closed implicitly
|
||||
when the server crashed */
|
||||
|
||||
dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
|
||||
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
|
@ -74,8 +74,14 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
|
||||
cERROR(1, "%s: Could not init md5 shash\n", __func__);
|
||||
goto symlink_hash_err;
|
||||
}
|
||||
crypto_shash_update(&sdescmd5->shash, link_str, link_len);
|
||||
rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update iwth link_str\n", __func__);
|
||||
goto symlink_hash_err;
|
||||
}
|
||||
rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
|
||||
symlink_hash_err:
|
||||
crypto_free_shash(md5);
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Directory search handling
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2004, 2008
|
||||
* Copyright (C) Red Hat, Inc., 2011
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
@ -290,10 +291,10 @@ error_exit:
|
||||
}
|
||||
|
||||
/* return length of unicode string in bytes */
|
||||
static int cifs_unicode_bytelen(char *str)
|
||||
static int cifs_unicode_bytelen(const char *str)
|
||||
{
|
||||
int len;
|
||||
__le16 *ustr = (__le16 *)str;
|
||||
const __le16 *ustr = (const __le16 *)str;
|
||||
|
||||
for (len = 0; len <= PATH_MAX; len++) {
|
||||
if (ustr[len] == 0)
|
||||
@ -334,78 +335,128 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||
|
||||
}
|
||||
|
||||
struct cifs_dirent {
|
||||
const char *name;
|
||||
size_t namelen;
|
||||
u32 resume_key;
|
||||
u64 ino;
|
||||
};
|
||||
|
||||
static void cifs_fill_dirent_unix(struct cifs_dirent *de,
|
||||
const FILE_UNIX_INFO *info, bool is_unicode)
|
||||
{
|
||||
de->name = &info->FileName[0];
|
||||
if (is_unicode)
|
||||
de->namelen = cifs_unicode_bytelen(de->name);
|
||||
else
|
||||
de->namelen = strnlen(de->name, PATH_MAX);
|
||||
de->resume_key = info->ResumeKey;
|
||||
de->ino = le64_to_cpu(info->basic.UniqueId);
|
||||
}
|
||||
|
||||
static void cifs_fill_dirent_dir(struct cifs_dirent *de,
|
||||
const FILE_DIRECTORY_INFO *info)
|
||||
{
|
||||
de->name = &info->FileName[0];
|
||||
de->namelen = le32_to_cpu(info->FileNameLength);
|
||||
de->resume_key = info->FileIndex;
|
||||
}
|
||||
|
||||
static void cifs_fill_dirent_full(struct cifs_dirent *de,
|
||||
const FILE_FULL_DIRECTORY_INFO *info)
|
||||
{
|
||||
de->name = &info->FileName[0];
|
||||
de->namelen = le32_to_cpu(info->FileNameLength);
|
||||
de->resume_key = info->FileIndex;
|
||||
}
|
||||
|
||||
static void cifs_fill_dirent_search(struct cifs_dirent *de,
|
||||
const SEARCH_ID_FULL_DIR_INFO *info)
|
||||
{
|
||||
de->name = &info->FileName[0];
|
||||
de->namelen = le32_to_cpu(info->FileNameLength);
|
||||
de->resume_key = info->FileIndex;
|
||||
de->ino = le64_to_cpu(info->UniqueId);
|
||||
}
|
||||
|
||||
static void cifs_fill_dirent_both(struct cifs_dirent *de,
|
||||
const FILE_BOTH_DIRECTORY_INFO *info)
|
||||
{
|
||||
de->name = &info->FileName[0];
|
||||
de->namelen = le32_to_cpu(info->FileNameLength);
|
||||
de->resume_key = info->FileIndex;
|
||||
}
|
||||
|
||||
static void cifs_fill_dirent_std(struct cifs_dirent *de,
|
||||
const FIND_FILE_STANDARD_INFO *info)
|
||||
{
|
||||
de->name = &info->FileName[0];
|
||||
/* one byte length, no endianess conversion */
|
||||
de->namelen = info->FileNameLength;
|
||||
de->resume_key = info->ResumeKey;
|
||||
}
|
||||
|
||||
static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
|
||||
u16 level, bool is_unicode)
|
||||
{
|
||||
memset(de, 0, sizeof(*de));
|
||||
|
||||
switch (level) {
|
||||
case SMB_FIND_FILE_UNIX:
|
||||
cifs_fill_dirent_unix(de, info, is_unicode);
|
||||
break;
|
||||
case SMB_FIND_FILE_DIRECTORY_INFO:
|
||||
cifs_fill_dirent_dir(de, info);
|
||||
break;
|
||||
case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
|
||||
cifs_fill_dirent_full(de, info);
|
||||
break;
|
||||
case SMB_FIND_FILE_ID_FULL_DIR_INFO:
|
||||
cifs_fill_dirent_search(de, info);
|
||||
break;
|
||||
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
|
||||
cifs_fill_dirent_both(de, info);
|
||||
break;
|
||||
case SMB_FIND_FILE_INFO_STANDARD:
|
||||
cifs_fill_dirent_std(de, info);
|
||||
break;
|
||||
default:
|
||||
cFYI(1, "Unknown findfirst level %d", level);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define UNICODE_DOT cpu_to_le16(0x2e)
|
||||
|
||||
/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
|
||||
static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||
static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
|
||||
{
|
||||
int rc = 0;
|
||||
char *filename = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
if (cfile->srch_inf.unicode) {
|
||||
len = cifs_unicode_bytelen(filename);
|
||||
} else {
|
||||
/* BB should we make this strnlen of PATH_MAX? */
|
||||
len = strnlen(filename, 5);
|
||||
if (!de->name)
|
||||
return 0;
|
||||
|
||||
if (is_unicode) {
|
||||
__le16 *ufilename = (__le16 *)de->name;
|
||||
if (de->namelen == 2) {
|
||||
/* check for . */
|
||||
if (ufilename[0] == UNICODE_DOT)
|
||||
rc = 1;
|
||||
} else if (de->namelen == 4) {
|
||||
/* check for .. */
|
||||
if (ufilename[0] == UNICODE_DOT &&
|
||||
ufilename[1] == UNICODE_DOT)
|
||||
rc = 2;
|
||||
}
|
||||
} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO *pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO *pFindData =
|
||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = pFindData->FileNameLength;
|
||||
} else {
|
||||
cFYI(1, "Unknown findfirst level %d",
|
||||
cfile->srch_inf.info_level);
|
||||
}
|
||||
|
||||
if (filename) {
|
||||
if (cfile->srch_inf.unicode) {
|
||||
__le16 *ufilename = (__le16 *)filename;
|
||||
if (len == 2) {
|
||||
/* check for . */
|
||||
if (ufilename[0] == UNICODE_DOT)
|
||||
rc = 1;
|
||||
} else if (len == 4) {
|
||||
/* check for .. */
|
||||
if ((ufilename[0] == UNICODE_DOT)
|
||||
&& (ufilename[1] == UNICODE_DOT))
|
||||
rc = 2;
|
||||
}
|
||||
} else /* ASCII */ {
|
||||
if (len == 1) {
|
||||
if (filename[0] == '.')
|
||||
rc = 1;
|
||||
} else if (len == 2) {
|
||||
if ((filename[0] == '.') && (filename[1] == '.'))
|
||||
rc = 2;
|
||||
}
|
||||
} else /* ASCII */ {
|
||||
if (de->namelen == 1) {
|
||||
if (de->name[0] == '.')
|
||||
rc = 1;
|
||||
} else if (de->namelen == 2) {
|
||||
if (de->name[0] == '.' && de->name[1] == '.')
|
||||
rc = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,66 +478,18 @@ static int is_dir_changed(struct file *file)
|
||||
}
|
||||
|
||||
static int cifs_save_resume_key(const char *current_entry,
|
||||
struct cifsFileInfo *cifsFile)
|
||||
struct cifsFileInfo *file_info)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int len = 0;
|
||||
__u16 level;
|
||||
char *filename;
|
||||
struct cifs_dirent de;
|
||||
int rc;
|
||||
|
||||
if ((cifsFile == NULL) || (current_entry == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
level = cifsFile->srch_inf.info_level;
|
||||
|
||||
if (level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
|
||||
filename = &pFindData->FileName[0];
|
||||
if (cifsFile->srch_inf.unicode) {
|
||||
len = cifs_unicode_bytelen(filename);
|
||||
} else {
|
||||
/* BB should we make this strnlen of PATH_MAX? */
|
||||
len = strnlen(filename, PATH_MAX);
|
||||
}
|
||||
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
||||
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO *pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO *pFindData =
|
||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
/* one byte length, no name conversion */
|
||||
len = (unsigned int)pFindData->FileNameLength;
|
||||
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
||||
} else {
|
||||
cFYI(1, "Unknown findfirst level %d", level);
|
||||
return -EINVAL;
|
||||
rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
|
||||
file_info->srch_inf.unicode);
|
||||
if (!rc) {
|
||||
file_info->srch_inf.presume_name = de.name;
|
||||
file_info->srch_inf.resume_name_len = de.namelen;
|
||||
file_info->srch_inf.resume_key = de.resume_key;
|
||||
}
|
||||
cifsFile->srch_inf.resume_name_len = len;
|
||||
cifsFile->srch_inf.presume_name = filename;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -605,136 +608,70 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* inode num, inode type and filename returned */
|
||||
static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
||||
char *current_entry, __u16 level, unsigned int unicode,
|
||||
struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
|
||||
static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
|
||||
void *dirent, char *scratch_buf, unsigned int max_len)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int len = 0;
|
||||
char *filename;
|
||||
struct nls_table *nlt = cifs_sb->local_nls;
|
||||
|
||||
*pinum = 0;
|
||||
|
||||
if (level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
|
||||
filename = &pFindData->FileName[0];
|
||||
if (unicode) {
|
||||
len = cifs_unicode_bytelen(filename);
|
||||
} else {
|
||||
/* BB should we make this strnlen of PATH_MAX? */
|
||||
len = strnlen(filename, PATH_MAX);
|
||||
}
|
||||
|
||||
*pinum = le64_to_cpu(pFindData->basic.UniqueId);
|
||||
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO *pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
*pinum = le64_to_cpu(pFindData->UniqueId);
|
||||
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO *pFindData =
|
||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
/* one byte length, no name conversion */
|
||||
len = (unsigned int)pFindData->FileNameLength;
|
||||
} else {
|
||||
cFYI(1, "Unknown findfirst level %d", level);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len > max_len) {
|
||||
cERROR(1, "bad search response length %d past smb end", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unicode) {
|
||||
pqst->len = cifs_from_ucs2((char *) pqst->name,
|
||||
(__le16 *) filename,
|
||||
UNICODE_NAME_MAX,
|
||||
min(len, max_len), nlt,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
pqst->len -= nls_nullsize(nlt);
|
||||
} else {
|
||||
pqst->name = filename;
|
||||
pqst->len = len;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
|
||||
void *direntry, char *scratch_buf, unsigned int max_len)
|
||||
{
|
||||
int rc = 0;
|
||||
struct qstr qstring;
|
||||
struct cifsFileInfo *pCifsF;
|
||||
u64 inum;
|
||||
ino_t ino;
|
||||
struct super_block *sb;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct dentry *tmp_dentry;
|
||||
struct cifsFileInfo *file_info = file->private_data;
|
||||
struct super_block *sb = file->f_path.dentry->d_sb;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_dirent de = { NULL, };
|
||||
struct cifs_fattr fattr;
|
||||
struct dentry *dentry;
|
||||
struct qstr name;
|
||||
int rc = 0;
|
||||
ino_t ino;
|
||||
|
||||
/* get filename and len into qstring */
|
||||
/* get dentry */
|
||||
/* decide whether to create and populate ionde */
|
||||
if ((direntry == NULL) || (file == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
pCifsF = file->private_data;
|
||||
|
||||
if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
|
||||
return -ENOENT;
|
||||
|
||||
rc = cifs_entry_is_dot(pfindEntry, pCifsF);
|
||||
/* skip . and .. since we added them first */
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
|
||||
sb = file->f_path.dentry->d_sb;
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
|
||||
qstring.name = scratch_buf;
|
||||
rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
|
||||
pCifsF->srch_inf.info_level,
|
||||
pCifsF->srch_inf.unicode, cifs_sb,
|
||||
max_len, &inum /* returned */);
|
||||
|
||||
rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
|
||||
file_info->srch_inf.unicode);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
|
||||
cifs_unix_basic_to_fattr(&fattr,
|
||||
&((FILE_UNIX_INFO *) pfindEntry)->basic,
|
||||
cifs_sb);
|
||||
else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
|
||||
cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
|
||||
pfindEntry, cifs_sb);
|
||||
else
|
||||
cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
|
||||
pfindEntry, cifs_sb);
|
||||
if (de.namelen > max_len) {
|
||||
cERROR(1, "bad search response length %zd past smb end",
|
||||
de.namelen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
fattr.cf_uniqueid = inum;
|
||||
/* skip . and .. since we added them first */
|
||||
if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
|
||||
return 0;
|
||||
|
||||
if (file_info->srch_inf.unicode) {
|
||||
struct nls_table *nlt = cifs_sb->local_nls;
|
||||
|
||||
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_MOUNT_MAP_SPECIAL_CHR);
|
||||
name.len -= nls_nullsize(nlt);
|
||||
} else {
|
||||
name.name = de.name;
|
||||
name.len = de.namelen;
|
||||
}
|
||||
|
||||
switch (file_info->srch_inf.info_level) {
|
||||
case SMB_FIND_FILE_UNIX:
|
||||
cifs_unix_basic_to_fattr(&fattr,
|
||||
&((FILE_UNIX_INFO *)find_entry)->basic,
|
||||
cifs_sb);
|
||||
break;
|
||||
case SMB_FIND_FILE_INFO_STANDARD:
|
||||
cifs_std_info_to_fattr(&fattr,
|
||||
(FIND_FILE_STANDARD_INFO *)find_entry,
|
||||
cifs_sb);
|
||||
break;
|
||||
default:
|
||||
cifs_dir_info_to_fattr(&fattr,
|
||||
(FILE_DIRECTORY_INFO *)find_entry,
|
||||
cifs_sb);
|
||||
break;
|
||||
}
|
||||
|
||||
if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
fattr.cf_uniqueid = de.ino;
|
||||
} else {
|
||||
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
||||
cifs_autodisable_serverino(cifs_sb);
|
||||
@ -750,12 +687,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
|
||||
fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
|
||||
|
||||
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
|
||||
tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
|
||||
dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr);
|
||||
|
||||
rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
|
||||
ino, fattr.cf_dtype);
|
||||
rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
|
||||
fattr.cf_dtype);
|
||||
|
||||
dput(tmp_dentry);
|
||||
dput(dentry);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -157,8 +157,14 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
|
||||
cERROR(1, "%s: Could not init md4 shash\n", __func__);
|
||||
goto mdfour_err;
|
||||
}
|
||||
crypto_shash_update(&sdescmd4->shash, link_str, link_len);
|
||||
rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with link_str\n", __func__);
|
||||
goto mdfour_err;
|
||||
}
|
||||
rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not genereate md4 hash\n", __func__);
|
||||
|
||||
mdfour_err:
|
||||
crypto_free_shash(md4);
|
||||
|
Loading…
Reference in New Issue
Block a user