Commit 8908c94d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs updates from Steve French:
 "Various small CIFS and SMB3 fixes (including some for stable)"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
  remove directory incorrectly tries to set delete on close on non-empty directories
  Update cifs.ko version to 2.09
  fs/cifs: correctly to anonymous authentication for the NTLM(v2) authentication
  fs/cifs: correctly to anonymous authentication for the NTLM(v1) authentication
  fs/cifs: correctly to anonymous authentication for the LANMAN authentication
  fs/cifs: correctly to anonymous authentication via NTLMSSP
  cifs: remove any preceding delimiter from prefix_path
  cifs: Use file_dentry()
parents 0b7962a6 897fba11
...@@ -151,8 +151,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -151,8 +151,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
if (sb_mountdata == NULL) if (sb_mountdata == NULL)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (strlen(fullpath) - ref->path_consumed) if (strlen(fullpath) - ref->path_consumed) {
prepath = fullpath + ref->path_consumed; prepath = fullpath + ref->path_consumed;
/* skip initial delimiter */
if (*prepath == '/' || *prepath == '\\')
prepath++;
}
*devname = cifs_build_devname(ref->node_name, prepath); *devname = cifs_build_devname(ref->node_name, prepath);
if (IS_ERR(*devname)) { if (IS_ERR(*devname)) {
......
...@@ -134,5 +134,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ...@@ -134,5 +134,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "2.08" #define CIFS_VERSION "2.09"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -1196,8 +1196,12 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol) ...@@ -1196,8 +1196,12 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
convert_delimiter(vol->UNC, '\\'); convert_delimiter(vol->UNC, '\\');
/* If pos is NULL, or is a bogus trailing delimiter then no prepath */ /* skip any delimiter */
if (!*pos++ || !*pos) if (*pos == '/' || *pos == '\\')
pos++;
/* If pos is NULL then no prepath */
if (!*pos)
return 0; return 0;
vol->prepath = kstrdup(pos, GFP_KERNEL); vol->prepath = kstrdup(pos, GFP_KERNEL);
......
...@@ -271,7 +271,7 @@ struct cifsFileInfo * ...@@ -271,7 +271,7 @@ struct cifsFileInfo *
cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
struct tcon_link *tlink, __u32 oplock) struct tcon_link *tlink, __u32 oplock)
{ {
struct dentry *dentry = file->f_path.dentry; struct dentry *dentry = file_dentry(file);
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
struct cifsInodeInfo *cinode = CIFS_I(inode); struct cifsInodeInfo *cinode = CIFS_I(inode);
struct cifsFileInfo *cfile; struct cifsFileInfo *cfile;
...@@ -461,7 +461,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -461,7 +461,7 @@ int cifs_open(struct inode *inode, struct file *file)
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
server = tcon->ses->server; server = tcon->ses->server;
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file_dentry(file));
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
......
...@@ -303,7 +303,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file) ...@@ -303,7 +303,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file)
cifsFile->invalidHandle = true; cifsFile->invalidHandle = true;
cifsFile->srch_inf.endOfSearch = false; cifsFile->srch_inf.endOfSearch = false;
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file_dentry(file));
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto error_exit; goto error_exit;
...@@ -762,7 +762,7 @@ static int cifs_filldir(char *find_entry, struct file *file, ...@@ -762,7 +762,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
*/ */
fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
cifs_prime_dcache(file->f_path.dentry, &name, &fattr); cifs_prime_dcache(file_dentry(file), &name, &fattr);
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
......
...@@ -400,19 +400,27 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -400,19 +400,27 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob->LmChallengeResponse.MaximumLength = 0; sec_blob->LmChallengeResponse.MaximumLength = 0;
sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
rc = setup_ntlmv2_rsp(ses, nls_cp); if (ses->user_name != NULL) {
if (rc) { rc = setup_ntlmv2_rsp(ses, nls_cp);
cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); if (rc) {
goto setup_ntlmv2_ret; cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
goto setup_ntlmv2_ret;
}
memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
ses->auth_key.len - CIFS_SESS_KEY_SIZE);
tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
sec_blob->NtChallengeResponse.Length =
cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
sec_blob->NtChallengeResponse.MaximumLength =
cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
} else {
/*
* don't send an NT Response for anonymous access
*/
sec_blob->NtChallengeResponse.Length = 0;
sec_blob->NtChallengeResponse.MaximumLength = 0;
} }
memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
ses->auth_key.len - CIFS_SESS_KEY_SIZE);
tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
sec_blob->NtChallengeResponse.Length =
cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
sec_blob->NtChallengeResponse.MaximumLength =
cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
if (ses->domainName == NULL) { if (ses->domainName == NULL) {
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
...@@ -670,20 +678,24 @@ sess_auth_lanman(struct sess_data *sess_data) ...@@ -670,20 +678,24 @@ sess_auth_lanman(struct sess_data *sess_data)
pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
/* no capabilities flags in old lanman negotiation */ if (ses->user_name != NULL) {
pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); /* no capabilities flags in old lanman negotiation */
pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
/* Calculate hash with password and copy into bcc_ptr.
* Encryption Key (stored as in cryptkey) gets used if the /* Calculate hash with password and copy into bcc_ptr.
* security mode bit in Negottiate Protocol response states * Encryption Key (stored as in cryptkey) gets used if the
* to use challenge/response method (i.e. Password bit is 1). * security mode bit in Negottiate Protocol response states
*/ * to use challenge/response method (i.e. Password bit is 1).
rc = calc_lanman_hash(ses->password, ses->server->cryptkey, */
ses->server->sec_mode & SECMODE_PW_ENCRYPT ? rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
true : false, lnm_session_key); ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
true : false, lnm_session_key);
memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
bcc_ptr += CIFS_AUTH_RESP_SIZE; memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
bcc_ptr += CIFS_AUTH_RESP_SIZE;
} else {
pSMB->old_req.PasswordLength = 0;
}
/* /*
* can not sign if LANMAN negotiated so no need * can not sign if LANMAN negotiated so no need
...@@ -769,26 +781,31 @@ sess_auth_ntlm(struct sess_data *sess_data) ...@@ -769,26 +781,31 @@ sess_auth_ntlm(struct sess_data *sess_data)
capabilities = cifs_ssetup_hdr(ses, pSMB); capabilities = cifs_ssetup_hdr(ses, pSMB);
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
pSMB->req_no_secext.CaseInsensitivePasswordLength = if (ses->user_name != NULL) {
cpu_to_le16(CIFS_AUTH_RESP_SIZE); pSMB->req_no_secext.CaseInsensitivePasswordLength =
pSMB->req_no_secext.CaseSensitivePasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
cpu_to_le16(CIFS_AUTH_RESP_SIZE); pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_AUTH_RESP_SIZE);
/* calculate ntlm response and session key */
rc = setup_ntlm_response(ses, sess_data->nls_cp); /* calculate ntlm response and session key */
if (rc) { rc = setup_ntlm_response(ses, sess_data->nls_cp);
cifs_dbg(VFS, "Error %d during NTLM authentication\n", if (rc) {
rc); cifs_dbg(VFS, "Error %d during NTLM authentication\n",
goto out; rc);
} goto out;
}
/* copy ntlm response */ /* copy ntlm response */
memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
CIFS_AUTH_RESP_SIZE); CIFS_AUTH_RESP_SIZE);
bcc_ptr += CIFS_AUTH_RESP_SIZE; bcc_ptr += CIFS_AUTH_RESP_SIZE;
memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
CIFS_AUTH_RESP_SIZE); CIFS_AUTH_RESP_SIZE);
bcc_ptr += CIFS_AUTH_RESP_SIZE; bcc_ptr += CIFS_AUTH_RESP_SIZE;
} else {
pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
}
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
/* unicode strings must be word aligned */ /* unicode strings must be word aligned */
...@@ -878,22 +895,26 @@ sess_auth_ntlmv2(struct sess_data *sess_data) ...@@ -878,22 +895,26 @@ sess_auth_ntlmv2(struct sess_data *sess_data)
/* LM2 password would be here if we supported it */ /* LM2 password would be here if we supported it */
pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
/* calculate nlmv2 response and session key */ if (ses->user_name != NULL) {
rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp); /* calculate nlmv2 response and session key */
if (rc) { rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc); if (rc) {
goto out; cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
} goto out;
}
memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
ses->auth_key.len - CIFS_SESS_KEY_SIZE); ses->auth_key.len - CIFS_SESS_KEY_SIZE);
bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
/* set case sensitive password length after tilen may get /* set case sensitive password length after tilen may get
* assigned, tilen is 0 otherwise. * assigned, tilen is 0 otherwise.
*/ */
pSMB->req_no_secext.CaseSensitivePasswordLength = pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
} else {
pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
}
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
if (sess_data->iov[0].iov_len % 2) { if (sess_data->iov[0].iov_len % 2) {
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define SMB2_OP_DELETE 7 #define SMB2_OP_DELETE 7
#define SMB2_OP_HARDLINK 8 #define SMB2_OP_HARDLINK 8
#define SMB2_OP_SET_EOF 9 #define SMB2_OP_SET_EOF 9
#define SMB2_OP_RMDIR 10
/* Used when constructing chained read requests. */ /* Used when constructing chained read requests. */
#define CHAINED_REQUEST 1 #define CHAINED_REQUEST 1
......
...@@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
* SMB2_open() call. * SMB2_open() call.
*/ */
break; break;
case SMB2_OP_RMDIR:
tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
fid.volatile_fid);
break;
case SMB2_OP_RENAME: case SMB2_OP_RENAME:
tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
fid.volatile_fid, (__le16 *)data); fid.volatile_fid, (__le16 *)data);
...@@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, ...@@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *cifs_sb) struct cifs_sb_info *cifs_sb)
{ {
return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, CREATE_NOT_FILE,
NULL, SMB2_OP_DELETE); NULL, SMB2_OP_RMDIR);
} }
int int
......
...@@ -2574,6 +2574,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2574,6 +2574,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
return rc; return rc;
} }
int
SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid)
{
__u8 delete_pending = 1;
void *data;
unsigned int size;
data = &delete_pending;
size = 1; /* sizeof __u8 */
return send_set_info(xid, tcon, persistent_fid, volatile_fid,
current->tgid, FILE_DISPOSITION_INFORMATION, 1, &data,
&size);
}
int int
SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, __le16 *target_file) u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
......
...@@ -141,6 +141,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -141,6 +141,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u64 persistent_fid, u64 volatile_fid,
__le16 *target_file); __le16 *target_file);
extern int SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid);
extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u64 persistent_fid, u64 volatile_fid,
__le16 *target_file); __le16 *target_file);
......
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