~ [ 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 "smb2pdu.h"
 35 #include "cifsglob.h"
 36 #include "cifsproto.h"
 37 #include "smb2proto.h"
 38 #include "cifs_debug.h"
 39 #include "smb2status.h"
 40 #include "smb2glob.h"
 41 
 42 static int
 43 smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
 44 {
 45         int rc;
 46         unsigned int size;
 47 
 48         if (server->secmech.sdeschmacsha256 != NULL)
 49                 return 0; /* already allocated */
 50 
 51         server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
 52         if (IS_ERR(server->secmech.hmacsha256)) {
 53                 cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
 54                 rc = PTR_ERR(server->secmech.hmacsha256);
 55                 server->secmech.hmacsha256 = NULL;
 56                 return rc;
 57         }
 58 
 59         size = sizeof(struct shash_desc) +
 60                         crypto_shash_descsize(server->secmech.hmacsha256);
 61         server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
 62         if (!server->secmech.sdeschmacsha256) {
 63                 crypto_free_shash(server->secmech.hmacsha256);
 64                 server->secmech.hmacsha256 = NULL;
 65                 return -ENOMEM;
 66         }
 67         server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
 68         server->secmech.sdeschmacsha256->shash.flags = 0x0;
 69 
 70         return 0;
 71 }
 72 
 73 static int
 74 smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
 75 {
 76         unsigned int size;
 77         int rc;
 78 
 79         if (server->secmech.sdesccmacaes != NULL)
 80                 return 0;  /* already allocated */
 81 
 82         rc = smb2_crypto_shash_allocate(server);
 83         if (rc)
 84                 return rc;
 85 
 86         server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
 87         if (IS_ERR(server->secmech.cmacaes)) {
 88                 cifs_dbg(VFS, "could not allocate crypto cmac-aes");
 89                 kfree(server->secmech.sdeschmacsha256);
 90                 server->secmech.sdeschmacsha256 = NULL;
 91                 crypto_free_shash(server->secmech.hmacsha256);
 92                 server->secmech.hmacsha256 = NULL;
 93                 rc = PTR_ERR(server->secmech.cmacaes);
 94                 server->secmech.cmacaes = NULL;
 95                 return rc;
 96         }
 97 
 98         size = sizeof(struct shash_desc) +
 99                         crypto_shash_descsize(server->secmech.cmacaes);
100         server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
101         if (!server->secmech.sdesccmacaes) {
102                 cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
103                 kfree(server->secmech.sdeschmacsha256);
104                 server->secmech.sdeschmacsha256 = NULL;
105                 crypto_free_shash(server->secmech.hmacsha256);
106                 crypto_free_shash(server->secmech.cmacaes);
107                 server->secmech.hmacsha256 = NULL;
108                 server->secmech.cmacaes = NULL;
109                 return -ENOMEM;
110         }
111         server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
112         server->secmech.sdesccmacaes->shash.flags = 0x0;
113 
114         return 0;
115 }
116 
117 static struct cifs_ses *
118 smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
119 {
120         struct cifs_ses *ses;
121 
122         list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
123                 if (ses->Suid != ses_id)
124                         continue;
125                 return ses;
126         }
127 
128         return NULL;
129 }
130 
131 struct cifs_ses *
132 smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
133 {
134         struct cifs_ses *ses;
135 
136         spin_lock(&cifs_tcp_ses_lock);
137         ses = smb2_find_smb_ses_unlocked(server, ses_id);
138         spin_unlock(&cifs_tcp_ses_lock);
139 
140         return ses;
141 }
142 
143 static struct cifs_tcon *
144 smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
145 {
146         struct cifs_tcon *tcon;
147 
148         list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
149                 if (tcon->tid != tid)
150                         continue;
151                 ++tcon->tc_count;
152                 return tcon;
153         }
154 
155         return NULL;
156 }
157 
158 /*
159  * Obtain tcon corresponding to the tid in the given
160  * cifs_ses
161  */
162 
163 struct cifs_tcon *
164 smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
165 {
166         struct cifs_ses *ses;
167         struct cifs_tcon *tcon;
168 
169         spin_lock(&cifs_tcp_ses_lock);
170         ses = smb2_find_smb_ses_unlocked(server, ses_id);
171         if (!ses) {
172                 spin_unlock(&cifs_tcp_ses_lock);
173                 return NULL;
174         }
175         tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
176         spin_unlock(&cifs_tcp_ses_lock);
177 
178         return tcon;
179 }
180 
181 int
182 smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
183 {
184         int i, rc;
185         unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
186         unsigned char *sigptr = smb2_signature;
187         struct kvec *iov = rqst->rq_iov;
188         int n_vec = rqst->rq_nvec;
189         struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
190         struct cifs_ses *ses;
191 
192         ses = smb2_find_smb_ses(server, smb2_pdu->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(smb2_pdu->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         for (i = 0; i < n_vec; i++) {
221                 if (iov[i].iov_len == 0)
222                         continue;
223                 if (iov[i].iov_base == NULL) {
224                         cifs_dbg(VFS, "null iovec entry\n");
225                         return -EIO;
226                 }
227                 /*
228                  * The first entry includes a length field (which does not get
229                  * signed that occupies the first 4 bytes before the header).
230                  */
231                 if (i == 0) {
232                         if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
233                                 break; /* nothing to sign or corrupt header */
234                         rc =
235                         crypto_shash_update(
236                                 &server->secmech.sdeschmacsha256->shash,
237                                 iov[i].iov_base + 4, iov[i].iov_len - 4);
238                 } else {
239                         rc =
240                         crypto_shash_update(
241                                 &server->secmech.sdeschmacsha256->shash,
242                                 iov[i].iov_base, iov[i].iov_len);
243                 }
244                 if (rc) {
245                         cifs_dbg(VFS, "%s: Could not update with payload\n",
246                                  __func__);
247                         return rc;
248                 }
249         }
250 
251         /* now hash over the rq_pages array */
252         for (i = 0; i < rqst->rq_npages; i++) {
253                 struct kvec p_iov;
254 
255                 cifs_rqst_page_to_kvec(rqst, i, &p_iov);
256                 crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
257                                         p_iov.iov_base, p_iov.iov_len);
258                 kunmap(rqst->rq_pages[i]);
259         }
260 
261         rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
262                                 sigptr);
263         if (rc)
264                 cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
265 
266         memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE);
267 
268         return rc;
269 }
270 
271 int
272 generate_smb3signingkey(struct cifs_ses *ses)
273 {
274         unsigned char zero = 0x0;
275         __u8 i[4] = {0, 0, 0, 1};
276         __u8 L[4] = {0, 0, 0, 128};
277         int rc = 0;
278         unsigned char prfhash[SMB2_HMACSHA256_SIZE];
279         unsigned char *hashptr = prfhash;
280 
281         memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
282         memset(ses->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE);
283 
284         rc = smb3_crypto_shash_allocate(ses->server);
285         if (rc) {
286                 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
287                 goto smb3signkey_ret;
288         }
289 
290         rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
291                 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
292         if (rc) {
293                 cifs_dbg(VFS, "%s: Could not set with session key\n", __func__);
294                 goto smb3signkey_ret;
295         }
296 
297         rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
298         if (rc) {
299                 cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
300                 goto smb3signkey_ret;
301         }
302 
303         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
304                                 i, 4);
305         if (rc) {
306                 cifs_dbg(VFS, "%s: Could not update with n\n", __func__);
307                 goto smb3signkey_ret;
308         }
309 
310         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
311                                 "SMB2AESCMAC", 12);
312         if (rc) {
313                 cifs_dbg(VFS, "%s: Could not update with label\n", __func__);
314                 goto smb3signkey_ret;
315         }
316 
317         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
318                                 &zero, 1);
319         if (rc) {
320                 cifs_dbg(VFS, "%s: Could not update with zero\n", __func__);
321                 goto smb3signkey_ret;
322         }
323 
324         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
325                                 "SmbSign", 8);
326         if (rc) {
327                 cifs_dbg(VFS, "%s: Could not update with context\n", __func__);
328                 goto smb3signkey_ret;
329         }
330 
331         rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
332                                 L, 4);
333         if (rc) {
334                 cifs_dbg(VFS, "%s: Could not update with L\n", __func__);
335                 goto smb3signkey_ret;
336         }
337 
338         rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
339                                 hashptr);
340         if (rc) {
341                 cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
342                 goto smb3signkey_ret;
343         }
344 
345         memcpy(ses->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE);
346 
347 smb3signkey_ret:
348         return rc;
349 }
350 
351 int
352 smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
353 {
354         int i;
355         int rc = 0;
356         unsigned char smb3_signature[SMB2_CMACAES_SIZE];
357         unsigned char *sigptr = smb3_signature;
358         struct kvec *iov = rqst->rq_iov;
359         int n_vec = rqst->rq_nvec;
360         struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
361         struct cifs_ses *ses;
362 
363         ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
364         if (!ses) {
365                 cifs_dbg(VFS, "%s: Could not find session\n", __func__);
366                 return 0;
367         }
368 
369         memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
370         memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
371 
372         rc = crypto_shash_setkey(server->secmech.cmacaes,
373                 ses->smb3signingkey, SMB2_CMACAES_SIZE);
374 
375         if (rc) {
376                 cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
377                 return rc;
378         }
379 
380         /*
381          * we already allocate sdesccmacaes when we init smb3 signing key,
382          * so unlike smb2 case we do not have to check here if secmech are
383          * initialized
384          */
385         rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
386         if (rc) {
387                 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
388                 return rc;
389         }
390 
391         for (i = 0; i < n_vec; i++) {
392                 if (iov[i].iov_len == 0)
393                         continue;
394                 if (iov[i].iov_base == NULL) {
395                         cifs_dbg(VFS, "null iovec entry");
396                         return -EIO;
397                 }
398                 /*
399                  * The first entry includes a length field (which does not get
400                  * signed that occupies the first 4 bytes before the header).
401                  */
402                 if (i == 0) {
403                         if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
404                                 break; /* nothing to sign or corrupt header */
405                         rc =
406                         crypto_shash_update(
407                                 &server->secmech.sdesccmacaes->shash,
408                                 iov[i].iov_base + 4, iov[i].iov_len - 4);
409                 } else {
410                         rc =
411                         crypto_shash_update(
412                                 &server->secmech.sdesccmacaes->shash,
413                                 iov[i].iov_base, iov[i].iov_len);
414                 }
415                 if (rc) {
416                         cifs_dbg(VFS, "%s: Couldn't update cmac aes with payload\n",
417                                                         __func__);
418                         return rc;
419                 }
420         }
421 
422         /* now hash over the rq_pages array */
423         for (i = 0; i < rqst->rq_npages; i++) {
424                 struct kvec p_iov;
425 
426                 cifs_rqst_page_to_kvec(rqst, i, &p_iov);
427                 crypto_shash_update(&server->secmech.sdesccmacaes->shash,
428                                         p_iov.iov_base, p_iov.iov_len);
429                 kunmap(rqst->rq_pages[i]);
430         }
431 
432         rc = crypto_shash_final(&server->secmech.sdesccmacaes->shash,
433                                                 sigptr);
434         if (rc)
435                 cifs_dbg(VFS, "%s: Could not generate cmac aes\n", __func__);
436 
437         memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE);
438 
439         return rc;
440 }
441 
442 /* must be called with server->srv_mutex held */
443 static int
444 smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
445 {
446         int rc = 0;
447         struct smb2_hdr *smb2_pdu = rqst->rq_iov[0].iov_base;
448 
449         if (!(smb2_pdu->Flags & SMB2_FLAGS_SIGNED) ||
450             server->tcpStatus == CifsNeedNegotiate)
451                 return rc;
452 
453         if (!server->session_estab) {
454                 strncpy(smb2_pdu->Signature, "BSRSPYL", 8);
455                 return rc;
456         }
457 
458         rc = server->ops->calc_signature(rqst, server);
459 
460         return rc;
461 }
462 
463 int
464 smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
465 {
466         unsigned int rc;
467         char server_response_sig[16];
468         struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
469 
470         if ((smb2_pdu->Command == SMB2_NEGOTIATE) ||
471             (smb2_pdu->Command == SMB2_SESSION_SETUP) ||
472             (smb2_pdu->Command == SMB2_OPLOCK_BREAK) ||
473             (!server->session_estab))
474                 return 0;
475 
476         /*
477          * BB what if signatures are supposed to be on for session but
478          * server does not send one? BB
479          */
480 
481         /* Do not need to verify session setups with signature "BSRSPYL " */
482         if (memcmp(smb2_pdu->Signature, "BSRSPYL ", 8) == 0)
483                 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
484                          smb2_pdu->Command);
485 
486         /*
487          * Save off the origiginal signature so we can modify the smb and check
488          * our calculated signature against what the server sent.
489          */
490         memcpy(server_response_sig, smb2_pdu->Signature, SMB2_SIGNATURE_SIZE);
491 
492         memset(smb2_pdu->Signature, 0, SMB2_SIGNATURE_SIZE);
493 
494         mutex_lock(&server->srv_mutex);
495         rc = server->ops->calc_signature(rqst, server);
496         mutex_unlock(&server->srv_mutex);
497 
498         if (rc)
499                 return rc;
500 
501         if (memcmp(server_response_sig, smb2_pdu->Signature,
502                    SMB2_SIGNATURE_SIZE))
503                 return -EACCES;
504         else
505                 return 0;
506 }
507 
508 /*
509  * Set message id for the request. Should be called after wait_for_free_request
510  * and when srv_mutex is held.
511  */
512 static inline void
513 smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr)
514 {
515         hdr->MessageId = get_next_mid64(server);
516 }
517 
518 static struct mid_q_entry *
519 smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
520                      struct TCP_Server_Info *server)
521 {
522         struct mid_q_entry *temp;
523 
524         if (server == NULL) {
525                 cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
526                 return NULL;
527         }
528 
529         temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
530         if (temp == NULL)
531                 return temp;
532         else {
533                 memset(temp, 0, sizeof(struct mid_q_entry));
534                 kref_init(&temp->refcount);
535                 temp->mid = smb_buffer->MessageId;      /* always LE */
536                 temp->pid = current->pid;
537                 temp->command = smb_buffer->Command;    /* Always LE */
538                 temp->when_alloc = jiffies;
539                 temp->server = server;
540 
541                 /*
542                  * The default is for the mid to be synchronous, so the
543                  * default callback just wakes up the current task.
544                  */
545                 get_task_struct(current);
546                 temp->creator = current;
547                 temp->callback = cifs_wake_up_task;
548                 temp->callback_data = current;
549         }
550 
551         atomic_inc(&midCount);
552         temp->mid_state = MID_REQUEST_ALLOCATED;
553         return temp;
554 }
555 
556 static int
557 smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
558                    struct mid_q_entry **mid)
559 {
560         if (ses->server->tcpStatus == CifsExiting)
561                 return -ENOENT;
562 
563         if (ses->server->tcpStatus == CifsNeedReconnect) {
564                 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
565                 return -EAGAIN;
566         }
567 
568         if (ses->status == CifsNew) {
569                 if ((buf->Command != SMB2_SESSION_SETUP) &&
570                     (buf->Command != SMB2_NEGOTIATE))
571                         return -EAGAIN;
572                 /* else ok - we are setting up session */
573         }
574 
575         if (ses->status == CifsExiting) {
576                 if (buf->Command != SMB2_LOGOFF)
577                         return -EAGAIN;
578                 /* else ok - we are shutting down the session */
579         }
580 
581         *mid = smb2_mid_entry_alloc(buf, ses->server);
582         if (*mid == NULL)
583                 return -ENOMEM;
584         spin_lock(&GlobalMid_Lock);
585         list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
586         spin_unlock(&GlobalMid_Lock);
587         return 0;
588 }
589 
590 int
591 smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
592                    bool log_error)
593 {
594         unsigned int len = get_rfc1002_length(mid->resp_buf);
595         struct kvec iov;
596         struct smb_rqst rqst = { .rq_iov = &iov,
597                                  .rq_nvec = 1 };
598 
599         iov.iov_base = (char *)mid->resp_buf;
600         iov.iov_len = get_rfc1002_length(mid->resp_buf) + 4;
601 
602         dump_smb(mid->resp_buf, min_t(u32, 80, len));
603         /* convert the length into a more usable form */
604         if (len > 24 && server->sign) {
605                 int rc;
606 
607                 rc = smb2_verify_signature(&rqst, server);
608                 if (rc)
609                         cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
610                                  rc);
611         }
612 
613         return map_smb2_to_linux_error(mid->resp_buf, log_error);
614 }
615 
616 struct mid_q_entry *
617 smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
618 {
619         int rc;
620         struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
621         struct mid_q_entry *mid;
622 
623         smb2_seq_num_into_buf(ses->server, hdr);
624 
625         rc = smb2_get_mid_entry(ses, hdr, &mid);
626         if (rc)
627                 return ERR_PTR(rc);
628         rc = smb2_sign_rqst(rqst, ses->server);
629         if (rc) {
630                 cifs_delete_mid(mid);
631                 return ERR_PTR(rc);
632         }
633         return mid;
634 }
635 
636 struct mid_q_entry *
637 smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
638 {
639         int rc;
640         struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
641         struct mid_q_entry *mid;
642 
643         smb2_seq_num_into_buf(server, hdr);
644 
645         mid = smb2_mid_entry_alloc(hdr, server);
646         if (mid == NULL)
647                 return ERR_PTR(-ENOMEM);
648 
649         rc = smb2_sign_rqst(rqst, server);
650         if (rc) {
651                 DeleteMidQEntry(mid);
652                 return ERR_PTR(rc);
653         }
654 
655         return mid;
656 }
657 

~ [ 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