Blame view

fs/cifs/smb2transport.c 15.6 KB
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  /*
   *   fs/cifs/smb2transport.c
   *
   *   Copyright (C) International Business Machines  Corp., 2002, 2011
   *                 Etersoft, 2012
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *              Jeremy Allison (jra@samba.org) 2006
   *              Pavel Shilovsky (pshilovsky@samba.org) 2012
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
  
  #include <linux/fs.h>
  #include <linux/list.h>
  #include <linux/wait.h>
  #include <linux/net.h>
  #include <linux/delay.h>
  #include <linux/uaccess.h>
  #include <asm/processor.h>
  #include <linux/mempool.h>
fb308a6f2   Jeff Layton   cifs: teach signi...
33
  #include <linux/highmem.h>
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
34
35
36
37
38
39
  #include "smb2pdu.h"
  #include "cifsglob.h"
  #include "cifsproto.h"
  #include "smb2proto.h"
  #include "cifs_debug.h"
  #include "smb2status.h"
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
40
  #include "smb2glob.h"
95dc8dd14   Steve French   Limit allocation ...
41
42
43
  static int
  smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
  {
ba4820293   Jeff Layton   cifs: fix bad err...
44
  	int rc;
95dc8dd14   Steve French   Limit allocation ...
45
46
47
48
49
50
51
52
53
  	unsigned int size;
  
  	if (server->secmech.sdeschmacsha256 != NULL)
  		return 0; /* already allocated */
  
  	server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
  	if (IS_ERR(server->secmech.hmacsha256)) {
  		cifs_dbg(VFS, "could not allocate crypto hmacsha256
  ");
ba4820293   Jeff Layton   cifs: fix bad err...
54
55
56
  		rc = PTR_ERR(server->secmech.hmacsha256);
  		server->secmech.hmacsha256 = NULL;
  		return rc;
95dc8dd14   Steve French   Limit allocation ...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  	}
  
  	size = sizeof(struct shash_desc) +
  			crypto_shash_descsize(server->secmech.hmacsha256);
  	server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
  	if (!server->secmech.sdeschmacsha256) {
  		crypto_free_shash(server->secmech.hmacsha256);
  		server->secmech.hmacsha256 = NULL;
  		return -ENOMEM;
  	}
  	server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
  	server->secmech.sdeschmacsha256->shash.flags = 0x0;
  
  	return 0;
  }
  
  static int
  smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
  {
  	unsigned int size;
  	int rc;
  
  	if (server->secmech.sdesccmacaes != NULL)
  		return 0;  /* already allocated */
  
  	rc = smb2_crypto_shash_allocate(server);
  	if (rc)
  		return rc;
  
  	server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
  	if (IS_ERR(server->secmech.cmacaes)) {
  		cifs_dbg(VFS, "could not allocate crypto cmac-aes");
  		kfree(server->secmech.sdeschmacsha256);
  		server->secmech.sdeschmacsha256 = NULL;
  		crypto_free_shash(server->secmech.hmacsha256);
  		server->secmech.hmacsha256 = NULL;
ba4820293   Jeff Layton   cifs: fix bad err...
93
94
95
  		rc = PTR_ERR(server->secmech.cmacaes);
  		server->secmech.cmacaes = NULL;
  		return rc;
95dc8dd14   Steve French   Limit allocation ...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  	}
  
  	size = sizeof(struct shash_desc) +
  			crypto_shash_descsize(server->secmech.cmacaes);
  	server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
  	if (!server->secmech.sdesccmacaes) {
  		cifs_dbg(VFS, "%s: Can't alloc cmacaes
  ", __func__);
  		kfree(server->secmech.sdeschmacsha256);
  		server->secmech.sdeschmacsha256 = NULL;
  		crypto_free_shash(server->secmech.hmacsha256);
  		crypto_free_shash(server->secmech.cmacaes);
  		server->secmech.hmacsha256 = NULL;
  		server->secmech.cmacaes = NULL;
  		return -ENOMEM;
  	}
  	server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
  	server->secmech.sdesccmacaes->shash.flags = 0x0;
  
  	return 0;
  }
32811d242   Shirish Pargaonkar   cifs: Start using...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  static struct cifs_ses *
  smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
  {
  	struct cifs_ses *ses;
  
  	spin_lock(&cifs_tcp_ses_lock);
  	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
  		if (ses->Suid != smb2hdr->SessionId)
  			continue;
  		spin_unlock(&cifs_tcp_ses_lock);
  		return ses;
  	}
  	spin_unlock(&cifs_tcp_ses_lock);
  
  	return NULL;
  }
