950 lines · c
1// SPDX-License-Identifier: LGPL-2.12/*3 *4 * Copyright (C) International Business Machines Corp., 2002, 20115 * Etersoft, 20126 * Author(s): Steve French (sfrench@us.ibm.com)7 * Jeremy Allison (jra@samba.org) 20068 * Pavel Shilovsky (pshilovsky@samba.org) 20129 *10 */11 12#include <linux/fs.h>13#include <linux/list.h>14#include <linux/wait.h>15#include <linux/net.h>16#include <linux/delay.h>17#include <linux/uaccess.h>18#include <asm/processor.h>19#include <linux/mempool.h>20#include <linux/highmem.h>21#include <crypto/aead.h>22#include "cifsglob.h"23#include "cifsproto.h"24#include "smb2proto.h"25#include "cifs_debug.h"26#include "../common/smb2status.h"27#include "smb2glob.h"28 29static int30smb3_crypto_shash_allocate(struct TCP_Server_Info *server)31{32 struct cifs_secmech *p = &server->secmech;33 int rc;34 35 rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);36 if (rc)37 goto err;38 39 rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);40 if (rc)41 goto err;42 43 return 0;44err:45 cifs_free_hash(&p->hmacsha256);46 return rc;47}48 49int50smb311_crypto_shash_allocate(struct TCP_Server_Info *server)51{52 struct cifs_secmech *p = &server->secmech;53 int rc = 0;54 55 rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);56 if (rc)57 return rc;58 59 rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);60 if (rc)61 goto err;62 63 rc = cifs_alloc_hash("sha512", &p->sha512);64 if (rc)65 goto err;66 67 return 0;68 69err:70 cifs_free_hash(&p->aes_cmac);71 cifs_free_hash(&p->hmacsha256);72 return rc;73}74 75 76static77int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)78{79 struct cifs_chan *chan;80 struct TCP_Server_Info *pserver;81 struct cifs_ses *ses = NULL;82 int i;83 int rc = 0;84 bool is_binding = false;85 86 spin_lock(&cifs_tcp_ses_lock);87 88 /* If server is a channel, select the primary channel */89 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;90 91 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {92 if (ses->Suid == ses_id)93 goto found;94 }95 trace_smb3_ses_not_found(ses_id);96 cifs_server_dbg(FYI, "%s: Could not find session 0x%llx\n",97 __func__, ses_id);98 rc = -ENOENT;99 goto out;100 101found:102 spin_lock(&ses->ses_lock);103 spin_lock(&ses->chan_lock);104 105 is_binding = (cifs_chan_needs_reconnect(ses, server) &&106 ses->ses_status == SES_GOOD);107 if (is_binding) {108 /*109 * If we are in the process of binding a new channel110 * to an existing session, use the master connection111 * session key112 */113 memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);114 spin_unlock(&ses->chan_lock);115 spin_unlock(&ses->ses_lock);116 goto out;117 }118 119 /*120 * Otherwise, use the channel key.121 */122 123 for (i = 0; i < ses->chan_count; i++) {124 chan = ses->chans + i;125 if (chan->server == server) {126 memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);127 spin_unlock(&ses->chan_lock);128 spin_unlock(&ses->ses_lock);129 goto out;130 }131 }132 spin_unlock(&ses->chan_lock);133 spin_unlock(&ses->ses_lock);134 135 cifs_dbg(VFS,136 "%s: Could not find channel signing key for session 0x%llx\n",137 __func__, ses_id);138 rc = -ENOENT;139 140out:141 spin_unlock(&cifs_tcp_ses_lock);142 return rc;143}144 145static struct cifs_ses *146smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)147{148 struct TCP_Server_Info *pserver;149 struct cifs_ses *ses;150 151 /* If server is a channel, select the primary channel */152 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;153 154 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {155 if (ses->Suid != ses_id)156 continue;157 158 spin_lock(&ses->ses_lock);159 if (ses->ses_status == SES_EXITING) {160 spin_unlock(&ses->ses_lock);161 continue;162 }163 cifs_smb_ses_inc_refcount(ses);164 spin_unlock(&ses->ses_lock);165 return ses;166 }167 168 return NULL;169}170 171struct cifs_ses *172smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)173{174 struct cifs_ses *ses;175 176 spin_lock(&cifs_tcp_ses_lock);177 ses = smb2_find_smb_ses_unlocked(server, ses_id);178 spin_unlock(&cifs_tcp_ses_lock);179 180 return ses;181}182 183static struct cifs_tcon *184smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)185{186 struct cifs_tcon *tcon;187 188 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {189 if (tcon->tid != tid)190 continue;191 ++tcon->tc_count;192 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,193 netfs_trace_tcon_ref_get_find_sess_tcon);194 return tcon;195 }196 197 return NULL;198}199 200/*201 * Obtain tcon corresponding to the tid in the given202 * cifs_ses203 */204 205struct cifs_tcon *206smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)207{208 struct cifs_ses *ses;209 struct cifs_tcon *tcon;210 211 spin_lock(&cifs_tcp_ses_lock);212 ses = smb2_find_smb_ses_unlocked(server, ses_id);213 if (!ses) {214 spin_unlock(&cifs_tcp_ses_lock);215 return NULL;216 }217 tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);218 if (!tcon) {219 spin_unlock(&cifs_tcp_ses_lock);220 cifs_put_smb_ses(ses);221 return NULL;222 }223 spin_unlock(&cifs_tcp_ses_lock);224 /* tcon already has a ref to ses, so we don't need ses anymore */225 cifs_put_smb_ses(ses);226 227 return tcon;228}229 230int231smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,232 bool allocate_crypto)233{234 int rc;235 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];236 unsigned char *sigptr = smb2_signature;237 struct kvec *iov = rqst->rq_iov;238 struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;239 struct cifs_ses *ses;240 struct shash_desc *shash = NULL;241 struct smb_rqst drqst;242 243 ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));244 if (unlikely(!ses)) {245 cifs_server_dbg(FYI, "%s: Could not find session\n", __func__);246 return -ENOENT;247 }248 249 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);250 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);251 252 if (allocate_crypto) {253 rc = cifs_alloc_hash("hmac(sha256)", &shash);254 if (rc) {255 cifs_server_dbg(VFS,256 "%s: sha256 alloc failed\n", __func__);257 goto out;258 }259 } else {260 shash = server->secmech.hmacsha256;261 }262 263 rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response,264 SMB2_NTLMV2_SESSKEY_SIZE);265 if (rc) {266 cifs_server_dbg(VFS,267 "%s: Could not update with response\n",268 __func__);269 goto out;270 }271 272 rc = crypto_shash_init(shash);273 if (rc) {274 cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);275 goto out;276 }277 278 /*279 * For SMB2+, __cifs_calc_signature() expects to sign only the actual280 * data, that is, iov[0] should not contain a rfc1002 length.281 *282 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to283 * __cifs_calc_signature().284 */285 drqst = *rqst;286 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {287 rc = crypto_shash_update(shash, iov[0].iov_base,288 iov[0].iov_len);289 if (rc) {290 cifs_server_dbg(VFS,291 "%s: Could not update with payload\n",292 __func__);293 goto out;294 }295 drqst.rq_iov++;296 drqst.rq_nvec--;297 }298 299 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);300 if (!rc)301 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);302 303out:304 if (allocate_crypto)305 cifs_free_hash(&shash);306 if (ses)307 cifs_put_smb_ses(ses);308 return rc;309}310 311static int generate_key(struct cifs_ses *ses, struct kvec label,312 struct kvec context, __u8 *key, unsigned int key_size)313{314 unsigned char zero = 0x0;315 __u8 i[4] = {0, 0, 0, 1};316 __u8 L128[4] = {0, 0, 0, 128};317 __u8 L256[4] = {0, 0, 1, 0};318 int rc = 0;319 unsigned char prfhash[SMB2_HMACSHA256_SIZE];320 unsigned char *hashptr = prfhash;321 struct TCP_Server_Info *server = ses->server;322 323 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);324 memset(key, 0x0, key_size);325 326 rc = smb3_crypto_shash_allocate(server);327 if (rc) {328 cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);329 goto smb3signkey_ret;330 }331 332 rc = crypto_shash_setkey(server->secmech.hmacsha256->tfm,333 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);334 if (rc) {335 cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);336 goto smb3signkey_ret;337 }338 339 rc = crypto_shash_init(server->secmech.hmacsha256);340 if (rc) {341 cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);342 goto smb3signkey_ret;343 }344 345 rc = crypto_shash_update(server->secmech.hmacsha256, i, 4);346 if (rc) {347 cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);348 goto smb3signkey_ret;349 }350 351 rc = crypto_shash_update(server->secmech.hmacsha256, label.iov_base, label.iov_len);352 if (rc) {353 cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);354 goto smb3signkey_ret;355 }356 357 rc = crypto_shash_update(server->secmech.hmacsha256, &zero, 1);358 if (rc) {359 cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);360 goto smb3signkey_ret;361 }362 363 rc = crypto_shash_update(server->secmech.hmacsha256, context.iov_base, context.iov_len);364 if (rc) {365 cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);366 goto smb3signkey_ret;367 }368 369 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||370 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {371 rc = crypto_shash_update(server->secmech.hmacsha256, L256, 4);372 } else {373 rc = crypto_shash_update(server->secmech.hmacsha256, L128, 4);374 }375 if (rc) {376 cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);377 goto smb3signkey_ret;378 }379 380 rc = crypto_shash_final(server->secmech.hmacsha256, hashptr);381 if (rc) {382 cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);383 goto smb3signkey_ret;384 }385 386 memcpy(key, hashptr, key_size);387 388smb3signkey_ret:389 return rc;390}391 392struct derivation {393 struct kvec label;394 struct kvec context;395};396 397struct derivation_triplet {398 struct derivation signing;399 struct derivation encryption;400 struct derivation decryption;401};402 403static int404generate_smb3signingkey(struct cifs_ses *ses,405 struct TCP_Server_Info *server,406 const struct derivation_triplet *ptriplet)407{408 int rc;409 bool is_binding = false;410 int chan_index = 0;411 412 spin_lock(&ses->ses_lock);413 spin_lock(&ses->chan_lock);414 is_binding = (cifs_chan_needs_reconnect(ses, server) &&415 ses->ses_status == SES_GOOD);416 417 chan_index = cifs_ses_get_chan_index(ses, server);418 if (chan_index == CIFS_INVAL_CHAN_INDEX) {419 spin_unlock(&ses->chan_lock);420 spin_unlock(&ses->ses_lock);421 422 return -EINVAL;423 }424 425 spin_unlock(&ses->chan_lock);426 spin_unlock(&ses->ses_lock);427 428 /*429 * All channels use the same encryption/decryption keys but430 * they have their own signing key.431 *432 * When we generate the keys, check if it is for a new channel433 * (binding) in which case we only need to generate a signing434 * key and store it in the channel as to not overwrite the435 * master connection signing key stored in the session436 */437 438 if (is_binding) {439 rc = generate_key(ses, ptriplet->signing.label,440 ptriplet->signing.context,441 ses->chans[chan_index].signkey,442 SMB3_SIGN_KEY_SIZE);443 if (rc)444 return rc;445 } else {446 rc = generate_key(ses, ptriplet->signing.label,447 ptriplet->signing.context,448 ses->smb3signingkey,449 SMB3_SIGN_KEY_SIZE);450 if (rc)451 return rc;452 453 /* safe to access primary channel, since it will never go away */454 spin_lock(&ses->chan_lock);455 memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,456 SMB3_SIGN_KEY_SIZE);457 spin_unlock(&ses->chan_lock);458 459 rc = generate_key(ses, ptriplet->encryption.label,460 ptriplet->encryption.context,461 ses->smb3encryptionkey,462 SMB3_ENC_DEC_KEY_SIZE);463 if (rc)464 return rc;465 rc = generate_key(ses, ptriplet->decryption.label,466 ptriplet->decryption.context,467 ses->smb3decryptionkey,468 SMB3_ENC_DEC_KEY_SIZE);469 if (rc)470 return rc;471 }472 473#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS474 cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);475 /*476 * The session id is opaque in terms of endianness, so we can't477 * print it as a long long. we dump it as we got it on the wire478 */479 cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),480 &ses->Suid);481 cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);482 cifs_dbg(VFS, "Session Key %*ph\n",483 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);484 cifs_dbg(VFS, "Signing Key %*ph\n",485 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);486 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||487 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {488 cifs_dbg(VFS, "ServerIn Key %*ph\n",489 SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);490 cifs_dbg(VFS, "ServerOut Key %*ph\n",491 SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);492 } else {493 cifs_dbg(VFS, "ServerIn Key %*ph\n",494 SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);495 cifs_dbg(VFS, "ServerOut Key %*ph\n",496 SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);497 }498#endif499 return rc;500}501 502int503generate_smb30signingkey(struct cifs_ses *ses,504 struct TCP_Server_Info *server)505 506{507 struct derivation_triplet triplet;508 struct derivation *d;509 510 d = &triplet.signing;511 d->label.iov_base = "SMB2AESCMAC";512 d->label.iov_len = 12;513 d->context.iov_base = "SmbSign";514 d->context.iov_len = 8;515 516 d = &triplet.encryption;517 d->label.iov_base = "SMB2AESCCM";518 d->label.iov_len = 11;519 d->context.iov_base = "ServerIn ";520 d->context.iov_len = 10;521 522 d = &triplet.decryption;523 d->label.iov_base = "SMB2AESCCM";524 d->label.iov_len = 11;525 d->context.iov_base = "ServerOut";526 d->context.iov_len = 10;527 528 return generate_smb3signingkey(ses, server, &triplet);529}530 531int532generate_smb311signingkey(struct cifs_ses *ses,533 struct TCP_Server_Info *server)534 535{536 struct derivation_triplet triplet;537 struct derivation *d;538 539 d = &triplet.signing;540 d->label.iov_base = "SMBSigningKey";541 d->label.iov_len = 14;542 d->context.iov_base = ses->preauth_sha_hash;543 d->context.iov_len = 64;544 545 d = &triplet.encryption;546 d->label.iov_base = "SMBC2SCipherKey";547 d->label.iov_len = 16;548 d->context.iov_base = ses->preauth_sha_hash;549 d->context.iov_len = 64;550 551 d = &triplet.decryption;552 d->label.iov_base = "SMBS2CCipherKey";553 d->label.iov_len = 16;554 d->context.iov_base = ses->preauth_sha_hash;555 d->context.iov_len = 64;556 557 return generate_smb3signingkey(ses, server, &triplet);558}559 560int561smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,562 bool allocate_crypto)563{564 int rc;565 unsigned char smb3_signature[SMB2_CMACAES_SIZE];566 unsigned char *sigptr = smb3_signature;567 struct kvec *iov = rqst->rq_iov;568 struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;569 struct shash_desc *shash = NULL;570 struct smb_rqst drqst;571 u8 key[SMB3_SIGN_KEY_SIZE];572 573 rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);574 if (unlikely(rc)) {575 cifs_server_dbg(FYI, "%s: Could not get signing key\n", __func__);576 return rc;577 }578 579 if (allocate_crypto) {580 rc = cifs_alloc_hash("cmac(aes)", &shash);581 if (rc)582 return rc;583 } else {584 shash = server->secmech.aes_cmac;585 }586 587 memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);588 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);589 590 rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);591 if (rc) {592 cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);593 goto out;594 }595 596 /*597 * we already allocate aes_cmac when we init smb3 signing key,598 * so unlike smb2 case we do not have to check here if secmech are599 * initialized600 */601 rc = crypto_shash_init(shash);602 if (rc) {603 cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);604 goto out;605 }606 607 /*608 * For SMB2+, __cifs_calc_signature() expects to sign only the actual609 * data, that is, iov[0] should not contain a rfc1002 length.610 *611 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to612 * __cifs_calc_signature().613 */614 drqst = *rqst;615 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {616 rc = crypto_shash_update(shash, iov[0].iov_base,617 iov[0].iov_len);618 if (rc) {619 cifs_server_dbg(VFS, "%s: Could not update with payload\n",620 __func__);621 goto out;622 }623 drqst.rq_iov++;624 drqst.rq_nvec--;625 }626 627 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);628 if (!rc)629 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);630 631out:632 if (allocate_crypto)633 cifs_free_hash(&shash);634 return rc;635}636 637/* must be called with server->srv_mutex held */638static int639smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)640{641 int rc = 0;642 struct smb2_hdr *shdr;643 struct smb2_sess_setup_req *ssr;644 bool is_binding;645 bool is_signed;646 647 shdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;648 ssr = (struct smb2_sess_setup_req *)shdr;649 650 is_binding = shdr->Command == SMB2_SESSION_SETUP &&651 (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);652 is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;653 654 if (!is_signed)655 return 0;656 spin_lock(&server->srv_lock);657 if (server->ops->need_neg &&658 server->ops->need_neg(server)) {659 spin_unlock(&server->srv_lock);660 return 0;661 }662 spin_unlock(&server->srv_lock);663 if (!is_binding && !server->session_estab) {664 strscpy(shdr->Signature, "BSRSPYL");665 return 0;666 }667 668 rc = server->ops->calc_signature(rqst, server, false);669 670 return rc;671}672 673int674smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)675{676 unsigned int rc;677 char server_response_sig[SMB2_SIGNATURE_SIZE];678 struct smb2_hdr *shdr =679 (struct smb2_hdr *)rqst->rq_iov[0].iov_base;680 681 if ((shdr->Command == SMB2_NEGOTIATE) ||682 (shdr->Command == SMB2_SESSION_SETUP) ||683 (shdr->Command == SMB2_OPLOCK_BREAK) ||684 server->ignore_signature ||685 (!server->session_estab))686 return 0;687 688 /*689 * BB what if signatures are supposed to be on for session but690 * server does not send one? BB691 */692 693 /* Do not need to verify session setups with signature "BSRSPYL " */694 if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)695 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",696 shdr->Command);697 698 /*699 * Save off the original signature so we can modify the smb and check700 * our calculated signature against what the server sent.701 */702 memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);703 704 memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);705 706 rc = server->ops->calc_signature(rqst, server, true);707 708 if (rc)709 return rc;710 711 if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {712 cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",713 shdr->Command, shdr->MessageId);714 return -EACCES;715 } else716 return 0;717}718 719/*720 * Set message id for the request. Should be called after wait_for_free_request721 * and when srv_mutex is held.722 */723static inline void724smb2_seq_num_into_buf(struct TCP_Server_Info *server,725 struct smb2_hdr *shdr)726{727 unsigned int i, num = le16_to_cpu(shdr->CreditCharge);728 729 shdr->MessageId = get_next_mid64(server);730 /* skip message numbers according to CreditCharge field */731 for (i = 1; i < num; i++)732 get_next_mid(server);733}734 735static struct mid_q_entry *736smb2_mid_entry_alloc(const struct smb2_hdr *shdr,737 struct TCP_Server_Info *server)738{739 struct mid_q_entry *temp;740 unsigned int credits = le16_to_cpu(shdr->CreditCharge);741 742 if (server == NULL) {743 cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");744 return NULL;745 }746 747 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);748 memset(temp, 0, sizeof(struct mid_q_entry));749 kref_init(&temp->refcount);750 temp->mid = le64_to_cpu(shdr->MessageId);751 temp->credits = credits > 0 ? credits : 1;752 temp->pid = current->pid;753 temp->command = shdr->Command; /* Always LE */754 temp->when_alloc = jiffies;755 temp->server = server;756 757 /*758 * The default is for the mid to be synchronous, so the759 * default callback just wakes up the current task.760 */761 get_task_struct(current);762 temp->creator = current;763 temp->callback = cifs_wake_up_task;764 temp->callback_data = current;765 766 atomic_inc(&mid_count);767 temp->mid_state = MID_REQUEST_ALLOCATED;768 trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId),769 le64_to_cpu(shdr->SessionId),770 le16_to_cpu(shdr->Command), temp->mid);771 return temp;772}773 774static int775smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,776 struct smb2_hdr *shdr, struct mid_q_entry **mid)777{778 spin_lock(&server->srv_lock);779 if (server->tcpStatus == CifsExiting) {780 spin_unlock(&server->srv_lock);781 return -ENOENT;782 }783 784 if (server->tcpStatus == CifsNeedReconnect) {785 spin_unlock(&server->srv_lock);786 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");787 return -EAGAIN;788 }789 790 if (server->tcpStatus == CifsNeedNegotiate &&791 shdr->Command != SMB2_NEGOTIATE) {792 spin_unlock(&server->srv_lock);793 return -EAGAIN;794 }795 spin_unlock(&server->srv_lock);796 797 spin_lock(&ses->ses_lock);798 if (ses->ses_status == SES_NEW) {799 if ((shdr->Command != SMB2_SESSION_SETUP) &&800 (shdr->Command != SMB2_NEGOTIATE)) {801 spin_unlock(&ses->ses_lock);802 return -EAGAIN;803 }804 /* else ok - we are setting up session */805 }806 807 if (ses->ses_status == SES_EXITING) {808 if (shdr->Command != SMB2_LOGOFF) {809 spin_unlock(&ses->ses_lock);810 return -EAGAIN;811 }812 /* else ok - we are shutting down the session */813 }814 spin_unlock(&ses->ses_lock);815 816 *mid = smb2_mid_entry_alloc(shdr, server);817 if (*mid == NULL)818 return -ENOMEM;819 spin_lock(&server->mid_lock);820 list_add_tail(&(*mid)->qhead, &server->pending_mid_q);821 spin_unlock(&server->mid_lock);822 823 return 0;824}825 826int827smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,828 bool log_error)829{830 unsigned int len = mid->resp_buf_size;831 struct kvec iov[1];832 struct smb_rqst rqst = { .rq_iov = iov,833 .rq_nvec = 1 };834 835 iov[0].iov_base = (char *)mid->resp_buf;836 iov[0].iov_len = len;837 838 dump_smb(mid->resp_buf, min_t(u32, 80, len));839 /* convert the length into a more usable form */840 if (len > 24 && server->sign && !mid->decrypted) {841 int rc;842 843 rc = smb2_verify_signature(&rqst, server);844 if (rc)845 cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",846 rc);847 }848 849 return map_smb2_to_linux_error(mid->resp_buf, log_error);850}851 852struct mid_q_entry *853smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,854 struct smb_rqst *rqst)855{856 int rc;857 struct smb2_hdr *shdr =858 (struct smb2_hdr *)rqst->rq_iov[0].iov_base;859 struct mid_q_entry *mid;860 861 smb2_seq_num_into_buf(server, shdr);862 863 rc = smb2_get_mid_entry(ses, server, shdr, &mid);864 if (rc) {865 revert_current_mid_from_hdr(server, shdr);866 return ERR_PTR(rc);867 }868 869 rc = smb2_sign_rqst(rqst, server);870 if (rc) {871 revert_current_mid_from_hdr(server, shdr);872 delete_mid(mid);873 return ERR_PTR(rc);874 }875 876 return mid;877}878 879struct mid_q_entry *880smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)881{882 int rc;883 struct smb2_hdr *shdr =884 (struct smb2_hdr *)rqst->rq_iov[0].iov_base;885 struct mid_q_entry *mid;886 887 spin_lock(&server->srv_lock);888 if (server->tcpStatus == CifsNeedNegotiate &&889 shdr->Command != SMB2_NEGOTIATE) {890 spin_unlock(&server->srv_lock);891 return ERR_PTR(-EAGAIN);892 }893 spin_unlock(&server->srv_lock);894 895 smb2_seq_num_into_buf(server, shdr);896 897 mid = smb2_mid_entry_alloc(shdr, server);898 if (mid == NULL) {899 revert_current_mid_from_hdr(server, shdr);900 return ERR_PTR(-ENOMEM);901 }902 903 rc = smb2_sign_rqst(rqst, server);904 if (rc) {905 revert_current_mid_from_hdr(server, shdr);906 release_mid(mid);907 return ERR_PTR(rc);908 }909 910 return mid;911}912 913int914smb3_crypto_aead_allocate(struct TCP_Server_Info *server)915{916 struct crypto_aead *tfm;917 918 if (!server->secmech.enc) {919 if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||920 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))921 tfm = crypto_alloc_aead("gcm(aes)", 0, 0);922 else923 tfm = crypto_alloc_aead("ccm(aes)", 0, 0);924 if (IS_ERR(tfm)) {925 cifs_server_dbg(VFS, "%s: Failed alloc encrypt aead\n",926 __func__);927 return PTR_ERR(tfm);928 }929 server->secmech.enc = tfm;930 }931 932 if (!server->secmech.dec) {933 if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||934 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))935 tfm = crypto_alloc_aead("gcm(aes)", 0, 0);936 else937 tfm = crypto_alloc_aead("ccm(aes)", 0, 0);938 if (IS_ERR(tfm)) {939 crypto_free_aead(server->secmech.enc);940 server->secmech.enc = NULL;941 cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",942 __func__);943 return PTR_ERR(tfm);944 }945 server->secmech.dec = tfm;946 }947 948 return 0;949}950