|
17 | 17 | #include "nterr.h"
|
18 | 18 | #include <linux/utsname.h>
|
19 | 19 | #include <linux/slab.h>
|
| 20 | +#include <linux/version.h> |
| 21 | +#include "cifsfs.h" |
20 | 22 | #include "cifs_spnego.h"
|
21 | 23 | #include "smb2proto.h"
|
22 | 24 | #include "fs_context.h"
|
@@ -809,6 +811,74 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
|
809 | 811 | return rc;
|
810 | 812 | }
|
811 | 813 |
|
| 814 | +/* |
| 815 | + * Build ntlmssp blob with additional fields, such as version, |
| 816 | + * supported by modern servers. For safety limit to SMB3 or later |
| 817 | + * See notes in MS-NLMP Section 2.2.2.1 e.g. |
| 818 | + */ |
| 819 | +int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, |
| 820 | + u16 *buflen, |
| 821 | + struct cifs_ses *ses, |
| 822 | + struct TCP_Server_Info *server, |
| 823 | + const struct nls_table *nls_cp) |
| 824 | +{ |
| 825 | + int rc = 0; |
| 826 | + struct negotiate_message *sec_blob; |
| 827 | + __u32 flags; |
| 828 | + unsigned char *tmp; |
| 829 | + int len; |
| 830 | + |
| 831 | + len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message)); |
| 832 | + *pbuffer = kmalloc(len, GFP_KERNEL); |
| 833 | + if (!*pbuffer) { |
| 834 | + rc = -ENOMEM; |
| 835 | + cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); |
| 836 | + *buflen = 0; |
| 837 | + goto setup_ntlm_smb3_neg_ret; |
| 838 | + } |
| 839 | + sec_blob = (struct negotiate_message *)*pbuffer; |
| 840 | + |
| 841 | + memset(*pbuffer, 0, sizeof(struct negotiate_message)); |
| 842 | + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); |
| 843 | + sec_blob->MessageType = NtLmNegotiate; |
| 844 | + |
| 845 | + /* BB is NTLMV2 session security format easier to use here? */ |
| 846 | + flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
| 847 | + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
| 848 | + NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | |
| 849 | + NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL | |
| 850 | + NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION; |
| 851 | + if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) |
| 852 | + flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
| 853 | + |
| 854 | + sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR; |
| 855 | + sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL; |
| 856 | + sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD); |
| 857 | + sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3; |
| 858 | + |
| 859 | + tmp = *pbuffer + sizeof(struct negotiate_message); |
| 860 | + ses->ntlmssp->client_flags = flags; |
| 861 | + sec_blob->NegotiateFlags = cpu_to_le32(flags); |
| 862 | + |
| 863 | + /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */ |
| 864 | + cifs_security_buffer_from_str(&sec_blob->DomainName, |
| 865 | + NULL, |
| 866 | + CIFS_MAX_DOMAINNAME_LEN, |
| 867 | + *pbuffer, &tmp, |
| 868 | + nls_cp); |
| 869 | + |
| 870 | + cifs_security_buffer_from_str(&sec_blob->WorkstationName, |
| 871 | + NULL, |
| 872 | + CIFS_MAX_WORKSTATION_LEN, |
| 873 | + *pbuffer, &tmp, |
| 874 | + nls_cp); |
| 875 | + |
| 876 | + *buflen = tmp - *pbuffer; |
| 877 | +setup_ntlm_smb3_neg_ret: |
| 878 | + return rc; |
| 879 | +} |
| 880 | + |
| 881 | + |
812 | 882 | int build_ntlmssp_auth_blob(unsigned char **pbuffer,
|
813 | 883 | u16 *buflen,
|
814 | 884 | struct cifs_ses *ses,
|
|
0 commit comments