95dc8dd14   Steve French   Limit allocation ...
133

38107d45c   Steve French   Do not send SMB2 ...
134
  int
0b688cfc8   Jeff Layton   cifs: change smb2...
135
  smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
136
  {
16c568eff   Al Viro   cifs: merge the h...
137
  	int rc;
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
138
139
  	unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
  	unsigned char *sigptr = smb2_signature;
0b688cfc8   Jeff Layton   cifs: change smb2...
140
  	struct kvec *iov = rqst->rq_iov;
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
141
  	struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
32811d242   Shirish Pargaonkar   cifs: Start using...
142
143
144
145
146
147
148
149
  	struct cifs_ses *ses;
  
  	ses = smb2_find_smb_ses(smb2_pdu, server);
  	if (!ses) {
  		cifs_dbg(VFS, "%s: Could not find session
  ", __func__);
  		return 0;
  	}
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
150
151
152
  
  	memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
  	memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
95dc8dd14   Steve French   Limit allocation ...
153
154
155
156
157
158
  	rc = smb2_crypto_shash_allocate(server);
  	if (rc) {
  		cifs_dbg(VFS, "%s: shah256 alloc failed
  ", __func__);
  		return rc;
  	}
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
159
  	rc = crypto_shash_setkey(server->secmech.hmacsha256,
32811d242   Shirish Pargaonkar   cifs: Start using...
160
  		ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
161
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
162
163
  		cifs_dbg(VFS, "%s: Could not update with response
  ", __func__);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
164
165
166
167
168
  		return rc;
  	}
  
  	rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
  	if (rc) {
95dc8dd14   Steve French   Limit allocation ...
169
  		cifs_dbg(VFS, "%s: Could not init sha256", __func__);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
170
171
  		return rc;
  	}
16c568eff   Al Viro   cifs: merge the h...
172
173
  	rc = __cifs_calc_signature(rqst, server, sigptr,
  		&server->secmech.sdeschmacsha256->shash);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
174

16c568eff   Al Viro   cifs: merge the h...
175
176
  	if (!rc)
  		memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
177
178
179
  
  	return rc;
  }
373512ec5   Steve French   Prepare for encry...
180
181
  static int generate_key(struct cifs_ses *ses, struct kvec label,
  			struct kvec context, __u8 *key, unsigned int key_size)
429b46f4f   Steve French   [CIFS] SMB3 Signi...
182
183
184
185
186
187
188
189
190
  {
  	unsigned char zero = 0x0;
  	__u8 i[4] = {0, 0, 0, 1};
  	__u8 L[4] = {0, 0, 0, 128};
  	int rc = 0;
  	unsigned char prfhash[SMB2_HMACSHA256_SIZE];
  	unsigned char *hashptr = prfhash;
  
  	memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
373512ec5   Steve French   Prepare for encry...
191
  	memset(key, 0x0, key_size);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
192

32811d242   Shirish Pargaonkar   cifs: Start using...
193
  	rc = smb3_crypto_shash_allocate(ses->server);
95dc8dd14   Steve French   Limit allocation ...
194
195
196
197
198
  	if (rc) {
  		cifs_dbg(VFS, "%s: crypto alloc failed
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
199
200
  	rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
  		ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
201
202
203
204
205
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not set with session key
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
206
  	rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
207
208
209
210
211
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not init sign hmac
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
212
  	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
429b46f4f   Steve French   [CIFS] SMB3 Signi...
213
214
215
216
217
218
  				i, 4);
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not update with n
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
219
  	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
373512ec5   Steve French   Prepare for encry...
220
  				label.iov_base, label.iov_len);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
221
222
223
224
225
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not update with label
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
226
  	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
429b46f4f   Steve French   [CIFS] SMB3 Signi...
227
228
229
230
231
232
  				&zero, 1);
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not update with zero
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
233
  	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
373512ec5   Steve French   Prepare for encry...
234
  				context.iov_base, context.iov_len);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
235
236
237
238
239
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not update with context
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
240
  	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
429b46f4f   Steve French   [CIFS] SMB3 Signi...
241
242
243
244
245
246
  				L, 4);
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not update with L
  ", __func__);
  		goto smb3signkey_ret;
  	}
