smb2transport.c 21.0 KB
Newer Older
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>
33
#include <linux/highmem.h>
34
#include <crypto/aead.h>
35 36 37 38 39 40
#include "smb2pdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "smb2proto.h"
#include "cifs_debug.h"
#include "smb2status.h"
P
Pavel Shilovsky 已提交
41 42
#include "smb2glob.h"

43 44 45
static int
smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
{
46 47 48
	return cifs_alloc_hash("hmac(sha256)",
			       &server->secmech.hmacsha256,
			       &server->secmech.sdeschmacsha256);
49 50 51 52 53
}

static int
smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
{
54
	struct cifs_secmech *p = &server->secmech;
55 56
	int rc;

57 58 59
	rc = cifs_alloc_hash("hmac(sha256)",
			     &p->hmacsha256,
			     &p->sdeschmacsha256);
60
	if (rc)
61
		goto err;
62

63 64 65
	rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
	if (rc)
		goto err;
66 67

	return 0;
68 69 70
err:
	cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
	return rc;
71 72
}

A
Aurelien Aptel 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
int
smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
{
	struct cifs_secmech *p = &server->secmech;
	int rc = 0;

	rc = cifs_alloc_hash("hmac(sha256)",
			     &p->hmacsha256,
			     &p->sdeschmacsha256);
	if (rc)
		return rc;

	rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
	if (rc)
		goto err;

	rc = cifs_alloc_hash("sha512", &p->sha512, &p->sdescsha512);
	if (rc)
		goto err;

	return 0;

err:
	cifs_free_hash(&p->cmacaes, &p->sdesccmacaes);
	cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
	return rc;
}

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

static
int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
{
	struct cifs_chan *chan;
	struct cifs_ses *ses = NULL;
	int i;
	int rc = 0;

	spin_lock(&cifs_tcp_ses_lock);

	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
			if (ses->Suid == ses_id)
				goto found;
		}
	}
	cifs_server_dbg(VFS, "%s: Could not find session 0x%llx\n",
			__func__, ses_id);
	rc = -ENOENT;
	goto out;

found:
	if (ses->binding) {
		/*
		 * If we are in the process of binding a new channel
		 * to an existing session, use the master connection
		 * session key
		 */
		memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
		goto out;
	}

	/*
	 * Otherwise, use the channel key.
	 */

	for (i = 0; i < ses->chan_count; i++) {
		chan = ses->chans + i;
		if (chan->server == server) {
			memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
			goto out;
		}
	}

	cifs_dbg(VFS,
		 "%s: Could not find channel signing key for session 0x%llx\n",
		 __func__, ses_id);
	rc = -ENOENT;

out:
	spin_unlock(&cifs_tcp_ses_lock);
	return rc;
}

S
Sachin Prabhu 已提交
156 157
static struct cifs_ses *
smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
158 159 160 161
{
	struct cifs_ses *ses;

	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
162
		if (ses->Suid != ses_id)
163 164 165
			continue;
		return ses;
	}
S
Sachin Prabhu 已提交
166 167 168 169 170 171 172 173 174 175 176

	return NULL;
}

struct cifs_ses *
smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
{
	struct cifs_ses *ses;

	spin_lock(&cifs_tcp_ses_lock);
	ses = smb2_find_smb_ses_unlocked(server, ses_id);
177 178
	spin_unlock(&cifs_tcp_ses_lock);

S
Sachin Prabhu 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
	return ses;
}

static struct cifs_tcon *
smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
{
	struct cifs_tcon *tcon;

	list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
		if (tcon->tid != tid)
			continue;
		++tcon->tc_count;
		return tcon;
	}

194 195 196
	return NULL;
}

S
Sachin Prabhu 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
/*
 * Obtain tcon corresponding to the tid in the given
 * cifs_ses
 */

