struct mid_q_entry * cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) { int rc; struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct mid_q_entry *mid; if (rqst->rq_iov[0].iov_len != 4 || rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) return ERR_PTR(-EIO); /* enable signing if server requires it */ if (server->sign) hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; mid = AllocMidQEntry(hdr, server); if (mid == NULL) return ERR_PTR(-ENOMEM); rc = cifs_sign_rqst(rqst, server, &mid->sequence_number); if (rc) { DeleteMidQEntry(mid); return ERR_PTR(rc); } return mid; }
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence) { struct smb_rqst rqst = { .rq_iov = iov, .rq_nvec = n_vec }; return cifs_sign_rqst(&rqst, server, pexpected_response_sequence); }
int cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error) { unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; dump_smb(mid->resp_buf, min_t(u32, 92, len)); /* convert the length into a more usable form */ if (server->sign) { struct kvec iov[2]; int rc = 0; struct smb_rqst rqst = { .rq_iov = iov, .rq_nvec = 2 }; iov[0].iov_base = mid->resp_buf; iov[0].iov_len = 4; iov[1].iov_base = (char *)mid->resp_buf + 4; iov[1].iov_len = len - 4; /* FIXME: add code to kill session */ rc = cifs_verify_signature(&rqst, server, mid->sequence_number); if (rc) cifs_dbg(VFS, "SMB signature verification returned error = %d\n", rc); } /* BB special case reconnect tid and uid here? */ return map_smb_to_linux_error(mid->resp_buf, log_error); } struct mid_q_entry * cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) { int rc; struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct mid_q_entry *mid; if (rqst->rq_iov[0].iov_len != 4 || rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) return ERR_PTR(-EIO); rc = allocate_mid(ses, hdr, &mid); if (rc) return ERR_PTR(rc); rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); if (rc) { cifs_delete_mid(mid); return ERR_PTR(rc); } return mid; }
int cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error) { unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; dump_smb(mid->resp_buf, min_t(u32, 92, len)); /* convert the length into a more usable form */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { struct kvec iov; int rc = 0; struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; iov.iov_base = mid->resp_buf; iov.iov_len = len; /* FIXME: add code to kill session */ rc = cifs_verify_signature(&rqst, server, mid->sequence_number + 1); if (rc) cERROR(1, "SMB signature verification returned error = " "%d", rc); } /* BB special case reconnect tid and uid here? */ return map_smb_to_linux_error(mid->resp_buf, log_error); } struct mid_q_entry * cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) { int rc; struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct mid_q_entry *mid; rc = allocate_mid(ses, hdr, &mid); if (rc) return ERR_PTR(rc); rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); if (rc) { cifs_delete_mid(mid); return ERR_PTR(rc); } return mid; }