aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/sess.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/sess.c')
-rw-r--r--fs/cifs/sess.c131
1 files changed, 97 insertions, 34 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 0a57cb7db5dd..4788e16a02cc 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -383,6 +383,9 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
383static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, 383static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
384 struct cifsSesInfo *ses) 384 struct cifsSesInfo *ses)
385{ 385{
386 unsigned int tioffset; /* challeng message target info area */
387 unsigned int tilen; /* challeng message target info area length */
388
386 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; 389 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
387 390
388 if (blob_len < sizeof(CHALLENGE_MESSAGE)) { 391 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
@@ -405,6 +408,20 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
405 /* BB spec says that if AvId field of MsvAvTimestamp is populated then 408 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
406 we must set the MIC field of the AUTHENTICATE_MESSAGE */ 409 we must set the MIC field of the AUTHENTICATE_MESSAGE */
407 410
411 ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags);
412
413 tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
414 tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
415 ses->server->tilen = tilen;
416 if (tilen) {
417 ses->server->tiblob = kmalloc(tilen, GFP_KERNEL);
418 if (!ses->server->tiblob) {
419 cERROR(1, "Challenge target info allocation failure");
420 return -ENOMEM;
421 }
422 memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen);
423 }
424
408 return 0; 425 return 0;
409} 426}
410 427
@@ -425,12 +442,13 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
425 /* BB is NTLMV2 session security format easier to use here? */ 442 /* BB is NTLMV2 session security format easier to use here? */
426 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | 443 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
427 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 444 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
428 NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; 445 NTLMSSP_NEGOTIATE_NTLM;
429 if (ses->server->secMode & 446 if (ses->server->secMode &
430 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 447 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
431 flags |= NTLMSSP_NEGOTIATE_SIGN; 448 flags |= NTLMSSP_NEGOTIATE_SIGN |
432 if (ses->server->secMode & SECMODE_SIGN_REQUIRED) 449 NTLMSSP_NEGOTIATE_KEY_XCH |
433 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 450 NTLMSSP_NEGOTIATE_EXTENDED_SEC;
451 }
434 452
435 sec_blob->NegotiateFlags |= cpu_to_le32(flags); 453 sec_blob->NegotiateFlags |= cpu_to_le32(flags);
436 454
@@ -451,10 +469,12 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
451 struct cifsSesInfo *ses, 469 struct cifsSesInfo *ses,
452 const struct nls_table *nls_cp, bool first) 470 const struct nls_table *nls_cp, bool first)
453{ 471{
472 int rc;
473 unsigned int size;
454 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 474 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
455 __u32 flags; 475 __u32 flags;
456 unsigned char *tmp; 476 unsigned char *tmp;
457 char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 477 struct ntlmv2_resp ntlmv2_response = {};
458 478
459 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 479 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
460 sec_blob->MessageType = NtLmAuthenticate; 480 sec_blob->MessageType = NtLmAuthenticate;
@@ -477,19 +497,25 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
477 sec_blob->LmChallengeResponse.Length = 0; 497 sec_blob->LmChallengeResponse.Length = 0;
478 sec_blob->LmChallengeResponse.MaximumLength = 0; 498 sec_blob->LmChallengeResponse.MaximumLength = 0;
479 499
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_mac_key(&ses->server->mac_signing_key,
484 ntlm_session_key, ses->password);
485
486 memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
487 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 500 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
488 sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); 501 rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
489 sec_blob->NtChallengeResponse.MaximumLength = 502 if (rc) {
490 cpu_to_le16(CIFS_SESS_KEY_SIZE); 503 cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc);
504 goto setup_ntlmv2_ret;
505 }
506 size = sizeof(struct ntlmv2_resp);
507 memcpy(tmp, (char *)&ntlmv2_response, size);
508 tmp += size;
509 if (ses->server->tilen > 0) {
510 memcpy(tmp, ses->server->tiblob, ses->server->tilen);
511 tmp += ses->server->tilen;
512 } else
513 ses->server->tilen = 0;
491 514
492 tmp += CIFS_SESS_KEY_SIZE; 515 sec_blob->NtChallengeResponse.Length = cpu_to_le16(size +
516 ses->server->tilen);
517 sec_blob->NtChallengeResponse.MaximumLength =
518 cpu_to_le16(size + ses->server->tilen);
493 519
494 if (ses->domainName == NULL) { 520 if (ses->domainName == NULL) {
495 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 521 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -501,7 +527,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
501 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, 527 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
502 MAX_USERNAME_SIZE, nls_cp); 528 MAX_USERNAME_SIZE, nls_cp);
503 len *= 2; /* unicode is 2 bytes each */ 529 len *= 2; /* unicode is 2 bytes each */
504 len += 2; /* trailing null */
505 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 530 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
506 sec_blob->DomainName.Length = cpu_to_le16(len); 531 sec_blob->DomainName.Length = cpu_to_le16(len);
507 sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 532 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
@@ -518,7 +543,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
518 len = cifs_strtoUCS((__le16 *)tmp, ses->userName, 543 len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
519 MAX_USERNAME_SIZE, nls_cp); 544 MAX_USERNAME_SIZE, nls_cp);
520 len *= 2; /* unicode is 2 bytes each */ 545 len *= 2; /* unicode is 2 bytes each */
521 len += 2; /* trailing null */
522 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 546 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
523 sec_blob->UserName.Length = cpu_to_le16(len); 547 sec_blob->UserName.Length = cpu_to_le16(len);
524 sec_blob->UserName.MaximumLength = cpu_to_le16(len); 548 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
@@ -530,9 +554,26 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
530 sec_blob->WorkstationName.MaximumLength = 0; 554 sec_blob->WorkstationName.MaximumLength = 0;
531 tmp += 2; 555 tmp += 2;
532 556
533 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 557 if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
534 sec_blob->SessionKey.Length = 0; 558 !calc_seckey(ses->server)) {
535 sec_blob->SessionKey.MaximumLength = 0; 559 memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
560 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
561 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
562 sec_blob->SessionKey.MaximumLength =
563 cpu_to_le16(CIFS_CPHTXT_SIZE);
564 tmp += CIFS_CPHTXT_SIZE;
565 } else {
566 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
567 sec_blob->SessionKey.Length = 0;
568 sec_blob->SessionKey.MaximumLength = 0;
569 }
570
571 ses->server->sequence_number = 0;
572
573setup_ntlmv2_ret:
574 if (ses->server->tilen > 0)
575 kfree(ses->server->tiblob);
576
536 return tmp - pbuffer; 577 return tmp - pbuffer;
537} 578}
538 579
@@ -546,15 +587,14 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
546 return; 587 return;
547} 588}
548 589
549static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, 590static int setup_ntlmssp_auth_req(char *ntlmsspblob,
550 struct cifsSesInfo *ses, 591 struct cifsSesInfo *ses,
551 const struct nls_table *nls, bool first_time) 592 const struct nls_table *nls, bool first_time)
552{ 593{
553 int bloblen; 594 int bloblen;
554 595
555 bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, 596 bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls,
556 first_time); 597 first_time);
557 pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
558 598
559 return bloblen; 599 return bloblen;
560} 600}
@@ -580,6 +620,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
580 struct key *spnego_key = NULL; 620 struct key *spnego_key = NULL;
581 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 621 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
582 bool first_time; 622 bool first_time;
623 char *ntlmsspblob;
583 624
584 if (ses == NULL) 625 if (ses == NULL)
585 return -EINVAL; 626 return -EINVAL;
@@ -690,7 +731,7 @@ ssetup_ntlmssp_authenticate:
690 731
691 if (first_time) /* should this be moved into common code 732 if (first_time) /* should this be moved into common code
692 with similar ntlmv2 path? */ 733 with similar ntlmv2 path? */
693 cifs_calculate_mac_key(&ses->server->mac_signing_key, 734 cifs_calculate_session_key(&ses->server->session_key,
694 ntlm_session_key, ses->password); 735 ntlm_session_key, ses->password);
695 /* copy session key */ 736 /* copy session key */
696 737
@@ -729,12 +770,21 @@ ssetup_ntlmssp_authenticate:
729 cpu_to_le16(sizeof(struct ntlmv2_resp)); 770 cpu_to_le16(sizeof(struct ntlmv2_resp));
730 771
731 /* calculate session key */ 772 /* calculate session key */
732 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 773 rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
774 if (rc) {
775 kfree(v2_sess_key);
776 goto ssetup_exit;
777 }
733 /* FIXME: calculate MAC key */ 778 /* FIXME: calculate MAC key */
734 memcpy(bcc_ptr, (char *)v2_sess_key, 779 memcpy(bcc_ptr, (char *)v2_sess_key,
735 sizeof(struct ntlmv2_resp)); 780 sizeof(struct ntlmv2_resp));
736 bcc_ptr += sizeof(struct ntlmv2_resp); 781 bcc_ptr += sizeof(struct ntlmv2_resp);
737 kfree(v2_sess_key); 782 kfree(v2_sess_key);
783 if (ses->server->tilen > 0) {
784 memcpy(bcc_ptr, ses->server->tiblob,
785 ses->server->tilen);
786 bcc_ptr += ses->server->tilen;
787 }
738 if (ses->capabilities & CAP_UNICODE) { 788 if (ses->capabilities & CAP_UNICODE) {
739 if (iov[0].iov_len % 2) { 789 if (iov[0].iov_len % 2) {
740 *bcc_ptr = 0; 790 *bcc_ptr = 0;
@@ -765,15 +815,15 @@ ssetup_ntlmssp_authenticate:
765 } 815 }
766 /* bail out if key is too long */ 816 /* bail out if key is too long */
767 if (msg->sesskey_len > 817 if (msg->sesskey_len >
768 sizeof(ses->server->mac_signing_key.data.krb5)) { 818 sizeof(ses->server->session_key.data.krb5)) {
769 cERROR(1, "Kerberos signing key too long (%u bytes)", 819 cERROR(1, "Kerberos signing key too long (%u bytes)",
770 msg->sesskey_len); 820 msg->sesskey_len);
771 rc = -EOVERFLOW; 821 rc = -EOVERFLOW;
772 goto ssetup_exit; 822 goto ssetup_exit;
773 } 823 }
774 if (first_time) { 824 if (first_time) {
775 ses->server->mac_signing_key.len = msg->sesskey_len; 825 ses->server->session_key.len = msg->sesskey_len;
776 memcpy(ses->server->mac_signing_key.data.krb5, 826 memcpy(ses->server->session_key.data.krb5,
777 msg->data, msg->sesskey_len); 827 msg->data, msg->sesskey_len);
778 } 828 }
779 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 829 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -815,12 +865,26 @@ ssetup_ntlmssp_authenticate:
815 if (phase == NtLmNegotiate) { 865 if (phase == NtLmNegotiate) {
816 setup_ntlmssp_neg_req(pSMB, ses); 866 setup_ntlmssp_neg_req(pSMB, ses);
817 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 867 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
868 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
818 } else if (phase == NtLmAuthenticate) { 869 } else if (phase == NtLmAuthenticate) {
819 int blob_len; 870 int blob_len;
820 blob_len = setup_ntlmssp_auth_req(pSMB, ses, 871 ntlmsspblob = kmalloc(5 *
821 nls_cp, 872 sizeof(struct _AUTHENTICATE_MESSAGE),
822 first_time); 873 GFP_KERNEL);
874 if (!ntlmsspblob) {
875 cERROR(1, "Can't allocate NTLMSSP");
876 rc = -ENOMEM;
877 goto ssetup_exit;
878 }
879
880 blob_len = setup_ntlmssp_auth_req(ntlmsspblob,
881 ses,
882 nls_cp,
883 first_time);
823 iov[1].iov_len = blob_len; 884 iov[1].iov_len = blob_len;
885 iov[1].iov_base = ntlmsspblob;
886 pSMB->req.SecurityBlobLength =
887 cpu_to_le16(blob_len);
824 /* Make sure that we tell the server that we 888 /* Make sure that we tell the server that we
825 are using the uid that it just gave us back 889 are using the uid that it just gave us back
826 on the response (challenge) */ 890 on the response (challenge) */
@@ -830,7 +894,6 @@ ssetup_ntlmssp_authenticate:
830 rc = -ENOSYS; 894 rc = -ENOSYS;
831 goto ssetup_exit; 895 goto ssetup_exit;
832 } 896 }
833 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
834 /* unicode strings must be word aligned */ 897 /* unicode strings must be word aligned */
835 if ((iov[0].iov_len + iov[1].iov_len) % 2) { 898 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
836 *bcc_ptr = 0; 899 *bcc_ptr = 0;