struct cifs_tcon *
smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32  tid)
{
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;

	spin_lock(&cifs_tcp_ses_lock);
	ses = smb2_find_smb_ses_unlocked(server, ses_id);
	if (!ses) {
		spin_unlock(&cifs_tcp_ses_lock);
		return NULL;
	}
	tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
	spin_unlock(&cifs_tcp_ses_lock);

	return tcon;
}

220
int
221
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
P
Pavel Shilovsky 已提交
222
{
223
	int rc;
P
Pavel Shilovsky 已提交
224 225
	unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
	unsigned char *sigptr = smb2_signature;
226
	struct kvec *iov = rqst->rq_iov;
227
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
228
	struct cifs_ses *ses;
229
	struct shash_desc *shash;
230
	struct smb_rqst drqst;
231

232
	ses = smb2_find_smb_ses(server, shdr->SessionId);
233
	if (!ses) {
234
		cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
235 236
		return 0;
	}
P
Pavel Shilovsky 已提交
237 238

	memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
239
	memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
240

241 242
	rc = smb2_crypto_shash_allocate(server);
	if (rc) {
243
		cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__);
244 245 246
		return rc;
	}

P
Pavel Shilovsky 已提交
247
	rc = crypto_shash_setkey(server->secmech.hmacsha256,
248
				 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
P
Pavel Shilovsky 已提交
249
	if (rc) {
250
		cifs_server_dbg(VFS, "%s: Could not update with response\n", __func__);
P
Pavel Shilovsky 已提交
251 252 253
		return rc;
	}

254
	shash = &server->secmech.sdeschmacsha256->shash;
255
	rc = crypto_shash_init(shash);
P
Pavel Shilovsky 已提交
256
	if (rc) {
257
		cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
P
Pavel Shilovsky 已提交
258 259 260
		return rc;
	}

261 262 263 264 265 266 267 268 269 270 271 272
	/*
	 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
	 * data, that is, iov[0] should not contain a rfc1002 length.
	 *
	 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
	 * __cifs_calc_signature().
	 */
	drqst = *rqst;
	if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
		rc = crypto_shash_update(shash, iov[0].iov_base,
					 iov[0].iov_len);
		if (rc) {
273
			cifs_server_dbg(VFS, "%s: Could not update with payload\n",
274 275 276 277 278 279
				 __func__);
			return rc;
		}
		drqst.rq_iov++;
		drqst.rq_nvec--;
	}
P
Pavel Shilovsky 已提交
280

281
	rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
282
	if (!rc)
283
		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
284 285 286 287

	return rc;
}

288 289
static int generate_key(struct cifs_ses *ses, struct kvec label,
			struct kvec context, __u8 *key, unsigned int key_size)
S
Steve French 已提交
290 291 292 293 294 295 296
{
	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;
297
	struct TCP_Server_Info *server = ses->server;
S
Steve French 已提交
298 299

	memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
300
	memset(key, 0x0, key_size);
S
Steve French 已提交
301

302
	rc = smb3_crypto_shash_allocate(server);
303
	if (rc) {
304
		cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
305 306 307
		goto smb3signkey_ret;
	}

308
	rc = crypto_shash_setkey(server->secmech.hmacsha256,
309
		ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
S
Steve French 已提交
310
	if (rc) {
311
		cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
S
Steve French 已提交
312 313 314
		goto smb3signkey_ret;
	}

315
	rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
S
Steve French 已提交
316
	if (rc) {
317
		cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
S
Steve French 已提交
318 319 320
		goto smb3signkey_ret;
	}

321
	rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
322 323
				i, 4);
	if (rc) {
324
		cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
S
Steve French 已提交
325 326 327
		goto smb3signkey_ret;
	}

328
	rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
329
				label.iov_base, label.iov_len);
S
Steve French 已提交
330
	if (rc) {
331
		cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
S
Steve French 已提交
332 333 334
		goto smb3signkey_ret;
	}

335
	rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
336 337
				&zero, 1);
	if (rc) {
338
		cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
S
Steve French 已提交
339 340 341
		goto smb3signkey_ret;
	}

342
	rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
343
				context.iov_base, context.iov_len);
S
Steve French 已提交
344
	if (rc) {
345
		cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
S
Steve French 已提交
346 347 348
		goto smb3signkey_ret;
	}

349
	rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
350 351
				L, 4);
	if (rc) {
352
		cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
S
Steve French 已提交
353 354 355
		goto smb3signkey_ret;
	}

356
	rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
357 358
				hashptr);
	if (rc) {
359
		cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
S
Steve French 已提交
360 361 362
		goto smb3signkey_ret;
	}

363
	memcpy(key, hashptr, key_size);
S
Steve French 已提交
364 365

smb3signkey_ret:
366
	return rc;
S
Steve French 已提交
367 368
}

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
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;

386 387 388 389 390 391 392 393 394
	/*
	 * All channels use the same encryption/decryption keys but
	 * they have their own signing key.
	 *
	 * When we generate the keys, check if it is for a new channel
	 * (binding) in which case we only need to generate a signing
	 * key and store it in the channel as to not overwrite the
	 * master connection signing key stored in the session
	 */
395

396 397 398 399 400 401 402 403 404 405 406 407 408 409
	if (ses->binding) {
		rc = generate_key(ses, ptriplet->signing.label,
				  ptriplet->signing.context,
				  cifs_ses_binding_channel(ses)->signkey,
				  SMB3_SIGN_KEY_SIZE);
		if (rc)
			return rc;
	} else {
		rc = generate_key(ses, ptriplet->signing.label,
				  ptriplet->signing.context,
				  ses->smb3signingkey,
				  SMB3_SIGN_KEY_SIZE);
		if (rc)
			return rc;
410 411 412 413

		memcpy(ses->chans[0].signkey, ses->smb3signingkey,
		       SMB3_SIGN_KEY_SIZE);

414 415 416 417 418 419 420 421 422 423 424
		rc = generate_key(ses, ptriplet->encryption.label,
				  ptriplet->encryption.context,
				  ses->smb3encryptionkey,
				  SMB3_SIGN_KEY_SIZE);
		rc = generate_key(ses, ptriplet->decryption.label,
				  ptriplet->decryption.context,
				  ses->smb3decryptionkey,
				  SMB3_SIGN_KEY_SIZE);
		if (rc)
			return rc;
	}
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446

	if (rc)
		return rc;

#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
	cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
	/*
	 * The session id is opaque in terms of endianness, so we can't
	 * print it as a long long. we dump it as we got it on the wire
	 */
	cifs_dbg(VFS, "Session Id    %*ph\n", (int)sizeof(ses->Suid),
			&ses->Suid);
	cifs_dbg(VFS, "Session Key   %*ph\n",
		 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
	cifs_dbg(VFS, "Signing Key   %*ph\n",
		 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
	cifs_dbg(VFS, "ServerIn Key  %*ph\n",
		 SMB3_SIGN_KEY_SIZE, ses->smb3encryptionkey);
	cifs_dbg(VFS, "ServerOut Key %*ph\n",
		 SMB3_SIGN_KEY_SIZE, ses->smb3decryptionkey);
#endif
	return rc;
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
}

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;
485 486 487 488
	d->label.iov_base = "SMBSigningKey";
	d->label.iov_len = 14;
	d->context.iov_base = ses->preauth_sha_hash;
	d->context.iov_len = 64;
489 490

	d = &triplet.encryption;
491 492 493 494
	d->label.iov_base = "SMBC2SCipherKey";
	d->label.iov_len = 16;
	d->context.iov_base = ses->preauth_sha_hash;
	d->context.iov_len = 64;
495 496

	d = &triplet.decryption;
497 498 499 500
	d->label.iov_base = "SMBS2CCipherKey";
	d->label.iov_len = 16;
	d->context.iov_base = ses->preauth_sha_hash;
	d->context.iov_len = 64;
501 502 503 504

	return generate_smb3signingkey(ses, &triplet);
}