32811d242   Shirish Pargaonkar   cifs: Start using...
247
  	rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
429b46f4f   Steve French   [CIFS] SMB3 Signi...
248
249
250
251
252
253
  				hashptr);
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not generate sha256 hash
  ", __func__);
  		goto smb3signkey_ret;
  	}
373512ec5   Steve French   Prepare for encry...
254
  	memcpy(key, hashptr, key_size);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
255
256
  
  smb3signkey_ret:
32811d242   Shirish Pargaonkar   cifs: Start using...
257
  	return rc;
429b46f4f   Steve French   [CIFS] SMB3 Signi...
258
  }
373512ec5   Steve French   Prepare for encry...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  struct derivation {
  	struct kvec label;
  	struct kvec context;
  };
  
  struct derivation_triplet {
  	struct derivation signing;
  	struct derivation encryption;
  	struct derivation decryption;
  };
  
  static int
  generate_smb3signingkey(struct cifs_ses *ses,
  			const struct derivation_triplet *ptriplet)
  {
  	int rc;
  
  	rc = generate_key(ses, ptriplet->signing.label,
  			  ptriplet->signing.context, ses->smb3signingkey,
  			  SMB3_SIGN_KEY_SIZE);
  	if (rc)
  		return rc;
  
  	rc = generate_key(ses, ptriplet->encryption.label,
  			  ptriplet->encryption.context, ses->smb3encryptionkey,
  			  SMB3_SIGN_KEY_SIZE);
  	if (rc)
  		return rc;
  
  	return generate_key(ses, ptriplet->decryption.label,
  			    ptriplet->decryption.context,
  			    ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
  }
  
  int
  generate_smb30signingkey(struct cifs_ses *ses)
  
  {
  	struct derivation_triplet triplet;
  	struct derivation *d;
  
  	d = &triplet.signing;
  	d->label.iov_base = "SMB2AESCMAC";
  	d->label.iov_len = 12;
  	d->context.iov_base = "SmbSign";
  	d->context.iov_len = 8;
  
  	d = &triplet.encryption;
  	d->label.iov_base = "SMB2AESCCM";
  	d->label.iov_len = 11;
  	d->context.iov_base = "ServerIn ";
  	d->context.iov_len = 10;
  
  	d = &triplet.decryption;
  	d->label.iov_base = "SMB2AESCCM";
  	d->label.iov_len = 11;
  	d->context.iov_base = "ServerOut";
  	d->context.iov_len = 10;
  
  	return generate_smb3signingkey(ses, &triplet);
  }
  
  int
  generate_smb311signingkey(struct cifs_ses *ses)
  
  {
  	struct derivation_triplet triplet;
  	struct derivation *d;
  
  	d = &triplet.signing;
  	d->label.iov_base = "SMB2AESCMAC";
  	d->label.iov_len = 12;
  	d->context.iov_base = "SmbSign";
  	d->context.iov_len = 8;
  
  	d = &triplet.encryption;
  	d->label.iov_base = "SMB2AESCCM";
  	d->label.iov_len = 11;
  	d->context.iov_base = "ServerIn ";
  	d->context.iov_len = 10;
  
  	d = &triplet.decryption;
  	d->label.iov_base = "SMB2AESCCM";
  	d->label.iov_len = 11;
  	d->context.iov_base = "ServerOut";
  	d->context.iov_len = 10;
  
  	return generate_smb3signingkey(ses, &triplet);
  }
429b46f4f   Steve French   [CIFS] SMB3 Signi...
348
  int
38107d45c   Steve French   Do not send SMB2 ...
349
350
  smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
  {
32811d242   Shirish Pargaonkar   cifs: Start using...
351
  	int rc = 0;
429b46f4f   Steve French   [CIFS] SMB3 Signi...
352
353
354
  	unsigned char smb3_signature[SMB2_CMACAES_SIZE];
  	unsigned char *sigptr = smb3_signature;
  	struct kvec *iov = rqst->rq_iov;
429b46f4f   Steve French   [CIFS] SMB3 Signi...
355
  	struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
32811d242   Shirish Pargaonkar   cifs: Start using...
356
357
358
359
360
361
362
363
  	struct cifs_ses *ses;
  
  	ses = smb2_find_smb_ses(smb2_pdu, server);
  	if (!ses) {
  		cifs_dbg(VFS, "%s: Could not find session
  ", __func__);
  		return 0;
  	}
429b46f4f   Steve French   [CIFS] SMB3 Signi...
364
365
366
367
368
  
  	memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
  	memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
  
  	rc = crypto_shash_setkey(server->secmech.cmacaes,
32811d242   Shirish Pargaonkar   cifs: Start using...
369
  		ses->smb3signingkey, SMB2_CMACAES_SIZE);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
370
371
372
373
374
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not set key for cmac aes
  ", __func__);
  		return rc;
  	}
95dc8dd14   Steve French   Limit allocation ...
375
376
377
378
379
  	/*
  	 * we already allocate sdesccmacaes when we init smb3 signing key,
  	 * so unlike smb2 case we do not have to check here if secmech are
  	 * initialized
  	 */
429b46f4f   Steve French   [CIFS] SMB3 Signi...
380
381
382
383
384
385
  	rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
  	if (rc) {
  		cifs_dbg(VFS, "%s: Could not init cmac aes
  ", __func__);
  		return rc;
  	}
16c568eff   Al Viro   cifs: merge the h...
386
387
388
  	
  	rc = __cifs_calc_signature(rqst, server, sigptr,
  				   &server->secmech.sdesccmacaes->shash);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
389

16c568eff   Al Viro   cifs: merge the h...
390
391
  	if (!rc)
  		memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE);
429b46f4f   Steve French   [CIFS] SMB3 Signi...
392
393
  
  	return rc;
38107d45c   Steve French   Do not send SMB2 ...
394
  }
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
395
396
  /* must be called with server->srv_mutex held */
  static int
0b688cfc8   Jeff Layton   cifs: change smb2...
397
  smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
398
399
  {
  	int rc = 0;
0b688cfc8   Jeff Layton   cifs: change smb2...
400
  	struct smb2_hdr *smb2_pdu = rqst->rq_iov[0].iov_base;
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
401
402
403
404
405
406
407
408
409
  
  	if (!(smb2_pdu->Flags & SMB2_FLAGS_SIGNED) ||
  	    server->tcpStatus == CifsNeedNegotiate)
  		return rc;
  
  	if (!server->session_estab) {
  		strncpy(smb2_pdu->Signature, "BSRSPYL", 8);
  		return rc;
  	}
38107d45c   Steve French   Do not send SMB2 ...
410
  	rc = server->ops->calc_signature(rqst, server);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
411
412
413
414
415
  
  	return rc;
  }
  
  int
0b688cfc8   Jeff Layton   cifs: change smb2...
416
  smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
417
418
419
  {
  	unsigned int rc;
  	char server_response_sig[16];
0b688cfc8   Jeff Layton   cifs: change smb2...
420
  	struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
421
422
  
  	if ((smb2_pdu->Command == SMB2_NEGOTIATE) ||
32811d242   Shirish Pargaonkar   cifs: Start using...
423
  	    (smb2_pdu->Command == SMB2_SESSION_SETUP) ||
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
424
425
426
427
428
429
430
431
432
433
434
  	    (smb2_pdu->Command == SMB2_OPLOCK_BREAK) ||
  	    (!server->session_estab))
  		return 0;
  
  	/*
  	 * BB what if signatures are supposed to be on for session but
  	 * server does not send one? BB
  	 */
  
  	/* Do not need to verify session setups with signature "BSRSPYL " */
  	if (memcmp(smb2_pdu->Signature, "BSRSPYL ", 8) == 0)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
435
436
437
  		cifs_dbg(FYI, "dummy signature received for smb command 0x%x
  ",
  			 smb2_pdu->Command);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
438
439
440
441
442
443
444
445
446
447
  
  	/*
  	 * Save off the origiginal signature so we can modify the smb and check
  	 * our calculated signature against what the server sent.
  	 */
  	memcpy(server_response_sig, smb2_pdu->Signature, SMB2_SIGNATURE_SIZE);
  
  	memset(smb2_pdu->Signature, 0, SMB2_SIGNATURE_SIZE);
  
  	mutex_lock(&server->srv_mutex);
38107d45c   Steve French   Do not send SMB2 ...
448
  	rc = server->ops->calc_signature(rqst, server);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
449
450
451
452
453
454
455
456
457
458
459
  	mutex_unlock(&server->srv_mutex);
  
  	if (rc)
  		return rc;
  
  	if (memcmp(server_response_sig, smb2_pdu->Signature,
  		   SMB2_SIGNATURE_SIZE))
  		return -EACCES;
  	else
  		return 0;
  }
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
460
461
462
463
464
465
466
  /*
   * Set message id for the request. Should be called after wait_for_free_request
   * and when srv_mutex is held.
   */
  static inline void
  smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr)
  {
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
467
  	unsigned int i, num = le16_to_cpu(hdr->CreditCharge);
3d378d3fd   Tim Gardner   cifs: Make big en...
468
  	hdr->MessageId = get_next_mid64(server);
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
469
470
471
  	/* skip message numbers according to CreditCharge field */
  	for (i = 1; i < num; i++)
  		get_next_mid(server);
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
472
473
474
475
476
477
478
479
480
  }
  
  static struct mid_q_entry *
  smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
  		     struct TCP_Server_Info *server)
  {
  	struct mid_q_entry *temp;
  
  	if (server == NULL) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
481
482
  		cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc
  ");
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
483
484
485
486
487
488
489
490
  		return NULL;
  	}
  
  	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
  	if (temp == NULL)
  		return temp;
  	else {
  		memset(temp, 0, sizeof(struct mid_q_entry));
9235d0987   Sachin Prabhu   Convert MessageID...
491
  		temp->mid = le64_to_cpu(smb_buffer->MessageId);
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  		temp->pid = current->pid;
  		temp->command = smb_buffer->Command;	/* Always LE */
  		temp->when_alloc = jiffies;
  		temp->server = server;
  
  		/*
  		 * The default is for the mid to be synchronous, so the
  		 * default callback just wakes up the current task.
  		 */
  		temp->callback = cifs_wake_up_task;
  		temp->callback_data = current;
  	}
  
  	atomic_inc(&midCount);
  	temp->mid_state = MID_REQUEST_ALLOCATED;
  	return temp;
  }
  
  static int
  smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
  		   struct mid_q_entry **mid)
  {
  	if (ses->server->tcpStatus == CifsExiting)
  		return -ENOENT;
  
  	if (ses->server->tcpStatus == CifsNeedReconnect) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
518
519
  		cifs_dbg(FYI, "tcp session dead - return to caller to retry
  ");
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
520
521
  		return -EAGAIN;
  	}
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
522
  	if (ses->status == CifsNew) {
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
523
524
525
526
527
  		if ((buf->Command != SMB2_SESSION_SETUP) &&
  		    (buf->Command != SMB2_NEGOTIATE))
  			return -EAGAIN;
  		/* else ok - we are setting up session */
  	}
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
528
529
530
531
532
533
  
  	if (ses->status == CifsExiting) {
  		if (buf->Command != SMB2_LOGOFF)
  			return -EAGAIN;
  		/* else ok - we are shutting down the session */
  	}
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  	*mid = smb2_mid_entry_alloc(buf, ses->server);
  	if (*mid == NULL)
  		return -ENOMEM;
  	spin_lock(&GlobalMid_Lock);
  	list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
  	spin_unlock(&GlobalMid_Lock);
  	return 0;
  }
  
  int
  smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
  		   bool log_error)
  {
  	unsigned int len = get_rfc1002_length(mid->resp_buf);
0b688cfc8   Jeff Layton   cifs: change smb2...
548
549
550
551
552
553
  	struct kvec iov;
  	struct smb_rqst rqst = { .rq_iov = &iov,
  				 .rq_nvec = 1 };
  
  	iov.iov_base = (char *)mid->resp_buf;
  	iov.iov_len = get_rfc1002_length(mid->resp_buf) + 4;
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
554
555
556
  
  	dump_smb(mid->resp_buf, min_t(u32, 80, len));
  	/* convert the length into a more usable form */
38d77c50b   Jeff Layton   cifs: track the e...
557
  	if (len > 24 && server->sign) {
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
558
  		int rc;
0b688cfc8   Jeff Layton   cifs: change smb2...
559
  		rc = smb2_verify_signature(&rqst, server);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
560
  		if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
561
562
563
  			cifs_dbg(VFS, "SMB signature verification returned error = %d
  ",
  				 rc);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
564
  	}
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
565
566
567
  
  	return map_smb2_to_linux_error(mid->resp_buf, log_error);
  }
