~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cifs/smb2transport.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *   fs/cifs/smb2transport.c
  3  *
  4  *   Copyright (C) International Business Machines  Corp., 2002, 2011
  5  *                 Etersoft, 2012
  6  *   Author(s): Steve French (sfrench@us.ibm.com)
  7  *              Jeremy Allison (jra@samba.org) 2006
  8  *              Pavel Shilovsky (pshilovsky@samba.org) 2012
  9  *
 10  *   This library is free software; you can redistribute it and/or modify
 11  *   it under the terms of the GNU Lesser General Public License as published
 12  *   by the Free Software Foundation; either version 2.1 of the License, or
 13  *   (at your option) any later version.
 14  *
 15  *   This library is distributed in the hope that it will be useful,
 16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 18  *   the GNU Lesser General Public License for more details.
 19  *
 20  *   You should have received a copy of the GNU Lesser General Public License
 21  *   along with this library; if not, write to the Free Software
 22  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 23  */
 24 
 25 #include <linux/fs.h>
 26 #include <linux/list.h>
 27 #include <linux/wait.h>
 28 #include <linux/net.h>
 29 #include <linux/delay.h>
 30 #include <linux/uaccess.h>
 31 #include <asm/processor.h>
 32 #include <linux/mempool.h>
 33 #include <linux/highmem.h>
 34 #include <crypto/aead.h>
 35 #include "smb2pdu.h"
 36 #include "cifsglob.h"
 37 #include "cifsproto.h"
 38 #include "smb2proto.h"
 39 #include "cifs_debug.h"
 40 #include "smb2status.h"
 41 #include "smb2glob.h"
 42 
 43 static int
 44 smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
 45 {
 46         int rc;
 47         unsigned int size;
 48 
 49         if (server->secmech.sdeschmacsha256 != NULL)
 50                 return 0; /* already allocated */
 51 
 52         server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
 53         if (IS_ERR(server->secmech.hmacsha256)) {
 54                 cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
 55                 rc = PTR_ERR(server->secmech.hmacsha256);
 56                 server->secmech.hmacsha256 = NULL;
 57                 return rc;
 58         }
 59 
 60         size = sizeof(struct shash_desc) +
 61                         crypto_shash_descsize(server->secmech.hmacsha256);
 62         server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
 63         if (!server->secmech.sdeschmacsha256) {
 64                 crypto_free_shash(server->secmech.hmacsha256);
 65                 server->secmech.hmacsha256 = NULL;
 66                 return -ENOMEM;
 67         }
 68         server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
 69         server->secmech.sdeschmacsha256->shash.flags = 0x0;
 70 
 71         return 0;
 72 }
 73 
 74 static int
 75 smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
 76 {
 77         unsigned int size;
 78         int rc;
 79 
 80         if (server->secmech.sdesccmacaes != NULL)
 81                 return 0;  /* already allocated */
 82 
 83         rc = smb2_crypto_shash_allocate(server);
 84         if (rc)
 85                 return rc;
 86 
 87         server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
 88         if (IS_ERR(server->secmech.cmacaes)) {
 89                 cifs_dbg(VFS, "could not allocate crypto cmac-aes");
 90                 kfree(server->secmech.sdeschmacsha256);
 91                 server->secmech.sdeschmacsha256 = NULL;
 92                 crypto_free_shash(server->secmech.hmacsha256);
 93                 server->secmech.hmacsha256 = NULL;
 94                 rc = PTR_ERR(server->secmech.cmacaes);
 95                 server->secmech.cmacaes = NULL;
 96                 return rc;
 97         }
 98 
 99         size = sizeof(struct shash_desc) +
100                         crypto_shash_descsize(server->secmech.cmacaes);
101         server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
102         if (!server->secmech.sdesccmacaes) {
103                 cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
104                 kfree(server->secmech.sdeschmacsha256);
105                 server->secmech.sdeschmacsha256 = NULL;
106                 crypto_free_shash(server->secmech.hmacsha256);
107                 crypto_free_shash(server->secmech.cmacaes);
108                 server->secmech.hmacsha256 = NULL;
109                 server->secmech.cmacaes = NULL;
110                 return -ENOMEM;
111         }
112         server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
113         server->secmech.sdesccmacaes->shash.flags = 0x0;
114 
115         return 0;
116 }
117 
118 static struct cifs_ses *
119 smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
120 {
121         struct cifs_ses *ses;
122 
123         list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
124                 if (ses->Suid != ses_id)
125                         continue;
126                 return ses;
127         }
128 
129         return NULL;
130 }
131 
132 struct cifs_ses *
133 smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
134 {
135         struct cifs_ses *ses;
136 
137         spin_lock(&cifs_tcp_ses_lock);
138         ses = smb2_find_smb_ses_unlocked(server, ses_id);
139         spin_unlock(&cifs_tcp_ses_lock);
140 
141         return ses;
142 }
143 
144 static struct cifs_tcon *
145 smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
146 {
147         struct cifs_tcon *tcon;
148 
149         list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
150                 if (tcon->tid != tid)
151                         continue;
152                 ++tcon->tc_count;
153                 return tcon;
154         }
155 
156         return NULL;
157 }
158 
159 /*
160  * Obtain tcon corresponding to the tid in the given
161  * cifs_ses
162  */
163 
164 struct cifs_tcon *
165 smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32  tid)
166 {
167         struct cifs_ses *ses;
168         struct cifs_tcon *tcon;
169 
170         spin_lock(&cifs_tcp_ses_lock);
171         ses = smb2_find_smb_ses_unlocked(server, ses_id);
172         if (!ses) {
173                 spin_unlock(&cifs_tcp_ses_lock);
174                 return NULL;
175         }
176         tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
177         spin_unlock(&cifs_tcp_ses_lock);
178 
179         return tcon;
180 }
181 
182 int
183 smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
184 {
185         int rc;
186         unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
187         unsigned char *sigptr = smb2_signature;
188         struct kvec *iov = rqst->rq_iov;
189         struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
190         struct cifs_ses *ses;
191 
192         ses = smb2_find_smb_ses(server, shdr->SessionId);
193         if (!ses) {
194                 cifs_dbg(VFS, "%s: Could not find session\n", __func__);
195                 return 0;
196         }
197 
198         memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
199         memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
200 
201         rc = smb2_crypto_shash_allocate(server);
202         if (rc) {
203                 cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__);
204                 return rc;
205         }
206 
207         rc = crypto_shash_setkey(server->secmech.hmacsha256,
208                 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
209         if (rc) {
210                 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
211                 return rc;
212         }
213 
214         rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
215         if (rc) {
216                 cifs_dbg(VFS, "%s: Could not init sha256", __func__);
217                 return rc;
218         }
219 
220         rc = __cifs_calc_signature(rqst, server, sigptr,
221                 &server->secmech.sdeschmacsha256->shash);
222 
223         if (!rc)
224                 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
225 
226         return rc;
227 }
228 
229 static int generate_key(struct cifs_ses *ses, struct kvec label,
230                         struct kvec context, __u8 *key, unsigned int key_size)
231 {
232         unsigned char zero = 0x0;
233         __u8 i[4] = {0, 0, 0, 1};
234         __u8 L[4] = {0, 0, 0, 128};
235         int rc = 0;
236         unsigned char prfhash[SMB2_HMACSHA256_SIZE];
237         unsigned char *hashptr = prfhash;
238 
239         memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
240         memset(key, 0x0, key_size);
241 
242         rc = smb3_crypto_shash_allocate(ses->server);
243         if (rc) {
244                 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
245                 goto smb3signkey_ret;
246         }
247 
248         rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
249                 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
250         if (rc) {
251                 cifs_dbg(VFS, "%s: Could not set with session key\n", __func__);
252                 goto smb3signkey_ret;
253         }
254 
255         rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
256         if (rc) {
257                 cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
258                 goto smb3signkey_ret;
259         }
260 
261         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
262                                 i, 4);
263         if (rc) {
264                 cifs_dbg(VFS, "%s: Could not update with n\n", __func__);
265                 goto smb3signkey_ret;
266         }
267 
268         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
269                                 label.iov_base, label.iov_len);
270         if (rc) {
271                 cifs_dbg(VFS, "%s: Could not update with label\n", __func__);
272                 goto smb3signkey_ret;
273         }
274 
275         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
276                                 &zero, 1);
277         if (rc) {
278                 cifs_dbg(VFS, "%s: Could not update with zero\n", __func__);
279                 goto smb3signkey_ret;
280         }
281 
282         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
283                                 context.iov_base, context.iov_len);
284         if (rc) {
285                 cifs_dbg(VFS, "%s: Could not update with context\n", __func__);
286                 goto smb3signkey_ret;
287         }
288 
289         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
290                                 L, 4);
291         if (rc) {
292                 cifs_dbg(VFS, "%s: Could not update with L\n", __func__);
293                 goto smb3signkey_ret;
294         }
295 
296         rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
297                                 hashptr);
298         if (rc) {
299                 cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
300                 goto smb3signkey_ret;
301         }
302 
303         memcpy(key, hashptr, key_size);
304 
305 smb3signkey_ret:
306         return rc;
307 }
308 
309 struct derivation {
310         struct kvec label;
311         struct kvec context;
312 };
313 
314 struct derivation_triplet {
315         struct derivation signing;
316         struct derivation encryption;
317         struct derivation decryption;
318 };
319 
320 static int
321 generate_smb3signingkey(struct cifs_ses *ses,
322                         const struct derivation_triplet *ptriplet)
323 {
324         int rc;
325 
326         rc = generate_key(ses, ptriplet->signing.label,
327                           ptriplet->signing.context, ses->smb3signingkey,
328                           SMB3_SIGN_KEY_SIZE);
329         if (rc)
330                 return rc;
331 
332         rc = generate_key(ses, ptriplet->encryption.label,
333                           ptriplet->encryption.context, ses->smb3encryptionkey,
334                           SMB3_SIGN_KEY_SIZE);
335         if (rc)
336                 return rc;
337 
338         return generate_key(ses, ptriplet->decryption.label,
339                             ptriplet->decryption.context,
340                             ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
341 }
342 
343 int
344 generate_smb30signingkey(struct cifs_ses *ses)
345 
346 {
347         struct derivation_triplet triplet;
348         struct derivation *d;
349 
350         d = &triplet.signing;
351         d->label.iov_base = "SMB2AESCMAC";
352         d->label.iov_len = 12;
353         d->context.iov_base = "SmbSign";
354         d->context.iov_len = 8;
355 
356         d = &triplet.encryption;
357         d->label.iov_base = "SMB2AESCCM";
358         d->label.iov_len = 11;
359         d->context.iov_base = "ServerIn ";
360         d->context.iov_len = 10;
361 
362         d = &triplet.decryption;
363         d->label.iov_base = "SMB2AESCCM";
364         d->label.iov_len = 11;
365         d->context.iov_base = "ServerOut";
366         d->context.iov_len = 10;
367 
368         return generate_smb3signingkey(ses, &triplet);
369 }
370 
371 int
372 generate_smb311signingkey(struct cifs_ses *ses)
373 
374 {
375         struct derivation_triplet triplet;
376         struct derivation *d;
377 
378         d = &triplet.signing;
379         d->label.iov_base = "SMB2AESCMAC";
380         d->label.iov_len = 12;
381         d->context.iov_base = "SmbSign";
382         d->context.iov_len = 8;
383 
384         d = &triplet.encryption;
385         d->label.iov_base = "SMB2AESCCM";
386         d->label.iov_len = 11;
387         d->context.iov_base = "ServerIn ";
388         d->context.iov_len = 10;
389 
390         d = &triplet.decryption;
391         d->label.iov_base = "SMB2AESCCM";
392         d->label.iov_len = 11;
393         d->context.iov_base = "ServerOut";
394         d->context.iov_len = 10;
395 
396         return generate_smb3signingkey(ses, &triplet);
397 }
398 
399 int
400 smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
401 {
402         int rc = 0;
403         unsigned char smb3_signature[SMB2_CMACAES_SIZE];
404         unsigned char *sigptr = smb3_signature;
405         struct kvec *iov = rqst->rq_iov;
406         struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
407         struct cifs_ses *ses;
408 
409         ses = smb2_find_smb_ses(server, shdr->SessionId);
410         if (!ses) {
411                 cifs_dbg(VFS, "%s: Could not find session\n", __func__);
412                 return 0;
413         }
414 
415         memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
416         memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
417 
418         rc = crypto_shash_setkey(server->secmech.cmacaes,
419                 ses->smb3signingkey, SMB2_CMACAES_SIZE);
420 
421         if (rc) {
422                 cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
423                 return rc;
424         }
425 
426         /*
427          * we already allocate sdesccmacaes when we init smb3 signing key,
428          * so unlike smb2 case we do not have to check here if secmech are
429          * initialized
430          */
431         rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
432         if (rc) {
433                 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
434                 return rc;
435         }
436         
437         rc = __cifs_calc_signature(rqst, server, sigptr,
438                                    &server->secmech.sdesccmacaes->shash);
439 
440         if (!rc)
441                 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
442 
443         return rc;
444 }
445 
446 /* must be called with server->srv_mutex held */
447 static int
448 smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
449 {
450         int rc = 0;
451         struct smb2_sync_hdr *shdr =
452                         (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
453 
454         if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
455             server->tcpStatus == CifsNeedNegotiate)
456                 return rc;
457 
458         if (!server->session_estab) {
459                 strncpy(shdr->Signature, "BSRSPYL", 8);
460                 return rc;
461         }
462 
463         rc = server->ops->calc_signature(rqst, server);
464 
465         return rc;
466 }
467 
468 int
469 smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
470 {
471         unsigned int rc;
472         char server_response_sig[16];
473         struct smb2_sync_hdr *shdr =
474                         (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
475 
476         if ((shdr->Command == SMB2_NEGOTIATE) ||
477             (shdr->Command == SMB2_SESSION_SETUP) ||
478             (shdr->Command == SMB2_OPLOCK_BREAK) ||
479             (!server->session_estab))
480                 return 0;
481 
482         /*
483          * BB what if signatures are supposed to be on for session but
484          * server does not send one? BB
485          */
486 
487         /* Do not need to verify session setups with signature "BSRSPYL " */
488         if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
489                 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
490                          shdr->Command);
491 
492         /*
493          * Save off the origiginal signature so we can modify the smb and check
494          * our calculated signature against what the server sent.
495          */
496         memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
497 
498         memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
499 
500         mutex_lock(&server->srv_mutex);
501         rc = server->ops->calc_signature(rqst, server);
502         mutex_unlock(&server->srv_mutex);
503 
504         if (rc)
505                 return rc;
506 
507         if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE))
508                 return -EACCES;
509         else
510                 return 0;
511 }
512 
513 /*
514  * Set message id for the request. Should be called after wait_for_free_request
515  * and when srv_mutex is held.
516  */
517 static inline void
518 smb2_seq_num_into_buf(struct TCP_Server_Info *server,
519                       struct smb2_sync_hdr *shdr)
520 {
521         unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
522 
523         shdr->MessageId = get_next_mid64(server);
524         /* skip message numbers according to CreditCharge field */
525         for (i = 1; i < num; i++)
526                 get_next_mid(server);
527 }
528 
529 static struct mid_q_entry *
530 smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
531                      struct TCP_Server_Info *server)
532 {
533         struct mid_q_entry *temp;
534 
535         if (server == NULL) {
536                 cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
537                 return NULL;
538         }
539 
540         temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
541         if (temp == NULL)
542                 return temp;
543         else {
544                 memset(temp, 0, sizeof(struct mid_q_entry));
545                 temp->mid = le64_to_cpu(shdr->MessageId);
546                 temp->pid = current->pid;
547                 temp->command = shdr->Command; /* Always LE */
548                 temp->when_alloc = jiffies;
549                 temp->server = server;
550 
551                 /*
552                  * The default is for the mid to be synchronous, so the
553                  * default callback just wakes up the current task.
554                  */
555                 temp->callback = cifs_wake_up_task;
556                 temp->callback_data = current;
557         }
558 
559         atomic_inc(&midCount);
560         temp->mid_state = MID_REQUEST_ALLOCATED;
561         return temp;
562 }
563 
564 static int
565 smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_sync_hdr *shdr,
566                    struct mid_q_entry **mid)
567 {
568         if (ses->server->tcpStatus == CifsExiting)
569                 return -ENOENT;
570 
571         if (ses->server->tcpStatus == CifsNeedReconnect) {
572                 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
573                 return -EAGAIN;
574         }
575 
576         if (ses->status == CifsNew) {
577                 if ((shdr->Command != SMB2_SESSION_SETUP) &&
578                     (shdr->Command != SMB2_NEGOTIATE))
579                         return -EAGAIN;
580                 /* else ok - we are setting up session */
581         }
582 
583         if (ses->status == CifsExiting) {
584                 if (shdr->Command != SMB2_LOGOFF)
585                         return -EAGAIN;
586                 /* else ok - we are shutting down the session */
587         }
588 
589         *mid = smb2_mid_entry_alloc(shdr, ses->server);
590         if (*mid == NULL)
591                 return -ENOMEM;
592         spin_lock(&GlobalMid_Lock);
593         list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
594         spin_unlock(&GlobalMid_Lock);
595         return 0;
596 }
597 
598 int
599 smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
600                    bool log_error)
601 {
602         unsigned int len = get_rfc1002_length(mid->resp_buf);
603         struct kvec iov[2];
604         struct smb_rqst rqst = { .rq_iov = iov,
605                                  .rq_nvec = 2 };
606 
607         iov[0].iov_base = (char *)mid->resp_buf;
608         iov[0].iov_len = 4;
609         iov[1].iov_base = (char *)mid->resp_buf + 4;
610         iov[1].iov_len = len;
611 
612         dump_smb(mid->resp_buf, min_t(u32, 80, len));
613         /* convert the length into a more usable form */
614         if (len > 24 && server->sign && !mid->decrypted) {
615                 int rc;
616 
617                 rc = smb2_verify_signature(&rqst, server);
618                 if (rc)
619                         cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
620                                  rc);
621         }
622 
623         return map_smb2_to_linux_error(mid->resp_buf, log_error);
624 }
625 
626 struct mid_q_entry *
627 smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
628 {
629         int rc;
630         struct smb2_sync_hdr *shdr =
631                         (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
632         struct mid_q_entry *mid;
633 
634         smb2_seq_num_into_buf(ses->server, shdr);
635 
636         rc = smb2_get_mid_entry(ses, shdr, &mid);
637         if (rc)
638                 return ERR_PTR(rc);
639         rc = smb2_sign_rqst(rqst, ses->server);
640         if (rc) {
641                 cifs_delete_mid(mid);
642                 return ERR_PTR(rc);
643         }
644         return mid;
645 }
646 
647 struct mid_q_entry *
648 smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
649 {
650         int rc;
651         struct smb2_sync_hdr *shdr =
652                         (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
653         struct mid_q_entry *mid;
654 
655         smb2_seq_num_into_buf(server, shdr);
656 
657         mid = smb2_mid_entry_alloc(shdr, server);
658         if (mid == NULL)
659                 return ERR_PTR(-ENOMEM);
660 
661         rc = smb2_sign_rqst(rqst, server);
662         if (rc) {
663                 DeleteMidQEntry(mid);
664                 return ERR_PTR(rc);
665         }
666 
667         return mid;
668 }
669 
670 int
671 smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
672 {
673         struct crypto_aead *tfm;
674 
675         if (!server->secmech.ccmaesencrypt) {
676                 tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
677                 if (IS_ERR(tfm)) {
678                         cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
679                                  __func__);
680                         return PTR_ERR(tfm);
681                 }
682                 server->secmech.ccmaesencrypt = tfm;
683         }
684 
685         if (!server->secmech.ccmaesdecrypt) {
686                 tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
687                 if (IS_ERR(tfm)) {
688                         crypto_free_aead(server->secmech.ccmaesencrypt);
689                         server->secmech.ccmaesencrypt = NULL;
690                         cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
691                                  __func__);
692                         return PTR_ERR(tfm);
693                 }
694                 server->secmech.ccmaesdecrypt = tfm;
695         }
696 
697         return 0;
698 }
699 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp