Commit 2b149f11978b44199954710d32c0eecf6c9efd9c

Authored by Shirish Pargaonkar
Committed by Steve French
1 parent 5f98ca9afb

cifs NTLMv2/NTLMSSP ntlmv2 within ntlmssp autentication code

Attribue Value (AV) pairs or Target Info (TI) pairs are part of
ntlmv2 authentication.
Structure ntlmv2_resp had only definition for two av pairs.
So removed it, and now allocation of av pairs is dynamic.
For servers like Windows 7/2008, av pairs sent by server in
challege packet (type 2 in the ntlmssp exchange/negotiation) can
vary.

Server sends them during ntlmssp negotiation. So when ntlmssp is used
as an authentication mechanism, type 2 challenge packet from server
has this information.  Pluck it and use the entire blob for
authenticaiton purpose.  If user has not specified, extract
(netbios) domain name from the av pairs which is used to calculate
ntlmv2 hash.  Servers like Windows 7 are particular about the AV pair
blob.

Servers like Windows 2003, are not very strict about the contents
of av pair blob used during ntlmv2 authentication.
So when security mechanism such as ntlmv2 is used (not ntlmv2 in ntlmssp),
there is no negotiation and so genereate a minimal blob that gets
used in ntlmv2 authentication as well as gets sent.

Fields tilen and tilbob are session specific.  AV pair values are defined.

To calculate ntlmv2 response we need ti/av pair blob.

For sec mech like ntlmssp, the blob is plucked from type 2 response from
the server.  From this blob, netbios name of the domain is retrieved,
if user has not already provided, to be included in the Target String
as part of ntlmv2 hash calculations.

For sec mech like ntlmv2, create a minimal, two av pair blob.

The allocated blob is freed in case of error.  In case there is no error,
this blob is used in calculating ntlmv2 response (in CalcNTLMv2_response)
and is also copied on the response to the server, and then freed.

The type 3 ntlmssp response is prepared on a buffer,
5 * sizeof of struct _AUTHENTICATE_MESSAGE, an empirical value large
enough to hold _AUTHENTICATE_MESSAGE plus a blob with max possible
10 values as part of ntlmv2 response and lmv2 keys and domain, user,
workstation  names etc.

Also, kerberos gets selected as a default mechanism if server supports it,
over the other security mechanisms.

Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

Showing 8 changed files with 225 additions and 53 deletions Side-by-side Diff

fs/cifs/cifsencrypt.c
... ... @@ -27,6 +27,7 @@
27 27 #include "md5.h"
28 28 #include "cifs_unicode.h"
29 29 #include "cifsproto.h"
  30 +#include "ntlmssp.h"
