diff options
-rw-r--r-- | fs/cifs/cifsencrypt.c | 53 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 9 | ||||
-rw-r--r-- | fs/cifs/connect.c | 11 | ||||
-rw-r--r-- | fs/cifs/sess.c | 29 |
4 files changed, 55 insertions, 47 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index ef95a272f73d..f856732161ab 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -328,15 +328,15 @@ build_avpair_blob(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
328 | * two times the unicode length of a server name + | 328 | * two times the unicode length of a server name + |
329 | * size of a timestamp (which is 8 bytes). | 329 | * size of a timestamp (which is 8 bytes). |
330 | */ | 330 | */ |
331 | ses->tilen = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8; | 331 | ses->auth_key.len = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8; |
332 | ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL); | 332 | ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL); |
333 | if (!ses->tiblob) { | 333 | if (!ses->auth_key.response) { |
334 | ses->tilen = 0; | 334 | ses->auth_key.len = 0; |
335 | cERROR(1, "Challenge target info allocation failure"); | 335 | cERROR(1, "Challenge target info allocation failure"); |
336 | return -ENOMEM; | 336 | return -ENOMEM; |
337 | } | 337 | } |
338 | 338 | ||
339 | blobptr = ses->tiblob; | 339 | blobptr = ses->auth_key.response; |
340 | attrptr = (struct ntlmssp2_name *) blobptr; | 340 | attrptr = (struct ntlmssp2_name *) blobptr; |
341 | 341 | ||
342 | attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); | 342 | attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); |
@@ -400,11 +400,11 @@ find_domain_name(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
400 | unsigned char *blobend; | 400 | unsigned char *blobend; |
401 | struct ntlmssp2_name *attrptr; | 401 | struct ntlmssp2_name *attrptr; |
402 | 402 | ||
403 | if (!ses->tilen || !ses->tiblob) | 403 | if (!ses->auth_key.len || !ses->auth_key.response) |
404 | return 0; | 404 | return 0; |
405 | 405 | ||
406 | blobptr = ses->tiblob; | 406 | blobptr = ses->auth_key.response; |
407 | blobend = ses->tiblob + ses->tilen; | 407 | blobend = blobptr + ses->auth_key.len; |
408 | 408 | ||
409 | while (blobptr + onesize < blobend) { | 409 | while (blobptr + onesize < blobend) { |
410 | attrptr = (struct ntlmssp2_name *) blobptr; | 410 | attrptr = (struct ntlmssp2_name *) blobptr; |
@@ -436,7 +436,7 @@ find_domain_name(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
436 | return 0; | 436 | return 0; |
437 | } | 437 | } |
438 | 438 | ||
439 | static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | 439 | static int calc_ntlmv2_hash(struct cifsSesInfo *ses, char *ntlmv2_hash, |
440 | const struct nls_table *nls_cp) | 440 | const struct nls_table *nls_cp) |
441 | { | 441 | { |
442 | int rc = 0; | 442 | int rc = 0; |
@@ -509,7 +509,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
509 | } | 509 | } |
510 | 510 | ||
511 | rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, | 511 | rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, |
512 | ses->ntlmv2_hash); | 512 | ntlmv2_hash); |
513 | 513 | ||
514 | calc_exit_1: | 514 | calc_exit_1: |
515 | kfree(user); | 515 | kfree(user); |
@@ -518,7 +518,7 @@ calc_exit_2: | |||
518 | } | 518 | } |
519 | 519 | ||
520 | static int | 520 | static int |
521 | CalcNTLMv2_response(const struct cifsSesInfo *ses) | 521 | CalcNTLMv2_response(const struct cifsSesInfo *ses, char *ntlmv2_hash) |
522 | { | 522 | { |
523 | int rc; | 523 | int rc; |
524 | unsigned int offset = CIFS_SESS_KEY_SIZE + 8; | 524 | unsigned int offset = CIFS_SESS_KEY_SIZE + 8; |
@@ -529,7 +529,7 @@ CalcNTLMv2_response(const struct cifsSesInfo *ses) | |||
529 | } | 529 | } |
530 | 530 | ||
531 | crypto_shash_setkey(ses->server->secmech.hmacmd5, | 531 | crypto_shash_setkey(ses->server->secmech.hmacmd5, |
532 | ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); | 532 | ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); |
533 | 533 | ||
534 | rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); | 534 | rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); |
535 | if (rc) { | 535 | if (rc) { |
@@ -539,7 +539,7 @@ CalcNTLMv2_response(const struct cifsSesInfo *ses) | |||
539 | 539 | ||
540 | if (ses->server->secType == RawNTLMSSP) | 540 | if (ses->server->secType == RawNTLMSSP) |
541 | memcpy(ses->auth_key.response + offset, | 541 | memcpy(ses->auth_key.response + offset, |
542 | ses->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); | 542 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
543 | else | 543 | else |
544 | memcpy(ses->auth_key.response + offset, | 544 | memcpy(ses->auth_key.response + offset, |
545 | ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); | 545 | ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
@@ -558,7 +558,10 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
558 | { | 558 | { |
559 | int rc; | 559 | int rc; |
560 | int baselen; | 560 | int baselen; |
561 | unsigned int tilen; | ||
561 | struct ntlmv2_resp *buf; | 562 | struct ntlmv2_resp *buf; |
563 | char ntlmv2_hash[16]; | ||
564 | unsigned char *tiblob = NULL; /* target info blob */ | ||
562 | 565 | ||
563 | if (ses->server->secType == RawNTLMSSP) { | 566 | if (ses->server->secType == RawNTLMSSP) { |
564 | if (!ses->domainName) { | 567 | if (!ses->domainName) { |
@@ -572,18 +575,22 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
572 | rc = build_avpair_blob(ses, nls_cp); | 575 | rc = build_avpair_blob(ses, nls_cp); |
573 | if (rc) { | 576 | if (rc) { |
574 | cERROR(1, "error %d building av pair blob", rc); | 577 | cERROR(1, "error %d building av pair blob", rc); |
575 | return rc; | 578 | goto setup_ntlmv2_rsp_ret; |
576 | } | 579 | } |
577 | } | 580 | } |
578 | 581 | ||
579 | baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); | 582 | baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); |
580 | ses->auth_key.len = baselen + ses->tilen; | 583 | tilen = ses->auth_key.len; |
581 | ses->auth_key.response = kmalloc(ses->auth_key.len, GFP_KERNEL); | 584 | tiblob = ses->auth_key.response; |
585 | |||
586 | ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL); | ||
582 | if (!ses->auth_key.response) { | 587 | if (!ses->auth_key.response) { |
583 | rc = ENOMEM; | 588 | rc = ENOMEM; |
589 | ses->auth_key.len = 0; | ||
584 | cERROR(1, "%s: Can't allocate auth blob", __func__); | 590 | cERROR(1, "%s: Can't allocate auth blob", __func__); |
585 | goto setup_ntlmv2_rsp_ret; | 591 | goto setup_ntlmv2_rsp_ret; |
586 | } | 592 | } |
593 | ses->auth_key.len += baselen; | ||
587 | 594 | ||
588 | buf = (struct ntlmv2_resp *) | 595 | buf = (struct ntlmv2_resp *) |
589 | (ses->auth_key.response + CIFS_SESS_KEY_SIZE); | 596 | (ses->auth_key.response + CIFS_SESS_KEY_SIZE); |
@@ -593,17 +600,17 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
593 | get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); | 600 | get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); |
594 | buf->reserved2 = 0; | 601 | buf->reserved2 = 0; |
595 | 602 | ||
596 | memcpy(ses->auth_key.response + baselen, ses->tiblob, ses->tilen); | 603 | memcpy(ses->auth_key.response + baselen, tiblob, tilen); |
597 | 604 | ||
598 | /* calculate ntlmv2_hash */ | 605 | /* calculate ntlmv2_hash */ |
599 | rc = calc_ntlmv2_hash(ses, nls_cp); | 606 | rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); |
600 | if (rc) { | 607 | if (rc) { |
601 | cERROR(1, "could not get v2 hash rc %d", rc); | 608 | cERROR(1, "could not get v2 hash rc %d", rc); |
602 | goto setup_ntlmv2_rsp_ret; | 609 | goto setup_ntlmv2_rsp_ret; |
603 | } | 610 | } |
604 | 611 | ||
605 | /* calculate first part of the client response (CR1) */ | 612 | /* calculate first part of the client response (CR1) */ |
606 | rc = CalcNTLMv2_response(ses); | 613 | rc = CalcNTLMv2_response(ses, ntlmv2_hash); |
607 | if (rc) { | 614 | if (rc) { |
608 | cERROR(1, "Could not calculate CR1 rc: %d", rc); | 615 | cERROR(1, "Could not calculate CR1 rc: %d", rc); |
609 | goto setup_ntlmv2_rsp_ret; | 616 | goto setup_ntlmv2_rsp_ret; |
@@ -611,7 +618,7 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
611 | 618 | ||
612 | /* now calculate the session key for NTLMv2 */ | 619 | /* now calculate the session key for NTLMv2 */ |
613 | crypto_shash_setkey(ses->server->secmech.hmacmd5, | 620 | crypto_shash_setkey(ses->server->secmech.hmacmd5, |
614 | ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); | 621 | ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); |
615 | 622 | ||
616 | rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); | 623 | rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); |
617 | if (rc) { | 624 | if (rc) { |
@@ -627,9 +634,7 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp) | |||
627 | ses->auth_key.response); | 634 | ses->auth_key.response); |
628 | 635 | ||
629 | setup_ntlmv2_rsp_ret: | 636 | setup_ntlmv2_rsp_ret: |
630 | kfree(ses->tiblob); | 637 | kfree(tiblob); |
631 | ses->tiblob = NULL; | ||
632 | ses->tilen = 0; | ||
633 | 638 | ||
634 | return rc; | 639 | return rc; |
635 | } | 640 | } |
@@ -657,7 +662,7 @@ calc_seckey(struct cifsSesInfo *ses) | |||
657 | CIFS_SESS_KEY_SIZE); | 662 | CIFS_SESS_KEY_SIZE); |
658 | 663 | ||
659 | sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); | 664 | sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); |
660 | sg_init_one(&sgout, ses->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); | 665 | sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); |
661 | 666 | ||
662 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); | 667 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); |
663 | if (rc) { | 668 | if (rc) { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b73695176467..f259e4d7612d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -119,11 +119,12 @@ struct cifs_secmech { | |||
119 | struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ | 119 | struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ |
120 | }; | 120 | }; |
121 | 121 | ||
122 | /* per smb connection structure/fields */ | 122 | /* per smb session structure/fields */ |
123 | struct ntlmssp_auth { | 123 | struct ntlmssp_auth { |
124 | __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */ | 124 | __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */ |
125 | __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */ | 125 | __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */ |
126 | unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */ | 126 | unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */ |
127 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */ | ||
127 | }; | 128 | }; |
128 | 129 | ||
129 | struct cifs_cred { | 130 | struct cifs_cred { |
@@ -241,12 +242,8 @@ struct cifsSesInfo { | |||
241 | char userName[MAX_USERNAME_SIZE + 1]; | 242 | char userName[MAX_USERNAME_SIZE + 1]; |
242 | char *domainName; | 243 | char *domainName; |
243 | char *password; | 244 | char *password; |
244 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */ | ||
245 | struct session_key auth_key; | 245 | struct session_key auth_key; |
246 | char ntlmv2_hash[16]; | 246 | struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ |
247 | unsigned int tilen; /* length of the target info blob */ | ||
248 | unsigned char *tiblob; /* target info blob in challenge response */ | ||
249 | struct ntlmssp_auth ntlmssp; /* ciphertext, flags */ | ||
250 | bool need_reconnect:1; /* connection reset, uid now invalid */ | 247 | bool need_reconnect:1; /* connection reset, uid now invalid */ |
251 | }; | 248 | }; |
252 | /* no more than one of the following three session flags may be set */ | 249 | /* no more than one of the following three session flags may be set */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4d8004ce5834..9eb327defa1d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1818,8 +1818,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
1818 | if (ses == NULL) | 1818 | if (ses == NULL) |
1819 | goto get_ses_fail; | 1819 | goto get_ses_fail; |
1820 | 1820 | ||
1821 | ses->tilen = 0; | ||
1822 | ses->tiblob = NULL; | ||
1823 | /* new SMB session uses our server ref */ | 1821 | /* new SMB session uses our server ref */ |
1824 | ses->server = server; | 1822 | ses->server = server; |
1825 | if (server->addr.sockAddr6.sin6_family == AF_INET6) | 1823 | if (server->addr.sockAddr6.sin6_family == AF_INET6) |
@@ -1840,10 +1838,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
1840 | goto get_ses_fail; | 1838 | goto get_ses_fail; |
1841 | } | 1839 | } |
1842 | if (volume_info->domainname) { | 1840 | if (volume_info->domainname) { |
1843 | int len = strlen(volume_info->domainname); | 1841 | ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL); |
1844 | ses->domainName = kmalloc(len + 1, GFP_KERNEL); | 1842 | if (!ses->domainName) |
1845 | if (ses->domainName) | 1843 | goto get_ses_fail; |
1846 | strcpy(ses->domainName, volume_info->domainname); | ||
1847 | } | 1844 | } |
1848 | ses->cred_uid = volume_info->cred_uid; | 1845 | ses->cred_uid = volume_info->cred_uid; |
1849 | ses->linux_uid = volume_info->linux_uid; | 1846 | ses->linux_uid = volume_info->linux_uid; |
@@ -3213,6 +3210,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses, | |||
3213 | kfree(ses->auth_key.response); | 3210 | kfree(ses->auth_key.response); |
3214 | ses->auth_key.response = NULL; | 3211 | ses->auth_key.response = NULL; |
3215 | ses->auth_key.len = 0; | 3212 | ses->auth_key.len = 0; |
3213 | kfree(ses->ntlmssp); | ||
3214 | ses->ntlmssp = NULL; | ||
3216 | 3215 | ||
3217 | return rc; | 3216 | return rc; |
3218 | } | 3217 | } |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index f74c5a88dd4c..7b01d3f6eed6 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -399,23 +399,22 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | |||
399 | return -EINVAL; | 399 | return -EINVAL; |
400 | } | 400 | } |
401 | 401 | ||
402 | memcpy(ses->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); | 402 | memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); |
403 | /* BB we could decode pblob->NegotiateFlags; some may be useful */ | 403 | /* BB we could decode pblob->NegotiateFlags; some may be useful */ |
404 | /* In particular we can examine sign flags */ | 404 | /* In particular we can examine sign flags */ |
405 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then | 405 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then |
406 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ | 406 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ |
407 | ses->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags); | 407 | ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); |
408 | tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); | 408 | tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); |
409 | tilen = cpu_to_le16(pblob->TargetInfoArray.Length); | 409 | tilen = cpu_to_le16(pblob->TargetInfoArray.Length); |
410 | ses->tilen = tilen; | 410 | if (tilen) { |
411 | if (ses->tilen) { | 411 | ses->auth_key.response = kmalloc(tilen, GFP_KERNEL); |
412 | ses->tiblob = kmalloc(tilen, GFP_KERNEL); | 412 | if (!ses->auth_key.response) { |
413 | if (!ses->tiblob) { | ||
414 | cERROR(1, "Challenge target info allocation failure"); | 413 | cERROR(1, "Challenge target info allocation failure"); |
415 | ses->tilen = 0; | ||
416 | return -ENOMEM; | 414 | return -ENOMEM; |
417 | } | 415 | } |
418 | memcpy(ses->tiblob, bcc_ptr + tioffset, ses->tilen); | 416 | memcpy(ses->auth_key.response, bcc_ptr + tioffset, tilen); |
417 | ses->auth_key.len = tilen; | ||
419 | } | 418 | } |
420 | 419 | ||
421 | return 0; | 420 | return 0; |
@@ -545,9 +544,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
545 | sec_blob->WorkstationName.MaximumLength = 0; | 544 | sec_blob->WorkstationName.MaximumLength = 0; |
546 | tmp += 2; | 545 | tmp += 2; |
547 | 546 | ||
548 | if ((ses->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && | 547 | if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && |
549 | !calc_seckey(ses)) { | 548 | !calc_seckey(ses)) { |
550 | memcpy(tmp, ses->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); | 549 | memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); |
551 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | 550 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); |
552 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); | 551 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); |
553 | sec_blob->SessionKey.MaximumLength = | 552 | sec_blob->SessionKey.MaximumLength = |
@@ -601,8 +600,16 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
601 | return -EINVAL; | 600 | return -EINVAL; |
602 | 601 | ||
603 | type = ses->server->secType; | 602 | type = ses->server->secType; |
604 | |||
605 | cFYI(1, "sess setup type %d", type); | 603 | cFYI(1, "sess setup type %d", type); |
604 | if (type == RawNTLMSSP) { | ||
605 | /* if memory allocation is successful, caller of this function | ||
606 | * frees it. | ||
607 | */ | ||
608 | ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL); | ||
609 | if (!ses->ntlmssp) | ||
610 | return -ENOMEM; | ||
611 | } | ||
612 | |||
606 | ssetup_ntlmssp_authenticate: | 613 | ssetup_ntlmssp_authenticate: |
607 | if (phase == NtLmChallenge) | 614 | if (phase == NtLmChallenge) |
608 | phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ | 615 | phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ |