diff options
-rw-r--r-- | fs/cifs/cifsencrypt.c | 26 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 14 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 7 | ||||
-rw-r--r-- | fs/cifs/transport.c | 4 |
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 | */ |
40 | static int cifs_calc_signature(const struct kvec *iov, int n_vec, | 40 | static 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 */ |
102 | int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | 104 | int 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 | ||
139 | int 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 */ |
138 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | 149 | int 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 | ||
150 | int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, | 161 | int 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 | */ | ||
170 | struct 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 | |||
165 | enum smb_version { | 179 | enum 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 | ||
25 | struct statfs; | 25 | struct statfs; |
26 | struct smb_vol; | 26 | struct smb_vol; |
27 | struct smb_rqst; | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | ***************************************************************** | 30 | ***************************************************************** |
@@ -394,10 +395,12 @@ extern void sesInfoFree(struct cifs_ses *); | |||
394 | extern struct cifs_tcon *tconInfoAlloc(void); | 395 | extern struct cifs_tcon *tconInfoAlloc(void); |
395 | extern void tconInfoFree(struct cifs_tcon *); | 396 | extern void tconInfoFree(struct cifs_tcon *); |
396 | 397 | ||
397 | extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); | 398 | extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, |
399 | __u32 *pexpected_response_sequence_number); | ||
398 | extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *, | 400 | extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *, |
399 | __u32 *); | 401 | __u32 *); |
400 | extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, | 402 | extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); |
403 | extern 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); |
403 | extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *, | 406 | extern 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 = " |