505 506 507
int
smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
{
508
	int rc;
S
Steve French 已提交
509 510 511
	unsigned char smb3_signature[SMB2_CMACAES_SIZE];
	unsigned char *sigptr = smb3_signature;
	struct kvec *iov = rqst->rq_iov;
512
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
513 514
	struct shash_desc *shash = &server->secmech.sdesccmacaes->shash;
	struct smb_rqst drqst;
515
	u8 key[SMB3_SIGN_KEY_SIZE];
516

517 518
	rc = smb2_get_sign_key(shdr->SessionId, server, key);
	if (rc)
519
		return 0;
S
Steve French 已提交
520 521

	memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
522
	memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
S
Steve French 已提交
523 524

	rc = crypto_shash_setkey(server->secmech.cmacaes,
525
				 key, SMB2_CMACAES_SIZE);
S
Steve French 已提交
526
	if (rc) {
527
		cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
S
Steve French 已提交
528 529 530
		return rc;
	}

531 532 533 534 535
	/*
	 * 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
	 */
536
	rc = crypto_shash_init(shash);
S
Steve French 已提交
537
	if (rc) {
538
		cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
S
Steve French 已提交
539 540
		return rc;
	}
541

542 543 544 545 546 547 548 549 550 551 552 553
	/*
	 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
	 * data, that is, iov[0] should not contain a rfc1002 length.
	 *
	 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
	 * __cifs_calc_signature().
	 */
	drqst = *rqst;
	if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
		rc = crypto_shash_update(shash, iov[0].iov_base,
					 iov[0].iov_len);
		if (rc) {
554
			cifs_server_dbg(VFS, "%s: Could not update with payload\n",
555 556 557 558 559 560
				 __func__);
			return rc;
		}
		drqst.rq_iov++;
		drqst.rq_nvec--;
	}
S
Steve French 已提交
561

562
	rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
563
	if (!rc)
564
		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
S
Steve French 已提交
565 566

	return rc;
567 568
}

P
Pavel Shilovsky 已提交
569 570
/* must be called with server->srv_mutex held */
static int
571
smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
P
Pavel Shilovsky 已提交
572 573
{
	int rc = 0;
574 575 576 577
	struct smb2_sync_hdr *shdr;
	struct smb2_sess_setup_req *ssr;
	bool is_binding;
	bool is_signed;
P
Pavel Shilovsky 已提交
578

579 580
	shdr = (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
	ssr = (struct smb2_sess_setup_req *)shdr;
P
Pavel Shilovsky 已提交
581

582 583 584 585 586 587 588 589 590
	is_binding = shdr->Command == SMB2_SESSION_SETUP &&
		(ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);
	is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;

	if (!is_signed)
		return 0;
	if (server->tcpStatus == CifsNeedNegotiate)
		return 0;
	if (!is_binding && !server->session_estab) {
591
		strncpy(shdr->Signature, "BSRSPYL", 8);
592
		return 0;
P
Pavel Shilovsky 已提交
593 594
	}

595
	rc = server->ops->calc_signature(rqst, server);
P
Pavel Shilovsky 已提交
596 597 598 599 600

	return rc;
}

int
601
smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
P
Pavel Shilovsky 已提交
602 603 604
{
	unsigned int rc;
	char server_response_sig[16];
605
	struct smb2_sync_hdr *shdr =
606
			(struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
P
Pavel Shilovsky 已提交
607

608 609 610
	if ((shdr->Command == SMB2_NEGOTIATE) ||
	    (shdr->Command == SMB2_SESSION_SETUP) ||
	    (shdr->Command == SMB2_OPLOCK_BREAK) ||
611
	    server->ignore_signature ||
P
Pavel Shilovsky 已提交
612 613 614 615 616 617 618 619 620
	    (!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 " */
621
	if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
622
		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
623
			 shdr->Command);
P
Pavel Shilovsky 已提交
624 625 626 627 628

	/*
	 * Save off the origiginal signature so we can modify the smb and check
	 * our calculated signature against what the server sent.
	 */
629
	memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
630

631
	memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
632 633

	mutex_lock(&server->srv_mutex);
634
	rc = server->ops->calc_signature(rqst, server);
P
Pavel Shilovsky 已提交
635 636 637 638 639
	mutex_unlock(&server->srv_mutex);

	if (rc)
		return rc;

640
	if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE))
P
Pavel Shilovsky 已提交
641 642 643 644 645
		return -EACCES;
	else
		return 0;
}

646 647 648 649 650
/*
 * Set message id for the request. Should be called after wait_for_free_request
 * and when srv_mutex is held.
 */
static inline void
651 652
smb2_seq_num_into_buf(struct TCP_Server_Info *server,
		      struct smb2_sync_hdr *shdr)
653
{
654
	unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
655

656
	shdr->MessageId = get_next_mid64(server);
657 658 659
	/* skip message numbers according to CreditCharge field */
	for (i = 1; i < num; i++)
		get_next_mid(server);
660 661 662
}

static struct mid_q_entry *
663
smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
664 665 666
		     struct TCP_Server_Info *server)
{
	struct mid_q_entry *temp;
667
	unsigned int credits = le16_to_cpu(shdr->CreditCharge);
668 669

