diff options
Diffstat (limited to 'fs/cifs/smb2pdu.c')
-rw-r--r-- | fs/cifs/smb2pdu.c | 219 |
1 files changed, 12 insertions, 207 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2013234..edccb52 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -454,81 +454,6 @@ neg_exit: return rc; } -int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) -{ - int rc = 0; - struct validate_negotiate_info_req vneg_inbuf; - struct validate_negotiate_info_rsp *pneg_rsp; - u32 rsplen; - - cifs_dbg(FYI, "validate negotiate\n"); - - /* - * validation ioctl must be signed, so no point sending this if we - * can not sign it. We could eventually change this to selectively - * sign just this, the first and only signed request on a connection. - * This is good enough for now since a user who wants better security - * would also enable signing on the mount. Having validation of - * negotiate info for signed connections helps reduce attack vectors - */ - if (tcon->ses->server->sign == false) - return 0; /* validation requires signing */ - - vneg_inbuf.Capabilities = - cpu_to_le32(tcon->ses->server->vals->req_capabilities); - memcpy(vneg_inbuf.Guid, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); - - if (tcon->ses->sign) - vneg_inbuf.SecurityMode = - cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); - else if (global_secflags & CIFSSEC_MAY_SIGN) - vneg_inbuf.SecurityMode = - cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); - else - vneg_inbuf.SecurityMode = 0; - - vneg_inbuf.DialectCount = cpu_to_le16(1); - vneg_inbuf.Dialects[0] = - cpu_to_le16(tcon->ses->server->vals->protocol_id); - - rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, - FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, - (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req), - (char **)&pneg_rsp, &rsplen); - - if (rc != 0) { - cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); - return -EIO; - } - - if (rsplen != sizeof(struct validate_negotiate_info_rsp)) { - cifs_dbg(VFS, "invalid size of protocol negotiate response\n"); - return -EIO; - } - - /* check validate negotiate info response matches what we got earlier */ - if (pneg_rsp->Dialect != - cpu_to_le16(tcon->ses->server->vals->protocol_id)) - goto vneg_out; - - if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) - goto vneg_out; - - /* do not validate server guid because not saved at negprot time yet */ - - if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND | - SMB2_LARGE_FILES) != tcon->ses->server->capabilities) - goto vneg_out; - - /* validate negotiate successful */ - cifs_dbg(FYI, "validate negotiate info successful\n"); - return 0; - -vneg_out: - cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); - return -EIO; -} - int SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *nls_cp) @@ -705,8 +630,6 @@ ssetup_ntlmssp_authenticate: goto ssetup_exit; ses->session_flags = le16_to_cpu(rsp->SessionFlags); - if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) - cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); ssetup_exit: free_rsp_buf(resp_buftype, rsp); @@ -794,14 +717,6 @@ static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code) #define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */) -/* These are similar values to what Windows uses */ -static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon) -{ - tcon->max_chunks = 256; - tcon->max_bytes_chunk = 1048576; - tcon->max_bytes_copy = 16777216; -} - int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, struct cifs_tcon *tcon, const struct nls_table *cp) @@ -903,9 +818,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); - init_copy_chunk_defaults(tcon); - if (tcon->ses->server->ops->validate_negotiate) - rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); + tcon_exit: free_rsp_buf(resp_buftype, rsp); kfree(unc_path); @@ -1224,7 +1137,6 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, cifs_dbg(FYI, "SMB2 IOCTL\n"); - *out_data = NULL; /* zero out returned data len, in case of error */ if (plen) *plen = 0; @@ -1270,38 +1182,19 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, req->Flags = 0; iov[0].iov_base = (char *)req; + /* 4 for rfc1002 length field */ + iov[0].iov_len = get_rfc1002_length(req) + 4; - /* - * If no input data, the size of ioctl struct in - * protocol spec still includes a 1 byte data buffer, - * but if input data passed to ioctl, we do not - * want to double count this, so we do not send - * the dummy one byte of data in iovec[0] if sending - * input data (in iovec[1]). We also must add 4 bytes - * in first iovec to allow for rfc1002 length field. - */ - - if (indatalen) { - iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; - inc_rfc1001_len(req, indatalen - 1); - } else - iov[0].iov_len = get_rfc1002_length(req) + 4; - + if (indatalen) + inc_rfc1001_len(req, indatalen); rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base; - if ((rc != 0) && (rc != -EINVAL)) { + if (rc != 0) { if (tcon) cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); goto ioctl_exit; - } else if (rc == -EINVAL) { - if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) && - (opcode != FSCTL_SRV_COPYCHUNK)) { - if (tcon) - cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); - goto ioctl_exit; - } } /* check if caller wants to look at return data or just return rc */ @@ -1341,33 +1234,6 @@ ioctl_exit: return rc; } -/* - * Individual callers to ioctl worker function follow - */ - -int -SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, - u64 persistent_fid, u64 volatile_fid) -{ - int rc; - char *res_key = NULL; - struct compress_ioctl fsctl_input; - char *ret_data = NULL; - - fsctl_input.CompressionState = - __constant_cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); - - rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, - FSCTL_SET_COMPRESSION, true /* is_fsctl */, - (char *)&fsctl_input /* data input */, - 2 /* in data len */, &ret_data /* out data */, NULL); - - cifs_dbg(FYI, "set compression rc %d\n", rc); - kfree(res_key); - - return rc; -} - int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) @@ -2238,9 +2104,11 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, rc = SendReceive2(xid, ses, iov, num, &resp_buftype, 0); rsp = (struct smb2_set_info_rsp *)iov[0].iov_base; - if (rc != 0) + if (rc != 0) { cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); - + goto out; + } +out: free_rsp_buf(resp_buftype, rsp); kfree(iov); return rc; @@ -2431,7 +2299,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); - goto qfsinf_exit; + goto qinf_exit; } rsp = (struct smb2_query_info_rsp *)iov.iov_base; @@ -2443,70 +2311,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, if (!rc) copy_fs_info_to_kstatfs(info, fsdata); -qfsinf_exit: - free_rsp_buf(resp_buftype, iov.iov_base); - return rc; -} - -int -SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, - u64 persistent_fid, u64 volatile_fid, int level) -{ - struct smb2_query_info_rsp *rsp = NULL; - struct kvec iov; - int rc = 0; - int resp_buftype, max_len, min_len; - struct cifs_ses *ses = tcon->ses; - unsigned int rsp_len, offset; - - if (level == FS_DEVICE_INFORMATION) { - max_len = sizeof(FILE_SYSTEM_DEVICE_INFO); - min_len = sizeof(FILE_SYSTEM_DEVICE_INFO); - } else if (level == FS_ATTRIBUTE_INFORMATION) { - max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO); - min_len = MIN_FS_ATTR_INFO_SIZE; - } else if (level == FS_SECTOR_SIZE_INFORMATION) { - max_len = sizeof(struct smb3_fs_ss_info); - min_len = sizeof(struct smb3_fs_ss_info); - } else { - cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level); - return -EINVAL; - } - - rc = build_qfs_info_req(&iov, tcon, level, max_len, - persistent_fid, volatile_fid); - if (rc) - return rc; - - rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); - if (rc) { - cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); - goto qfsattr_exit; - } - rsp = (struct smb2_query_info_rsp *)iov.iov_base; - - rsp_len = le32_to_cpu(rsp->OutputBufferLength); - offset = le16_to_cpu(rsp->OutputBufferOffset); - rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len); - if (rc) - goto qfsattr_exit; - - if (level == FS_ATTRIBUTE_INFORMATION) - memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset - + (char *)&rsp->hdr, min_t(unsigned int, - rsp_len, max_len)); - else if (level == FS_DEVICE_INFORMATION) - memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset - + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO)); - else if (level == FS_SECTOR_SIZE_INFORMATION) { - struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *) - (4 /* RFC1001 len */ + offset + (char *)&rsp->hdr); - tcon->ss_flags = le32_to_cpu(ss_info->Flags); - tcon->perf_sector_size = - le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); - } - -qfsattr_exit: +qinf_exit: free_rsp_buf(resp_buftype, iov.iov_base); return rc; } |