diff options
Diffstat (limited to 'fs/cifs/sess.c')
-rw-r--r-- | fs/cifs/sess.c | 132 |
1 files changed, 98 insertions, 34 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 0a57cb7db5d..795095f4eac 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, | |||
383 | static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | 383 | static 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 | |||
573 | setup_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 | ||
549 | static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, | 590 | static 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 | } |
@@ -690,7 +730,7 @@ ssetup_ntlmssp_authenticate: | |||
690 | 730 | ||
691 | if (first_time) /* should this be moved into common code | 731 | if (first_time) /* should this be moved into common code |
692 | with similar ntlmv2 path? */ | 732 | with similar ntlmv2 path? */ |
693 | cifs_calculate_mac_key(&ses->server->mac_signing_key, | 733 | cifs_calculate_session_key(&ses->server->session_key, |
694 | ntlm_session_key, ses->password); | 734 | ntlm_session_key, ses->password); |
695 | /* copy session key */ | 735 | /* copy session key */ |
696 | 736 | ||
@@ -729,12 +769,21 @@ ssetup_ntlmssp_authenticate: | |||
729 | cpu_to_le16(sizeof(struct ntlmv2_resp)); | 769 | cpu_to_le16(sizeof(struct ntlmv2_resp)); |
730 | 770 | ||
731 | /* calculate session key */ | 771 | /* calculate session key */ |
732 | setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); | 772 | rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); |
773 | if (rc) { | ||
774 | kfree(v2_sess_key); | ||
775 | goto ssetup_exit; | ||
776 | } | ||
733 | /* FIXME: calculate MAC key */ | 777 | /* FIXME: calculate MAC key */ |
734 | memcpy(bcc_ptr, (char *)v2_sess_key, | 778 | memcpy(bcc_ptr, (char *)v2_sess_key, |
735 | sizeof(struct ntlmv2_resp)); | 779 | sizeof(struct ntlmv2_resp)); |
736 | bcc_ptr += sizeof(struct ntlmv2_resp); | 780 | bcc_ptr += sizeof(struct ntlmv2_resp); |
737 | kfree(v2_sess_key); | 781 | kfree(v2_sess_key); |
782 | if (ses->server->tilen > 0) { | ||
783 | memcpy(bcc_ptr, ses->server->tiblob, | ||
784 | ses->server->tilen); | ||
785 | bcc_ptr += ses->server->tilen; | ||
786 | } | ||
738 | if (ses->capabilities & CAP_UNICODE) { | 787 | if (ses->capabilities & CAP_UNICODE) { |
739 | if (iov[0].iov_len % 2) { | 788 | if (iov[0].iov_len % 2) { |
740 | *bcc_ptr = 0; | 789 | *bcc_ptr = 0; |
@@ -765,15 +814,15 @@ ssetup_ntlmssp_authenticate: | |||
765 | } | 814 | } |
766 | /* bail out if key is too long */ | 815 | /* bail out if key is too long */ |
767 | if (msg->sesskey_len > | 816 | if (msg->sesskey_len > |
768 | sizeof(ses->server->mac_signing_key.data.krb5)) { | 817 | sizeof(ses->server->session_key.data.krb5)) { |
769 | cERROR(1, "Kerberos signing key too long (%u bytes)", | 818 | cERROR(1, "Kerberos signing key too long (%u bytes)", |
770 | msg->sesskey_len); | 819 | msg->sesskey_len); |
771 | rc = -EOVERFLOW; | 820 | rc = -EOVERFLOW; |
772 | goto ssetup_exit; | 821 | goto ssetup_exit; |
773 | } | 822 | } |
774 | if (first_time) { | 823 | if (first_time) { |
775 | ses->server->mac_signing_key.len = msg->sesskey_len; | 824 | ses->server->session_key.len = msg->sesskey_len; |
776 | memcpy(ses->server->mac_signing_key.data.krb5, | 825 | memcpy(ses->server->session_key.data.krb5, |
777 | msg->data, msg->sesskey_len); | 826 | msg->data, msg->sesskey_len); |
778 | } | 827 | } |
779 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 828 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
@@ -815,12 +864,28 @@ ssetup_ntlmssp_authenticate: | |||
815 | if (phase == NtLmNegotiate) { | 864 | if (phase == NtLmNegotiate) { |
816 | setup_ntlmssp_neg_req(pSMB, ses); | 865 | setup_ntlmssp_neg_req(pSMB, ses); |
817 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); | 866 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); |
867 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
818 | } else if (phase == NtLmAuthenticate) { | 868 | } else if (phase == NtLmAuthenticate) { |
819 | int blob_len; | 869 | int blob_len; |
820 | blob_len = setup_ntlmssp_auth_req(pSMB, ses, | 870 | char *ntlmsspblob; |
821 | nls_cp, | 871 | |
822 | first_time); | 872 | ntlmsspblob = kmalloc(5 * |
873 | sizeof(struct _AUTHENTICATE_MESSAGE), | ||
874 | GFP_KERNEL); | ||
875 | if (!ntlmsspblob) { | ||
876 | cERROR(1, "Can't allocate NTLMSSP"); | ||
877 | rc = -ENOMEM; | ||
878 | goto ssetup_exit; | ||
879 | } | ||
880 | |||
881 | blob_len = setup_ntlmssp_auth_req(ntlmsspblob, | ||
882 | ses, | ||
883 | nls_cp, | ||
884 | first_time); | ||
823 | iov[1].iov_len = blob_len; | 885 | iov[1].iov_len = blob_len; |
886 | iov[1].iov_base = ntlmsspblob; | ||
887 | pSMB->req.SecurityBlobLength = | ||
888 | cpu_to_le16(blob_len); | ||
824 | /* Make sure that we tell the server that we | 889 | /* Make sure that we tell the server that we |
825 | are using the uid that it just gave us back | 890 | are using the uid that it just gave us back |
826 | on the response (challenge) */ | 891 | on the response (challenge) */ |
@@ -830,7 +895,6 @@ ssetup_ntlmssp_authenticate: | |||
830 | rc = -ENOSYS; | 895 | rc = -ENOSYS; |
831 | goto ssetup_exit; | 896 | goto ssetup_exit; |
832 | } | 897 | } |
833 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
834 | /* unicode strings must be word aligned */ | 898 | /* unicode strings must be word aligned */ |
835 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { | 899 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { |
836 | *bcc_ptr = 0; | 900 | *bcc_ptr = 0; |