	if (server == NULL) {
670
		cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
671 672 673 674
		return NULL;
	}

	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
675
	memset(temp, 0, sizeof(struct mid_q_entry));
676
	kref_init(&temp->refcount);
677
	temp->mid = le64_to_cpu(shdr->MessageId);
678
	temp->credits = credits > 0 ? credits : 1;
679 680 681 682 683 684 685 686 687
	temp->pid = current->pid;
	temp->command = shdr->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.
	 */
688 689
	get_task_struct(current);
	temp->creator = current;
690 691
	temp->callback = cifs_wake_up_task;
	temp->callback_data = current;
692 693 694

	atomic_inc(&midCount);
	temp->mid_state = MID_REQUEST_ALLOCATED;
695 696
	trace_smb3_cmd_enter(shdr->TreeId, shdr->SessionId,
		le16_to_cpu(shdr->Command), temp->mid);
697 698 699 700
	return temp;
}

static int
A
Aurelien Aptel 已提交
701 702
smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,
		   struct smb2_sync_hdr *shdr, struct mid_q_entry **mid)
703
{
A
Aurelien Aptel 已提交
704
	if (server->tcpStatus == CifsExiting)
705 706
		return -ENOENT;

A
Aurelien Aptel 已提交
707
	if (server->tcpStatus == CifsNeedReconnect) {
708
		cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
709 710 711
		return -EAGAIN;
	}

A
Aurelien Aptel 已提交
712
	if (server->tcpStatus == CifsNeedNegotiate &&
713 714 715
	   shdr->Command != SMB2_NEGOTIATE)
		return -EAGAIN;

716
	if (ses->status == CifsNew) {
717 718
		if ((shdr->Command != SMB2_SESSION_SETUP) &&
		    (shdr->Command != SMB2_NEGOTIATE))
719 720 721
			return -EAGAIN;
		/* else ok - we are setting up session */
	}
722 723

	if (ses->status == CifsExiting) {
724
		if (shdr->Command != SMB2_LOGOFF)
725 726 727 728
			return -EAGAIN;
		/* else ok - we are shutting down the session */
	}

A
Aurelien Aptel 已提交
729
	*mid = smb2_mid_entry_alloc(shdr, server);
730 731 732
	if (*mid == NULL)
		return -ENOMEM;
	spin_lock(&GlobalMid_Lock);
A
Aurelien Aptel 已提交
733
	list_add_tail(&(*mid)->qhead, &server->pending_mid_q);
734
	spin_unlock(&GlobalMid_Lock);
735

736 737 738 739 740 741 742
	return 0;
}

int
smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
		   bool log_error)
{
743
	unsigned int len = mid->resp_buf_size;
744
	struct kvec iov[1];
745
	struct smb_rqst rqst = { .rq_iov = iov,
746
				 .rq_nvec = 1 };
747

748
	iov[0].iov_base = (char *)mid->resp_buf;
749
	iov[0].iov_len = len;
750 751 752

	dump_smb(mid->resp_buf, min_t(u32, 80, len));
	/* convert the length into a more usable form */
753
	if (len > 24 && server->sign && !mid->decrypted) {
P
Pavel Shilovsky 已提交
754 755
		int rc;

756
		rc = smb2_verify_signature(&rqst, server);
P
Pavel Shilovsky 已提交
757
		if (rc)
758
			cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
759
				 rc);
P
Pavel Shilovsky 已提交
760
	}
761 762 763 764

	return map_smb2_to_linux_error(mid->resp_buf, log_error);
}

765
struct mid_q_entry *
A
Aurelien Aptel 已提交
766 767
smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,
		   struct smb_rqst *rqst)
768 769
{
	int rc;
770
	struct smb2_sync_hdr *shdr =
771
			(struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
772 773
	struct mid_q_entry *mid;

A
Aurelien Aptel 已提交
774
	smb2_seq_num_into_buf(server, shdr);
775

A
Aurelien Aptel 已提交
776
	rc = smb2_get_mid_entry(ses, server, shdr, &mid);
777
	if (rc) {
A
Aurelien Aptel 已提交
778
		revert_current_mid_from_hdr(server, shdr);
779
		return ERR_PTR(rc);
780 781
	}

A
Aurelien Aptel 已提交
782
	rc = smb2_sign_rqst(rqst, server);
783
	if (rc) {
A
Aurelien Aptel 已提交
784
		revert_current_mid_from_hdr(server, shdr);
P
Pavel Shilovsky 已提交
785
		cifs_delete_mid(mid);
786 787
		return ERR_PTR(rc);
	}
788

789
	return mid;
790 791
}

792 793
struct mid_q_entry *
smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
794
{
795
	int rc;
796
	struct smb2_sync_hdr *shdr =
797
			(struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
798 799
	struct mid_q_entry *mid;

800 801 802 803
	if (server->tcpStatus == CifsNeedNegotiate &&
	   shdr->Command != SMB2_NEGOTIATE)
		return ERR_PTR(-EAGAIN);

804
	smb2_seq_num_into_buf(server, shdr);
805

806
	mid = smb2_mid_entry_alloc(shdr, server);
807 808
	if (mid == NULL) {
		revert_current_mid_from_hdr(server, shdr);
809
		return ERR_PTR(-ENOMEM);
810
	}
811

812
	rc = smb2_sign_rqst(rqst, server);
813
	if (rc) {
814
		revert_current_mid_from_hdr(server, shdr);
815
		DeleteMidQEntry(mid);
816
		return ERR_PTR(rc);
P
Pavel Shilovsky 已提交
817 818
	}

819
	return mid;
820
}
821 822 823 824 825 826 827

int
smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
{
	struct crypto_aead *tfm;

	if (!server->secmech.ccmaesencrypt) {
828 829 830 831
		if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
		else
			tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
832
		if (IS_ERR(tfm)) {
833
			cifs_server_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
834 835 836 837 838 839 840
				 __func__);
			return PTR_ERR(tfm);
		}
		server->secmech.ccmaesencrypt = tfm;
	}

	if (!server->secmech.ccmaesdecrypt) {
841 842 843 844
		if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
		else
			tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
845 846 847
		if (IS_ERR(tfm)) {
			crypto_free_aead(server->secmech.ccmaesencrypt);
			server->secmech.ccmaesencrypt = NULL;
848
			cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
849 850 851 852 853 854 855 856
				 __func__);
			return PTR_ERR(tfm);
		}
		server->secmech.ccmaesdecrypt = tfm;
	}

	return 0;
}