aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsencrypt.c103
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/transport.c11
3 files changed, 30 insertions, 86 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 12f1c1263013..2cfb695d1f89 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,83 +37,8 @@
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_calculate_signature(const struct smb_hdr *cifs_pdu, 40static int cifs_calc_signature(const struct kvec *iov, int n_vec,
41 struct TCP_Server_Info *server, char *signature) 41 struct TCP_Server_Info *server, char *signature)
42{
43 int rc;
44
45 if (cifs_pdu == NULL || signature == NULL || server == NULL)
46 return -EINVAL;
47
48 if (!server->secmech.sdescmd5) {
49 cERROR(1, "%s: Can't generate signature\n", __func__);
50 return -1;
51 }
52
53 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
54 if (rc) {
55 cERROR(1, "%s: Could not init md5\n", __func__);
56 return rc;
57 }
58
59 rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
60 server->session_key.response, server->session_key.len);
61 if (rc) {
62 cERROR(1, "%s: Could not update with response\n", __func__);
63 return rc;
64 }
65
66 rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
67 cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
68 if (rc) {
69 cERROR(1, "%s: Could not update with payload\n", __func__);
70 return rc;
71 }
72
73 rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
74 if (rc)
75 cERROR(1, "%s: Could not generate md5 hash\n", __func__);
76
77 return rc;
78}
79
80/* must be called with server->srv_mutex held */
81int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
82 __u32 *pexpected_response_sequence_number)
83{
84 int rc = 0;
85 char smb_signature[20];
86
87 if ((cifs_pdu == NULL) || (server == NULL))
88 return -EINVAL;
89
90 if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
91 server->tcpStatus == CifsNeedNegotiate)
92 return rc;
93
94 if (!server->session_estab) {
95 memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
96 return rc;
97 }
98
99 cifs_pdu->Signature.Sequence.SequenceNumber =
100 cpu_to_le32(server->sequence_number);
101 cifs_pdu->Signature.Sequence.Reserved = 0;
102
103 *pexpected_response_sequence_number = server->sequence_number++;
104 server->sequence_number++;
105
106 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
107 if (rc)
108 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
109 else
110 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
111
112 return rc;
113}
114
115static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
116 struct TCP_Server_Info *server, char *signature)
117{ 42{
118 int i; 43 int i;
119 int rc; 44 int rc;
@@ -179,7 +104,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
179{ 104{
180 int rc = 0; 105 int rc = 0;
181 char smb_signature[20]; 106 char smb_signature[20];
182 struct smb_hdr *cifs_pdu = iov[0].iov_base; 107 struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
183 108
184 if ((cifs_pdu == NULL) || (server == NULL)) 109 if ((cifs_pdu == NULL) || (server == NULL))
185 return -EINVAL; 110 return -EINVAL;
@@ -200,7 +125,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
200 *pexpected_response_sequence_number = server->sequence_number++; 125 *pexpected_response_sequence_number = server->sequence_number++;
201 server->sequence_number++; 126 server->sequence_number++;
202 127
203 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); 128 rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
204 if (rc) 129 if (rc)
205 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 130 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
206 else 131 else
@@ -209,13 +134,27 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
209 return rc; 134 return rc;
210} 135}
211 136
212int cifs_verify_signature(struct smb_hdr *cifs_pdu, 137/* must be called with server->srv_mutex held */
138int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
139 __u32 *pexpected_response_sequence_number)
140{
141 struct kvec iov;
142
143 iov.iov_base = cifs_pdu;
144 iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
145
146 return cifs_sign_smb2(&iov, 1, server,
147 pexpected_response_sequence_number);
148}
149
150int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
213 struct TCP_Server_Info *server, 151 struct TCP_Server_Info *server,
214 __u32 expected_sequence_number) 152 __u32 expected_sequence_number)
215{ 153{
216 unsigned int rc; 154 unsigned int rc;
217 char server_response_sig[8]; 155 char server_response_sig[8];
218 char what_we_think_sig_should_be[20]; 156 char what_we_think_sig_should_be[20];
157 struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
219 158
220 if (cifs_pdu == NULL || server == NULL) 159 if (cifs_pdu == NULL || server == NULL)
221 return -EINVAL; 160 return -EINVAL;
@@ -247,8 +186,8 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
247 cifs_pdu->Signature.Sequence.Reserved = 0; 186 cifs_pdu->Signature.Sequence.Reserved = 0;
248 187
249 mutex_lock(&server->srv_mutex); 188 mutex_lock(&server->srv_mutex);
250 rc = cifs_calculate_signature(cifs_pdu, server, 189 rc = cifs_calc_signature(iov, nr_iov, server,
251 what_we_think_sig_should_be); 190 what_we_think_sig_should_be);
252 mutex_unlock(&server->srv_mutex); 191 mutex_unlock(&server->srv_mutex);
253 192
254 if (rc) 193 if (rc)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 8df28e925e5b..03dc945d94a3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -380,7 +380,7 @@ extern void tconInfoFree(struct cifs_tcon *);
380extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); 380extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
381extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, 381extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
382 __u32 *); 382 __u32 *);
383extern int cifs_verify_signature(struct smb_hdr *, 383extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
384 struct TCP_Server_Info *server, 384 struct TCP_Server_Info *server,
385 __u32 expected_sequence_number); 385 __u32 expected_sequence_number);
386extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); 386extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 10ca6b2c26b7..33a3fbf3a3a5 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -496,13 +496,18 @@ int
496cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, 496cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
497 bool log_error) 497 bool log_error)
498{ 498{
499 dump_smb(mid->resp_buf, 499 unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4;
500 min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length))); 500
501 dump_smb(mid->resp_buf, min_t(u32, 92, len));
501 502
502 /* convert the length into a more usable form */ 503 /* convert the length into a more usable form */
503 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;
506
507 iov.iov_base = mid->resp_buf;
508 iov.iov_len = len;
504 /* FIXME: add code to kill session */ 509 /* FIXME: add code to kill session */
505 if (cifs_verify_signature(mid->resp_buf, server, 510 if (cifs_verify_signature(&iov, 1, server,
506 mid->sequence_number + 1) != 0) 511 mid->sequence_number + 1) != 0)
507 cERROR(1, "Unexpected SMB signature"); 512 cERROR(1, "Unexpected SMB signature");
508 } 513 }