aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsencrypt.c26
-rw-r--r--fs/cifs/cifsglob.h14
-rw-r--r--fs/cifs/cifsproto.h7
-rw-r--r--fs/cifs/cifssmb.c7
-rw-r--r--fs/cifs/transport.c4
5 files changed, 44 insertions, 14 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 724738c1a560..af520522ef20 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,11 +37,13 @@
37 * the sequence number before this function is called. Also, this function 37 * the sequence number before this function is called. Also, this function
38 * should be called with the server->srv_mutex held. 38 * should be called with the server->srv_mutex held.
39 */ 39 */
40static int cifs_calc_signature(const struct kvec *iov, int n_vec, 40static int cifs_calc_signature(struct smb_rqst *rqst,
41 struct TCP_Server_Info *server, char *signature) 41 struct TCP_Server_Info *server, char *signature)
42{ 42{
43 int i; 43 int i;
44 int rc; 44 int rc;
45 struct kvec *iov = rqst->rq_iov;
46 int n_vec = rqst->rq_nvec;
45 47
46 if (iov == NULL || signature == NULL || server == NULL) 48 if (iov == NULL || signature == NULL || server == NULL)
47 return -EINVAL; 49 return -EINVAL;
@@ -99,12 +101,12 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
99} 101}
100 102
101/* must be called with server->srv_mutex held */ 103/* must be called with server->srv_mutex held */
102int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 104int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
103 __u32 *pexpected_response_sequence_number) 105 __u32 *pexpected_response_sequence_number)
104{ 106{
105 int rc = 0; 107 int rc = 0;
106 char smb_signature[20]; 108 char smb_signature[20];
107 struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; 109 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
108 110
109 if ((cifs_pdu == NULL) || (server == NULL)) 111 if ((cifs_pdu == NULL) || (server == NULL))
110 return -EINVAL; 112 return -EINVAL;
@@ -125,7 +127,7 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
125 *pexpected_response_sequence_number = server->sequence_number++; 127 *pexpected_response_sequence_number = server->sequence_number++;
126 server->sequence_number++; 128 server->sequence_number++;
127 129
128 rc = cifs_calc_signature(iov, n_vec, server, smb_signature); 130 rc = cifs_calc_signature(rqst, server, smb_signature);
129 if (rc) 131 if (rc)
130 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 132 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
131 else 133 else
@@ -134,6 +136,15 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
134 return rc; 136 return rc;
135} 137}
136 138
139int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
140 __u32 *pexpected_response_sequence)
141{
142 struct smb_rqst rqst = { .rq_iov = iov,
143 .rq_nvec = n_vec };
144
145 return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
146}
147
137/* must be called with server->srv_mutex held */ 148/* must be called with server->srv_mutex held */
138int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 149int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
139 __u32 *pexpected_response_sequence_number) 150 __u32 *pexpected_response_sequence_number)
@@ -147,14 +158,14 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
147 pexpected_response_sequence_number); 158 pexpected_response_sequence_number);
148} 159}
149 160
150int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, 161int cifs_verify_signature(struct smb_rqst *rqst,
151 struct TCP_Server_Info *server, 162 struct TCP_Server_Info *server,
152 __u32 expected_sequence_number) 163 __u32 expected_sequence_number)
153{ 164{
154 unsigned int rc; 165 unsigned int rc;
155 char server_response_sig[8]; 166 char server_response_sig[8];
156 char what_we_think_sig_should_be[20]; 167 char what_we_think_sig_should_be[20];
157 struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; 168 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
158 169
159 if (cifs_pdu == NULL || server == NULL) 170 if (cifs_pdu == NULL || server == NULL)
160 return -EINVAL; 171 return -EINVAL;
@@ -186,8 +197,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
186 cifs_pdu->Signature.Sequence.Reserved = 0; 197 cifs_pdu->Signature.Sequence.Reserved = 0;
187 198
188 mutex_lock(&server->srv_mutex); 199 mutex_lock(&server->srv_mutex);
189 rc = cifs_calc_signature(iov, nr_iov, server, 200 rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
190 what_we_think_sig_should_be);
191 mutex_unlock(&server->srv_mutex); 201 mutex_unlock(&server->srv_mutex);
192 202
193 if (rc) 203 if (rc)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 3c007fe641f9..5ea50dd316c5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -162,6 +162,20 @@ struct cifs_cred {
162 ***************************************************************** 162 *****************************************************************
163 */ 163 */
164 164
165/*
166 * A smb_rqst represents a complete request to be issued to a server. It's
167 * formed by a kvec array, followed by an array of pages. Page data is assumed
168 * to start at the beginning of the first page.
169 */
170struct smb_rqst {
171 struct kvec *rq_iov; /* array of kvecs */
172 unsigned int rq_nvec; /* number of kvecs in array */
173 struct page **rq_pages; /* pointer to array of page ptrs */
174 unsigned int rq_npages; /* number pages in array */
175 unsigned int rq_pagesz; /* page size to use */
176 unsigned int rq_tailsz; /* length of last page */
177};
178
165enum smb_version { 179enum smb_version {
166 Smb_1 = 1, 180 Smb_1 = 1,
167 Smb_21, 181 Smb_21,
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c7ad9a8cf82a..8e071a5a7da4 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -24,6 +24,7 @@
24 24
25struct statfs; 25struct statfs;
26struct smb_vol; 26struct smb_vol;
27struct smb_rqst;
27 28
28/* 29/*
29 ***************************************************************** 30 *****************************************************************
@@ -394,10 +395,12 @@ extern void sesInfoFree(struct cifs_ses *);
394extern struct cifs_tcon *tconInfoAlloc(void); 395extern struct cifs_tcon *tconInfoAlloc(void);
395extern void tconInfoFree(struct cifs_tcon *); 396extern void tconInfoFree(struct cifs_tcon *);
396 397
397extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); 398extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
399 __u32 *pexpected_response_sequence_number);
398extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *, 400extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
399 __u32 *); 401 __u32 *);
400extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, 402extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
403extern int cifs_verify_signature(struct smb_rqst *rqst,
401 struct TCP_Server_Info *server, 404 struct TCP_Server_Info *server,
402 __u32 expected_sequence_number); 405 __u32 expected_sequence_number);
403extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *, 406extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c4f43cf671dc..6786b5ee5326 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1541,6 +1541,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
1541 struct cifs_readdata *rdata = mid->callback_data; 1541 struct cifs_readdata *rdata = mid->callback_data;
1542 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 1542 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1543 struct TCP_Server_Info *server = tcon->ses->server; 1543 struct TCP_Server_Info *server = tcon->ses->server;
1544 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1545 .rq_nvec = rdata->nr_iov };
1544 1546
1545 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, 1547 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1546 mid->mid, mid->mid_state, rdata->result, rdata->bytes); 1548 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
@@ -1552,9 +1554,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
1552 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { 1554 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1553 int rc = 0; 1555 int rc = 0;
1554 1556
1555 rc = cifs_verify_signature(rdata->iov, rdata->nr_iov, 1557 rc = cifs_verify_signature(&rqst, server,
1556 server, 1558 mid->sequence_number + 1);
1557 mid->sequence_number + 1);
1558 if (rc) 1559 if (rc)
1559 cERROR(1, "SMB signature verification returned " 1560 cERROR(1, "SMB signature verification returned "
1560 "error = %d", rc); 1561 "error = %d", rc);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index c4d7825dfc0a..bc9ccddad937 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -504,11 +504,13 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
504 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { 504 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
505 struct kvec iov; 505 struct kvec iov;
506 int rc = 0; 506 int rc = 0;
507 struct smb_rqst rqst = { .rq_iov = &iov,
508 .rq_nvec = 1 };
507 509
508 iov.iov_base = mid->resp_buf; 510 iov.iov_base = mid->resp_buf;
509 iov.iov_len = len; 511 iov.iov_len = len;
510 /* FIXME: add code to kill session */ 512 /* FIXME: add code to kill session */
511 rc = cifs_verify_signature(&iov, 1, server, 513 rc = cifs_verify_signature(&rqst, server,
512 mid->sequence_number + 1); 514 mid->sequence_number + 1);
513 if (rc) 515 if (rc)
514 cERROR(1, "SMB signature verification returned error = " 516 cERROR(1, "SMB signature verification returned error = "