30 31 #include <linux/ctype.h>
31 32 #include <linux/random.h>
32 33  
... ... @@ -262,6 +263,87 @@
262 263 }
263 264 #endif /* CIFS_WEAK_PW_HASH */
264 265  
  266 +/* This is just a filler for ntlmv2 type of security mechanisms.
  267 + * Older servers are not very particular about the contents of av pairs
  268 + * in the blob and for sec mechs like ntlmv2, there is no negotiation
  269 + * as in ntlmssp, so unless domain and server netbios and dns names
  270 + * are specified, there is no way to obtain name. In case of ntlmssp,
  271 + * server provides that info in type 2 challenge packet
  272 + */
  273 +static int
  274 +build_avpair_blob(struct cifsSesInfo *ses)
  275 +{
  276 + struct ntlmssp2_name *attrptr;
  277 +
  278 + ses->tilen = 2 * sizeof(struct ntlmssp2_name);
  279 + ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL);
  280 + if (!ses->tiblob) {
  281 + ses->tilen = 0;
  282 + cERROR(1, "Challenge target info allocation failure");
  283 + return -ENOMEM;
  284 + }
  285 + attrptr = (struct ntlmssp2_name *) ses->tiblob;
  286 + attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
  287 +
  288 + return 0;
  289 +}
  290 +
  291 +/* Server has provided av pairs/target info in the type 2 challenge
  292 + * packet and we have plucked it and stored within smb session.
  293 + * We parse that blob here to find netbios domain name to be used
  294 + * as part of ntlmv2 authentication (in Target String), if not already
  295 + * specified on the command line.
  296 + * If this function returns without any error but without fetching
  297 + * domain name, authentication may fail against some server but
  298 + * may not fail against other (those who are not very particular
  299 + * about target string i.e. for some, just user name might suffice.
  300 + */
  301 +static int
  302 +find_domain_name(struct cifsSesInfo *ses)
  303 +{
  304 + unsigned int attrsize;
  305 + unsigned int type;
  306 + unsigned int onesize = sizeof(struct ntlmssp2_name);
  307 + unsigned char *blobptr;
  308 + unsigned char *blobend;
  309 + struct ntlmssp2_name *attrptr;
  310 +
  311 + if (!ses->tilen || !ses->tiblob)
  312 + return 0;
  313 +
  314 + blobptr = ses->tiblob;
  315 + blobend = ses->tiblob + ses->tilen;
  316 +
  317 + while (blobptr + onesize < blobend) {
  318 + attrptr = (struct ntlmssp2_name *) blobptr;
  319 + type = le16_to_cpu(attrptr->type);
  320 + if (type == NTLMSSP_AV_EOL)
  321 + break;
  322 + blobptr += 2; /* advance attr type */
  323 + attrsize = le16_to_cpu(attrptr->length);
  324 + blobptr += 2; /* advance attr size */
  325 + if (blobptr + attrsize > blobend)
  326 + break;
  327 + if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
  328 + if (!attrsize)
  329 + break;
  330 + if (!ses->domainName) {
  331 + ses->domainName =
  332 + kmalloc(attrsize + 1, GFP_KERNEL);
  333 + if (!ses->domainName)
  334 + return -ENOMEM;
  335 + cifs_from_ucs2(ses->domainName,
  336 + (__le16 *)blobptr, attrsize, attrsize,
  337 + load_nls_default(), false);
  338 + break;
  339 + }
  340 + }
  341 + blobptr += attrsize; /* advance attr value */
  342 + }
  343 +
  344 + return 0;
  345 +}
  346 +
265 347 static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
266 348 const struct nls_table *nls_cp)
267 349 {
... ... @@ -321,7 +403,8 @@
321 403 return rc;
322 404 }
323 405  
324   -void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
  406 +int
  407 +setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
325 408 const struct nls_table *nls_cp)
326 409 {
327 410 int rc;
328 411  
329 412  
330 413  
... ... @@ -333,15 +416,29 @@
333 416 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
334 417 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
335 418 buf->reserved2 = 0;
336   - buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
337   - buf->names[0].length = 0;
338   - buf->names[1].type = 0;
339   - buf->names[1].length = 0;
340 419  
  420 + if (ses->server->secType == RawNTLMSSP) {
  421 + if (!ses->domainName) {
  422 + rc = find_domain_name(ses);
  423 + if (rc) {
  424 + cERROR(1, "error %d finding domain name", rc);
  425 + goto setup_ntlmv2_rsp_ret;
  426 + }
  427 + }
  428 + } else {
  429 + rc = build_avpair_blob(ses);
  430 + if (rc) {
  431 + cERROR(1, "error %d building av pair blob", rc);
  432 + return rc;
  433 + }
  434 + }
  435 +
341 436 /* calculate buf->ntlmv2_hash */
342 437 rc = calc_ntlmv2_hash(ses, nls_cp);
343   - if (rc)
  438 + if (rc) {
344 439 cERROR(1, "could not get v2 hash rc %d", rc);
  440 + goto setup_ntlmv2_rsp_ret;
  441 + }
345 442 CalcNTLMv2_response(ses, resp_buf);
346 443  
347 444 /* now calculate the MAC key for NTLMv2 */
... ... @@ -352,6 +449,15 @@
352 449 memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf,
353 450 sizeof(struct ntlmv2_resp));
354 451 ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp);
  452 +
  453 + return 0;
  454 +
  455 +setup_ntlmv2_rsp_ret:
  456 + kfree(ses->tiblob);
  457 + ses->tiblob = NULL;
  458 + ses->tilen = 0;
  459 +
  460 + return rc;
355 461 }
356 462  
357 463 void CalcNTLMv2_response(const struct cifsSesInfo *ses,
... ... @@ -364,6 +470,9 @@
364 470  
365 471 hmac_md5_update(v2_session_response+8,
366 472 sizeof(struct ntlmv2_resp) - 8, &context);
  473 +
  474 + if (ses->tilen)
  475 + hmac_md5_update(ses->tiblob, ses->tilen, &context);
367 476  
368 477 hmac_md5_final(v2_session_response, &context);
369 478 /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
... ... @@ -222,6 +222,8 @@
222 222 char userName[MAX_USERNAME_SIZE + 1];
223 223 char *domainName;
224 224 char *password;
  225 + unsigned int tilen; /* length of the target info blob */
  226 + unsigned char *tiblob; /* target info blob in challenge response */
225 227 bool need_reconnect:1; /* connection reset, uid now invalid */
226 228 };
227 229 /* no more than one of the following three session flags may be set */
... ... @@ -663,7 +663,6 @@
663 663 __le64 time;
664 664 __u64 client_chal; /* random */
665 665 __u32 reserved2;
666   - struct ntlmssp2_name names[2];
667 666 /* array of name entries could follow ending in minimum 4 byte struct */
668 667 } __attribute__((packed));
669 668  
... ... @@ -368,7 +368,7 @@
368 368 extern int cifs_calculate_session_key(struct session_key *key, const char *rn,
369 369 const char *pass);
370 370 extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
371   -extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
  371 +extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
372 372 const struct nls_table *);
373 373 #ifdef CONFIG_CIFS_WEAK_PW_HASH
374 374 extern void calc_lanman_hash(const char *password, const char *cryptkey,
... ... @@ -603,13 +603,15 @@
603 603 rc = 0;
604 604 else
605 605 rc = -EINVAL;
606   -
607   - if (server->sec_kerberos || server->sec_mskerberos)
608   - server->secType = Kerberos;
609   - else if (server->sec_ntlmssp)
610   - server->secType = RawNTLMSSP;
611   - else
612   - rc = -EOPNOTSUPP;
  606 + if (server->secType == Kerberos) {
  607 + if (!server->sec_kerberos &&
  608 + !server->sec_mskerberos)
  609 + rc = -EOPNOTSUPP;
  610 + } else if (server->secType == RawNTLMSSP) {
  611 + if (!server->sec_ntlmssp)
  612 + rc = -EOPNOTSUPP;
  613 + } else
  614 + rc = -EOPNOTSUPP;
613 615 }
614 616 } else
615 617 server->capabilities &= ~CAP_EXTENDED_SECURITY;
... ... @@ -1740,6 +1740,8 @@
1740 1740 if (ses == NULL)
1741 1741 goto get_ses_fail;
1742 1742  
  1743 + ses->tilen = 0;
  1744 + ses->tiblob = NULL;
1743 1745 /* new SMB session uses our server ref */
1744 1746 ses->server = server;
1745 1747 if (server->addr.sockAddr6.sin6_family == AF_INET6)
... ... @@ -61,6 +61,21 @@
61 61 #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
62 62 #define NTLMSSP_NEGOTIATE_56 0x80000000
63 63  
  64 +/* Define AV Pair Field IDs */
  65 +enum av_field_type {
  66 + NTLMSSP_AV_EOL = 0,
  67 + NTLMSSP_AV_NB_COMPUTER_NAME,
  68 + NTLMSSP_AV_NB_DOMAIN_NAME,
  69 + NTLMSSP_AV_DNS_COMPUTER_NAME,
  70 + NTLMSSP_AV_DNS_DOMAIN_NAME,
  71 + NTLMSSP_AV_DNS_TREE_NAME,
  72 + NTLMSSP_AV_FLAGS,
  73 + NTLMSSP_AV_TIMESTAMP,
  74 + NTLMSSP_AV_RESTRICTION,
  75 + NTLMSSP_AV_TARGET_NAME,
  76 + NTLMSSP_AV_CHANNEL_BINDINGS
  77 +};
  78 +
64 79 /* Although typedefs are not commonly used for structure definitions */
65 80 /* in the Linux kernel, in this particular case they are useful */
66 81 /* to more closely match the standards document for NTLMSSP from */
... ... @@ -383,6 +383,9 @@
383 383 static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
384 384 struct cifsSesInfo *ses)
385 385 {
  386 + unsigned int tioffset; /* challenge message target info area */
  387 + unsigned int tilen; /* challenge message target info area length */
  388 +
386 389 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
387 390  
388 391 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
... ... @@ -405,6 +408,19 @@
405 408 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
406 409 we must set the MIC field of the AUTHENTICATE_MESSAGE */
407 410  
  411 + tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
  412 + tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
  413 + ses->tilen = tilen;
  414 + if (ses->tilen) {
  415 + ses->tiblob = kmalloc(tilen, GFP_KERNEL);
  416 + if (!ses->tiblob) {
  417 + cERROR(1, "Challenge target info allocation failure");
  418 + ses->tilen = 0;
  419 + return -ENOMEM;
  420 + }
  421 + memcpy(ses->tiblob, bcc_ptr + tioffset, ses->tilen);
  422 + }
  423 +
408 424 return 0;
409 425 }
410 426  
... ... @@ -425,7 +441,7 @@
425 441 /* BB is NTLMV2 session security format easier to use here? */
426 442 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
427 443 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
428   - NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
  444 + NTLMSSP_NEGOTIATE_NTLM;
429 445 if (ses->server->secMode &
430 446 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
431 447 flags |= NTLMSSP_NEGOTIATE_SIGN;
432 448  
433 449  
... ... @@ -449,12 +465,14 @@
449 465 This function returns the length of the data in the blob */
450 466 static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
451 467 struct cifsSesInfo *ses,
452   - const struct nls_table *nls_cp, bool first)
  468 + const struct nls_table *nls_cp)
453 469 {
  470 + int rc;
  471 + unsigned int size;
454 472 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
455 473 __u32 flags;
456 474 unsigned char *tmp;
457   - char ntlm_session_key[CIFS_SESS_KEY_SIZE];
  475 + struct ntlmv2_resp ntlmv2_response = {};
458 476  
459 477 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
460 478 sec_blob->MessageType = NtLmAuthenticate;
... ... @@ -462,7 +480,7 @@
462 480 flags = NTLMSSP_NEGOTIATE_56 |
463 481 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
464 482 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
465   - NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
  483 + NTLMSSP_NEGOTIATE_NTLM;
466 484 if (ses->server->secMode &
467 485 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
468 486 flags |= NTLMSSP_NEGOTIATE_SIGN;
469 487  
470 488  
471 489  
... ... @@ -477,20 +495,27 @@
477 495 sec_blob->LmChallengeResponse.Length = 0;
478 496 sec_blob->LmChallengeResponse.MaximumLength = 0;
479 497  
480   - /* calculate session key, BB what about adding similar ntlmv2 path? */
481   - SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
482   - if (first)
483   - cifs_calculate_session_key(&ses->server->session_key,
484   - ntlm_session_key, ses->password);
485   -
486   - memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
487 498 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
488   - sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
  499 + rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
  500 + if (rc) {
  501 + cERROR(1, "Error %d during NTLMSSP authentication", rc);
  502 + goto setup_ntlmv2_ret;
  503 + }
  504 + size = sizeof(struct ntlmv2_resp);
  505 + memcpy(tmp, (char *)&ntlmv2_response, size);
  506 + tmp += size;
  507 + if (ses->tilen > 0) {
  508 + memcpy(tmp, ses->tiblob, ses->tilen);
  509 + tmp += ses->tilen;
  510 + }
  511 +
  512 + sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + ses->tilen);
489 513 sec_blob->NtChallengeResponse.MaximumLength =
490   - cpu_to_le16(CIFS_SESS_KEY_SIZE);
  514 + cpu_to_le16(size + ses->tilen);
  515 + kfree(ses->tiblob);
  516 + ses->tiblob = NULL;
  517 + ses->tilen = 0;
491 518  
492   - tmp += CIFS_SESS_KEY_SIZE;
493   -
494 519 if (ses->domainName == NULL) {
495 520 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
496 521 sec_blob->DomainName.Length = 0;
... ... @@ -501,7 +526,6 @@
501 526 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
502 527 MAX_USERNAME_SIZE, nls_cp);
503 528 len *= 2; /* unicode is 2 bytes each */
504   - len += 2; /* trailing null */
505 529 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
506 530 sec_blob->DomainName.Length = cpu_to_le16(len);
507 531 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
... ... @@ -518,7 +542,6 @@
518 542 len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
519 543 MAX_USERNAME_SIZE, nls_cp);
520 544 len *= 2; /* unicode is 2 bytes each */
521   - len += 2; /* trailing null */
522 545 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
523 546 sec_blob->UserName.Length = cpu_to_le16(len);
524 547 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
... ... @@ -533,6 +556,8 @@
533 556 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
534 557 sec_blob->SessionKey.Length = 0;
535 558 sec_blob->SessionKey.MaximumLength = 0;
  559 +
  560 +setup_ntlmv2_ret:
536 561 return tmp - pbuffer;
537 562 }
538 563  
... ... @@ -545,19 +570,6 @@
545 570  
546 571 return;
547 572 }
548   -
549   -static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
550   - struct cifsSesInfo *ses,
551   - const struct nls_table *nls, bool first_time)
552   -{
553   - int bloblen;
554   -
555   - bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
556   - first_time);
557   - pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
558   -
559   - return bloblen;
560   -}
561 573 #endif
562 574  
563 575 int
... ... @@ -580,6 +592,8 @@
580 592 struct key *spnego_key = NULL;
581 593 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
582 594 bool first_time;
  595 + int blob_len;
  596 + char *ntlmsspblob = NULL;
583 597  
584 598 if (ses == NULL)
585 599 return -EINVAL;
586 600  
587 601  
... ... @@ -729,12 +743,24 @@
729 743 cpu_to_le16(sizeof(struct ntlmv2_resp));
730 744  
731 745 /* calculate session key */
732   - setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
733   - /* FIXME: calculate MAC key */
  746 + rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
  747 + if (rc) {
  748 + cERROR(1, "Error %d during NTLMv2 authentication", rc);
  749 + kfree(v2_sess_key);
  750 + goto ssetup_exit;
  751 + }
734 752 memcpy(bcc_ptr, (char *)v2_sess_key,
735   - sizeof(struct ntlmv2_resp));
  753 + sizeof(struct ntlmv2_resp));
736 754 bcc_ptr += sizeof(struct ntlmv2_resp);
737 755 kfree(v2_sess_key);
  756 + if (ses->tilen > 0) {
  757 + memcpy(bcc_ptr, ses->tiblob, ses->tilen);
  758 + bcc_ptr += ses->tilen;
  759 + /* we never did allocate ses->domainName to free */
  760 + kfree(ses->tiblob);
  761 + ses->tiblob = NULL;
  762 + ses->tilen = 0;
  763 + }
738 764 if (ses->capabilities & CAP_UNICODE) {
739 765 if (iov[0].iov_len % 2) {
740 766 *bcc_ptr = 0;
741 767  
742 768  
... ... @@ -815,12 +841,28 @@
815 841 if (phase == NtLmNegotiate) {
816 842 setup_ntlmssp_neg_req(pSMB, ses);
817 843 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
  844 + iov[1].iov_base = &pSMB->req.SecurityBlob[0];
818 845 } else if (phase == NtLmAuthenticate) {
819   - int blob_len;
820   - blob_len = setup_ntlmssp_auth_req(pSMB, ses,
821   - nls_cp,
822   - first_time);
  846 + /* 5 is an empirical value, large enought to
  847 + * hold authenticate message, max 10 of
  848 + * av paris, doamin,user,workstation mames,
  849 + * flags etc..
  850 + */
  851 + ntlmsspblob = kmalloc(
  852 + 5*sizeof(struct _AUTHENTICATE_MESSAGE),
  853 + GFP_KERNEL);
  854 + if (!ntlmsspblob) {
  855 + cERROR(1, "Can't allocate NTLMSSP");
  856 + rc = -ENOMEM;
  857 + goto ssetup_exit;
  858 + }
  859 +
  860 + blob_len = build_ntlmssp_auth_blob(ntlmsspblob,
  861 + ses, nls_cp);
823 862 iov[1].iov_len = blob_len;
  863 + iov[1].iov_base = ntlmsspblob;
  864 + pSMB->req.SecurityBlobLength =
  865 + cpu_to_le16(blob_len);
824 866 /* Make sure that we tell the server that we
825 867 are using the uid that it just gave us back
826 868 on the response (challenge) */
... ... @@ -830,7 +872,6 @@
830 872 rc = -ENOSYS;
831 873 goto ssetup_exit;
832 874 }
833   - iov[1].iov_base = &pSMB->req.SecurityBlob[0];
834 875 /* unicode strings must be word aligned */
835 876 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
836 877 *bcc_ptr = 0;
... ... @@ -931,6 +972,8 @@
931 972 key_put(spnego_key);
932 973 }
933 974 kfree(str_area);
  975 + kfree(ntlmsspblob);
  976 + ntlmsspblob = NULL;
934 977 if (resp_buf_type == CIFS_SMALL_BUFFER) {
935 978 cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
936 979 cifs_small_buf_release(iov[0].iov_base);