mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
smb: client: fix session setup against servers that require SPN
Some servers might enforce the SPN to be set in the target info blob (AV pairs) when sending NTLMSSP_AUTH message. In Windows Server, this could be enforced with SmbServerNameHardeningLevel set to 2. Fix this by always appending SPN (cifs/<hostname>) to the existing list of target infos when setting up NTLMv2 response blob. Cc: linux-cifs@vger.kernel.org Cc: David Howells <dhowells@redhat.com> Reported-by: Pierguido Lambri <plambri@redhat.com> Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
be77ab6b9f
commit
33cfdd7263
|
|
@ -532,17 +532,67 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up NTLMv2 response blob with SPN (cifs/<hostname>) appended to the
|
||||
* existing list of AV pairs.
|
||||
*/
|
||||
static int set_auth_key_response(struct cifs_ses *ses)
|
||||
{
|
||||
size_t baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
|
||||
size_t len, spnlen, tilen = 0, num_avs = 2 /* SPN + EOL */;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
char *spn __free(kfree) = NULL;
|
||||
struct ntlmssp2_name *av;
|
||||
char *rsp = NULL;
|
||||
int rc;
|
||||
|
||||
spnlen = strlen(server->hostname);
|
||||
len = sizeof("cifs/") + spnlen;
|
||||
spn = kmalloc(len, GFP_KERNEL);
|
||||
if (!spn) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spnlen = scnprintf(spn, len, "cifs/%.*s",
|
||||
(int)spnlen, server->hostname);
|
||||
|
||||
av_for_each_entry(ses, av)
|
||||
tilen += sizeof(*av) + AV_LEN(av);
|
||||
|
||||
len = baselen + tilen + spnlen * sizeof(__le16) + num_avs * sizeof(*av);
|
||||
rsp = kmalloc(len, GFP_KERNEL);
|
||||
if (!rsp) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(rsp + baselen, ses->auth_key.response, tilen);
|
||||
av = (void *)(rsp + baselen + tilen);
|
||||
av->type = cpu_to_le16(NTLMSSP_AV_TARGET_NAME);
|
||||
av->length = cpu_to_le16(spnlen * sizeof(__le16));
|
||||
cifs_strtoUTF16((__le16 *)av->data, spn, spnlen, ses->local_nls);
|
||||
av = (void *)((__u8 *)av + sizeof(*av) + AV_LEN(av));
|
||||
av->type = cpu_to_le16(NTLMSSP_AV_EOL);
|
||||
av->length = 0;
|
||||
|
||||
rc = 0;
|
||||
ses->auth_key.len = len;
|
||||
out:
|
||||
ses->auth_key.response = rsp;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
||||
{
|
||||
struct shash_desc *hmacmd5 = NULL;
|
||||
int rc;
|
||||
int baselen;
|
||||
unsigned int tilen;
|
||||
unsigned char *tiblob = NULL; /* target info blob */
|
||||
struct ntlmv2_resp *ntlmv2;
|
||||
char ntlmv2_hash[16];
|
||||
unsigned char *tiblob = NULL; /* target info blob */
|
||||
__le64 rsp_timestamp;
|
||||
__u64 cc;
|
||||
int rc;
|
||||
|
||||
if (nls_cp == NULL) {
|
||||
cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
|
||||
|
|
@ -588,32 +638,25 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|||
* (as Windows 7 does)
|
||||
*/
|
||||
rsp_timestamp = find_timestamp(ses);
|
||||
get_random_bytes(&cc, sizeof(cc));
|
||||
|
||||
cifs_server_lock(ses->server);
|
||||
|
||||
baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
|
||||
tilen = ses->auth_key.len;
|
||||
tiblob = ses->auth_key.response;
|
||||
|
||||
ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
|
||||
if (!ses->auth_key.response) {
|
||||
rc = -ENOMEM;
|
||||
rc = set_auth_key_response(ses);
|
||||
if (rc) {
|
||||
ses->auth_key.len = 0;
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
goto unlock;
|
||||
}
|
||||
ses->auth_key.len += baselen;
|
||||
|
||||
ntlmv2 = (struct ntlmv2_resp *)
|
||||
(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
|
||||
ntlmv2->blob_signature = cpu_to_le32(0x00000101);
|
||||
ntlmv2->reserved = 0;
|
||||
ntlmv2->time = rsp_timestamp;
|
||||
|
||||
get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
|
||||
ntlmv2->client_chal = cc;
|
||||
ntlmv2->reserved2 = 0;
|
||||
|
||||
memcpy(ses->auth_key.response + baselen, tiblob, tilen);
|
||||
|
||||
cifs_server_lock(ses->server);
|
||||
|
||||
rc = cifs_alloc_hash("hmac(md5)", &hmacmd5);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user