diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 94f2c8a9ae6d274202c9625fd88bdb73f7156190..ec9dbbcca3b9031c9aa26aee7468d9123a39a320 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -151,8 +151,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata, if (sb_mountdata == NULL) return ERR_PTR(-EINVAL); - if (strlen(fullpath) - ref->path_consumed) + if (strlen(fullpath) - ref->path_consumed) { prepath = fullpath + ref->path_consumed; + /* skip initial delimiter */ + if (*prepath == '/' || *prepath == '\\') + prepath++; + } *devname = cifs_build_devname(ref->node_name, prepath); if (IS_ERR(*devname)) { diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index c1e749af749b26b5624cd5f82b818db7e1ab68b5..9dcf974acc47f657ce5da39804bf7f887aeafc31 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -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; #endif /* CONFIG_CIFS_NFSD_EXPORT */ -#define CIFS_VERSION "2.08" +#define CIFS_VERSION "2.09" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2e2e0a6242d6ea268ded63f8b862c8b45e1a0d22..1bb258af1648e660c9bc054e49adea202f9136aa 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1196,8 +1196,12 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol) convert_delimiter(vol->UNC, '\\'); - /* If pos is NULL, or is a bogus trailing delimiter then no prepath */ - if (!*pos++ || !*pos) + /* skip any delimiter */ + if (*pos == '/' || *pos == '\\') + pos++; + + /* If pos is NULL then no prepath */ + if (!*pos) return 0; vol->prepath = kstrdup(pos, GFP_KERNEL); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9b51d4936a292e7fda96998f11635387cf567ee6..f3a90298dfe2108a8540937c5bfedb100f29c1e9 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -271,7 +271,7 @@ struct cifsFileInfo * cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, 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 cifsInodeInfo *cinode = CIFS_I(inode); struct cifsFileInfo *cfile; @@ -461,7 +461,7 @@ int cifs_open(struct inode *inode, struct file *file) tcon = tlink_tcon(tlink); 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) { rc = -ENOMEM; goto out; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 867439c2100173aa706298f0c59a959dcdc6c78a..65cf85dcda09bd773886c8aa6a86d82af1a033b5 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -303,7 +303,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file) cifsFile->invalidHandle = true; 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) { rc = -ENOMEM; goto error_exit; @@ -762,7 +762,7 @@ static int cifs_filldir(char *find_entry, struct file *file, */ 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); return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 59727e32ed0f68871785b17b0df0f41bf9e4f378..af0ec2d5ad0e9da25af4ec8528266451a42cc8b5 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -400,19 +400,27 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, sec_blob->LmChallengeResponse.MaximumLength = 0; sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); - rc = setup_ntlmv2_rsp(ses, nls_cp); - if (rc) { - cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); - goto setup_ntlmv2_ret; + if (ses->user_name != NULL) { + rc = setup_ntlmv2_rsp(ses, nls_cp); + if (rc) { + 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) { sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); @@ -670,20 +678,24 @@ sess_auth_lanman(struct sess_data *sess_data) pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; - /* 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 - * 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 ? - true : false, lnm_session_key); - - memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; + if (ses->user_name != NULL) { + /* 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 + * 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 ? + true : false, lnm_session_key); + + 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 @@ -769,26 +781,31 @@ sess_auth_ntlm(struct sess_data *sess_data) capabilities = cifs_ssetup_hdr(ses, pSMB); pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - pSMB->req_no_secext.CaseInsensitivePasswordLength = - 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); - if (rc) { - cifs_dbg(VFS, "Error %d during NTLM authentication\n", - rc); - goto out; - } + if (ses->user_name != NULL) { + pSMB->req_no_secext.CaseInsensitivePasswordLength = + 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); + if (rc) { + cifs_dbg(VFS, "Error %d during NTLM authentication\n", + rc); + goto out; + } - /* copy ntlm response */ - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; + /* copy ntlm response */ + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + CIFS_AUTH_RESP_SIZE); + bcc_ptr += CIFS_AUTH_RESP_SIZE; + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + 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) { /* unicode strings must be word aligned */ @@ -878,22 +895,26 @@ sess_auth_ntlmv2(struct sess_data *sess_data) /* LM2 password would be here if we supported it */ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; - /* calculate nlmv2 response and session key */ - rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp); - if (rc) { - cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc); - goto out; - } + if (ses->user_name != NULL) { + /* calculate nlmv2 response and session key */ + rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp); + if (rc) { + cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc); + goto out; + } - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - ses->auth_key.len - CIFS_SESS_KEY_SIZE); - bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + 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 - * assigned, tilen is 0 otherwise. - */ - pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); + /* set case sensitive password length after tilen may get + * assigned, tilen is 0 otherwise. + */ + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); + } else { + pSMB->req_no_secext.CaseSensitivePasswordLength = 0; + } if (ses->capabilities & CAP_UNICODE) { if (sess_data->iov[0].iov_len % 2) { diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index bc0bb9c34f72aaef62383760a06fa55c72d5b70b..0ffa180943357c5514b5ae025f61e4b19f574f38 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h @@ -44,6 +44,7 @@ #define SMB2_OP_DELETE 7 #define SMB2_OP_HARDLINK 8 #define SMB2_OP_SET_EOF 9 +#define SMB2_OP_RMDIR 10 /* Used when constructing chained read requests. */ #define CHAINED_REQUEST 1 diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 899bbc86f73e1416aafcd00708052c22bd87f52e..4f0231e685a922efcb97a6c5905bfedc7ca7ece6 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, * SMB2_open() call. */ break; + case SMB2_OP_RMDIR: + tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid, + fid.volatile_fid); + break; case SMB2_OP_RENAME: tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, fid.volatile_fid, (__le16 *)data); @@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb) { return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, - CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, - NULL, SMB2_OP_DELETE); + CREATE_NOT_FILE, + NULL, SMB2_OP_RMDIR); } int diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 42e1f440eb1e9ae1ca497c7f8127ff58b7988b77..8f38e33d365bcca5ce9079dc64e5d10525df801c 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2574,6 +2574,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, 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 SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, __le16 *target_file) diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 4f07dc93608db3fc8723f53d86219087b7cc76c8..eb2cde2f64ba7c818c5ea0db10dd8cb192d94c67 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -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, u64 persistent_fid, u64 volatile_fid, __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, u64 persistent_fid, u64 volatile_fid, __le16 *target_file);