| @@ -46,6 +46,7 @@ · 45 unmodified lines |
| 46 | #include "smb2status.h" | 46 | #include "smb2status.h" |
| 47 | #include "smb2glob.h" | 47 | #include "smb2glob.h" |
| 48 | #include "cifspdu.h" | 48 | #include "cifspdu.h" |
| | 49 | #include "cifs_spnego.h" |
| 49 | | 50 | |
| 50 | /* | 51 | /* |
| 51 | * The following table defines the expected "StructureSize" of SMB2 requests | 52 | * The following table defines the expected "StructureSize" of SMB2 requests |
| @@ -486,19 +487,15 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) · 434 unmodified lines |
| 486 | cifs_dbg(FYI, "missing security blob on negprot\n"); | 487 | cifs_dbg(FYI, "missing security blob on negprot\n"); |
| 487 | | 488 | |
| 488 | rc = cifs_enable_signing(server, ses->sign); | 489 | rc = cifs_enable_signing(server, ses->sign); |
| 489 | #ifdef CONFIG_SMB2_ASN1 /* BB REMOVEME when updated asn1.c ready */ | | |
| 490 | if (rc) | 490 | if (rc) |
| 491 | goto neg_exit; | 491 | goto neg_exit; |
| 492 | if (blob_length) | 492 | if (blob_length) { |
| 493 | rc = decode_negTokenInit(security_blob, blob_length, server); | 493 | rc = decode_negTokenInit(security_blob, blob_length, server); |
| 494 | if (rc == 1) | 494 | if (rc == 1) |
| 495 | rc = 0; | 495 | rc = 0; |
| 496 | else if (rc == 0) { | 496 | else if (rc == 0) |
| 497 | rc = -EIO; | 497 | rc = -EIO; |
| 498 | goto neg_exit; | | |
| 499 | } | 498 | } |
| 500 | #endif | | |
| 501 | | | |
| 502 | neg_exit: | 499 | neg_exit: |
| 503 | free_rsp_buf(resp_buftype, rsp); | 500 | free_rsp_buf(resp_buftype, rsp); |
| 504 | return rc; | 501 | return rc; |
| @@ -592,7 +589,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, · 87 unmodified lines |
| 592 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ | 589 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ |
| 593 | struct TCP_Server_Info *server = ses->server; | 590 | struct TCP_Server_Info *server = ses->server; |
| 594 | u16 blob_length = 0; | 591 | u16 blob_length = 0; |
| 595 | char *security_blob; | 592 | struct key *spnego_key = NULL; |
| | 593 | char *security_blob = NULL; |
| 596 | char *ntlmssp_blob = NULL; | 594 | char *ntlmssp_blob = NULL; |
| 597 | bool use_spnego = false; /* else use raw ntlmssp */ | 595 | bool use_spnego = false; /* else use raw ntlmssp */ |
| 598 | | 596 | |
| @@ -620,7 +618,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, · 21 unmodified lines |
| 620 | ses->ntlmssp->sesskey_per_smbsess = true; | 618 | ses->ntlmssp->sesskey_per_smbsess = true; |
| 621 | | 619 | |
| 622 | /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */ | 620 | /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */ |
| 623 | ses->sectype = RawNTLMSSP; | 621 | if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP) |
| | 622 | ses->sectype = RawNTLMSSP; |
| 624 | | 623 | |
| 625 | ssetup_ntlmssp_authenticate: | 624 | ssetup_ntlmssp_authenticate: |
| 626 | if (phase == NtLmChallenge) | 625 | if (phase == NtLmChallenge) |
| @@ -649,7 +648,48 @@ ssetup_ntlmssp_authenticate: · 22 unmodified lines |
| 649 | iov[0].iov_base = (char *)req; | 648 | iov[0].iov_base = (char *)req; |
| 650 | /* 4 for rfc1002 length field and 1 for pad */ | 649 | /* 4 for rfc1002 length field and 1 for pad */ |
| 651 | iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; | 650 | iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; |
| 652 | if (phase == NtLmNegotiate) { | 651 | |
| | 652 | if (ses->sectype == Kerberos) { |
| | 653 | #ifdef CONFIG_CIFS_UPCALL |
| | 654 | struct cifs_spnego_msg *msg; |
| | 655 | |
| | 656 | spnego_key = cifs_get_spnego_key(ses); |
| | 657 | if (IS_ERR(spnego_key)) { |
| | 658 | rc = PTR_ERR(spnego_key); |
| | 659 | spnego_key = NULL; |
| | 660 | goto ssetup_exit; |
| | 661 | } |
| | 662 | |
| | 663 | msg = spnego_key->payload.data; |
| | 664 | /* |
| | 665 | * check version field to make sure that cifs.upcall is |
| | 666 | * sending us a response in an expected form |
| | 667 | */ |
| | 668 | if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { |
| | 669 | cifs_dbg(VFS, |
| | 670 | "bad cifs.upcall version. Expected %d got %d", |
| | 671 | CIFS_SPNEGO_UPCALL_VERSION, msg->version); |
| | 672 | rc = -EKEYREJECTED; |
| | 673 | goto ssetup_exit; |
| | 674 | } |
| | 675 | ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len, |
| | 676 | GFP_KERNEL); |
| | 677 | if (!ses->auth_key.response) { |
| | 678 | cifs_dbg(VFS, |
| | 679 | "Kerberos can't allocate (%u bytes) memory", |
| | 680 | msg->sesskey_len); |
| | 681 | rc = -ENOMEM; |
| | 682 | goto ssetup_exit; |
| | 683 | } |
| | 684 | ses->auth_key.len = msg->sesskey_len; |
| | 685 | blob_length = msg->secblob_len; |
| | 686 | iov[1].iov_base = msg->data + msg->sesskey_len; |
| | 687 | iov[1].iov_len = blob_length; |
| | 688 | #else |
| | 689 | rc = -EOPNOTSUPP; |
| | 690 | goto ssetup_exit; |
| | 691 | #endif /* CONFIG_CIFS_UPCALL */ |
| | 692 | } else if (phase == NtLmNegotiate) { /* if not krb5 must be ntlmssp */ |
| 653 | ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE), | 693 | ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE), |
| 654 | GFP_KERNEL); | 694 | GFP_KERNEL); |
| 655 | if (ntlmssp_blob == NULL) { | 695 | if (ntlmssp_blob == NULL) { |
| @@ -672,6 +712,8 @@ ssetup_ntlmssp_authenticate: · 16 unmodified lines |
| 672 | /* with raw NTLMSSP we don't encapsulate in SPNEGO */ | 712 | /* with raw NTLMSSP we don't encapsulate in SPNEGO */ |
| 673 | security_blob = ntlmssp_blob; | 713 | security_blob = ntlmssp_blob; |
| 674 | } | 714 | } |
| | 715 | iov[1].iov_base = security_blob; |
| | 716 | iov[1].iov_len = blob_length; |
| 675 | } else if (phase == NtLmAuthenticate) { | 717 | } else if (phase == NtLmAuthenticate) { |
| 676 | req->hdr.SessionId = ses->Suid; | 718 | req->hdr.SessionId = ses->Suid; |
| 677 | ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500, | 719 | ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500, |
| @@ -699,6 +741,8 @@ ssetup_ntlmssp_authenticate: · 21 unmodified lines |
| 699 | } else { | 741 | } else { |
| 700 | security_blob = ntlmssp_blob; | 742 | security_blob = ntlmssp_blob; |
| 701 | } | 743 | } |
| | 744 | iov[1].iov_base = security_blob; |
| | 745 | iov[1].iov_len = blob_length; |
| 702 | } else { | 746 | } else { |
| 703 | cifs_dbg(VFS, "illegal ntlmssp phase\n"); | 747 | cifs_dbg(VFS, "illegal ntlmssp phase\n"); |
| 704 | rc = -EIO; | 748 | rc = -EIO; |
| @@ -710,8 +754,6 @@ ssetup_ntlmssp_authenticate: · 5 unmodified lines |
| 710 | cpu_to_le16(sizeof(struct smb2_sess_setup_req) - | 754 | cpu_to_le16(sizeof(struct smb2_sess_setup_req) - |
| 711 | 1 /* pad */ - 4 /* rfc1001 len */); | 755 | 1 /* pad */ - 4 /* rfc1001 len */); |
| 712 | req->SecurityBufferLength = cpu_to_le16(blob_length); | 756 | req->SecurityBufferLength = cpu_to_le16(blob_length); |
| 713 | iov[1].iov_base = security_blob; | | |
| 714 | iov[1].iov_len = blob_length; | | |
| 715 | | 757 | |
| 716 | inc_rfc1001_len(req, blob_length - 1 /* pad */); | 758 | inc_rfc1001_len(req, blob_length - 1 /* pad */); |
| 717 | | 759 | |
| @@ -722,6 +764,7 @@ ssetup_ntlmssp_authenticate: · 4 unmodified lines |
| 722 | | 764 | |
| 723 | kfree(security_blob); | 765 | kfree(security_blob); |
| 724 | rsp = (struct smb2_sess_setup_rsp *)iov[0].iov_base; | 766 | rsp = (struct smb2_sess_setup_rsp *)iov[0].iov_base; |
| | 767 | ses->Suid = rsp->hdr.SessionId; |
| 725 | if (resp_buftype != CIFS_NO_BUFFER && | 768 | if (resp_buftype != CIFS_NO_BUFFER && |
| 726 | rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) { | 769 | rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) { |
| 727 | if (phase != NtLmNegotiate) { | 770 | if (phase != NtLmNegotiate) { |
| @@ -739,7 +782,6 @@ ssetup_ntlmssp_authenticate: · 11 unmodified lines |
| 739 | /* NTLMSSP Negotiate sent now processing challenge (response) */ | 782 | /* NTLMSSP Negotiate sent now processing challenge (response) */ |
| 740 | phase = NtLmChallenge; /* process ntlmssp challenge */ | 783 | phase = NtLmChallenge; /* process ntlmssp challenge */ |
| 741 | rc = 0; /* MORE_PROCESSING is not an error here but expected */ | 784 | rc = 0; /* MORE_PROCESSING is not an error here but expected */ |
| 742 | ses->Suid = rsp->hdr.SessionId; | | |
| 743 | rc = decode_ntlmssp_challenge(rsp->Buffer, | 785 | rc = decode_ntlmssp_challenge(rsp->Buffer, |
| 744 | le16_to_cpu(rsp->SecurityBufferLength), ses); | 786 | le16_to_cpu(rsp->SecurityBufferLength), ses); |
| 745 | } | 787 | } |
| @@ -796,6 +838,10 @@ keygen_exit: · 50 unmodified lines |
| 796 | kfree(ses->auth_key.response); | 838 | kfree(ses->auth_key.response); |
| 797 | ses->auth_key.response = NULL; | 839 | ses->auth_key.response = NULL; |
| 798 | } | 840 | } |
| | 841 | if (spnego_key) { |
| | 842 | key_invalidate(spnego_key); |
| | 843 | key_put(spnego_key); |
| | 844 | } |
| 799 | kfree(ses->ntlmssp); | 845 | kfree(ses->ntlmssp); |
| 800 | | 846 | |
| 801 | return rc; | 847 | return rc; |
| @@ -876,6 +922,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, · 74 unmodified lines |
| 876 | if (tcon && tcon->bad_network_name) | 922 | if (tcon && tcon->bad_network_name) |
| 877 | return -ENOENT; | 923 | return -ENOENT; |
| 878 | | 924 | |
| | 925 | if ((tcon->seal) && |
| | 926 | ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) { |
| | 927 | cifs_dbg(VFS, "encryption requested but no server support"); |
| | 928 | return -EOPNOTSUPP; |
| | 929 | } |
| | 930 | |
| 879 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); | 931 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); |
| 880 | if (unc_path == NULL) | 932 | if (unc_path == NULL) |
| 881 | return -ENOMEM; | 933 | return -ENOMEM; |
| @@ -955,6 +1007,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, · 73 unmodified lines |
| 955 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) | 1007 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
| 956 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); | 1008 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); |
| 957 | init_copy_chunk_defaults(tcon); | 1009 | init_copy_chunk_defaults(tcon); |
| | 1010 | if (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA) |
| | 1011 | cifs_dbg(VFS, "Encrypted shares not supported"); |
| 958 | if (tcon->ses->server->ops->validate_negotiate) | 1012 | if (tcon->ses->server->ops->validate_negotiate) |
| 959 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); | 1013 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); |
| 960 | tcon_exit: | 1014 | tcon_exit: |