fec344e3f   Jeff Layton   cifs: change cifs...
568
569
  struct mid_q_entry *
  smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
570
571
  {
  	int rc;
fec344e3f   Jeff Layton   cifs: change cifs...
572
  	struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
573
574
575
576
577
578
  	struct mid_q_entry *mid;
  
  	smb2_seq_num_into_buf(ses->server, hdr);
  
  	rc = smb2_get_mid_entry(ses, hdr, &mid);
  	if (rc)
fec344e3f   Jeff Layton   cifs: change cifs...
579
580
581
  		return ERR_PTR(rc);
  	rc = smb2_sign_rqst(rqst, ses->server);
  	if (rc) {
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
582
  		cifs_delete_mid(mid);
fec344e3f   Jeff Layton   cifs: change cifs...
583
584
585
  		return ERR_PTR(rc);
  	}
  	return mid;
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
586
  }
fec344e3f   Jeff Layton   cifs: change cifs...
587
588
  struct mid_q_entry *
  smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
c95b8eeda   Pavel Shilovsky   CIFS: Add SMB2 su...
589
  {
fec344e3f   Jeff Layton   cifs: change cifs...
590
591
  	int rc;
  	struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
c95b8eeda   Pavel Shilovsky   CIFS: Add SMB2 su...
592
593
594
595
596
597
  	struct mid_q_entry *mid;
  
  	smb2_seq_num_into_buf(server, hdr);
  
  	mid = smb2_mid_entry_alloc(hdr, server);
  	if (mid == NULL)
fec344e3f   Jeff Layton   cifs: change cifs...
598
  		return ERR_PTR(-ENOMEM);
c95b8eeda   Pavel Shilovsky   CIFS: Add SMB2 su...
599

fec344e3f   Jeff Layton   cifs: change cifs...
600
  	rc = smb2_sign_rqst(rqst, server);
c95b8eeda   Pavel Shilovsky   CIFS: Add SMB2 su...
601
602
  	if (rc) {
  		DeleteMidQEntry(mid);
fec344e3f   Jeff Layton   cifs: change cifs...
603
  		return ERR_PTR(rc);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
604
  	}
fec344e3f   Jeff Layton   cifs: change cifs...
605
  	return mid;
c95b8eeda   Pavel Shilovsky   CIFS: Add SMB2 su...
606
  }