Skip to content

Commit 33cfdd7

Browse files
pcacjrsmfrench
authored andcommitted
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: [email protected] Cc: David Howells <[email protected]> Reported-by: Pierguido Lambri <[email protected]> Signed-off-by: Paulo Alcantara (Red Hat) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent be77ab6 commit 33cfdd7

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

fs/smb/client/cifsencrypt.c

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -532,17 +532,67 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_
532532
return rc;
533533
}
534534

535+
/*
536+
* Set up NTLMv2 response blob with SPN (cifs/<hostname>) appended to the
537+
* existing list of AV pairs.
538+
*/
539+
static int set_auth_key_response(struct cifs_ses *ses)
540+
{
541+
size_t baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
542+
size_t len, spnlen, tilen = 0, num_avs = 2 /* SPN + EOL */;
543+
struct TCP_Server_Info *server = ses->server;
544+
char *spn __free(kfree) = NULL;
545+
struct ntlmssp2_name *av;
546+
char *rsp = NULL;
547+
int rc;
548+
549+
spnlen = strlen(server->hostname);
550+
len = sizeof("cifs/") + spnlen;
551+
spn = kmalloc(len, GFP_KERNEL);
552+
if (!spn) {
553+
rc = -ENOMEM;
554+
goto out;
555+
}
556+
557+
spnlen = scnprintf(spn, len, "cifs/%.*s",
558+
(int)spnlen, server->hostname);
559+
560+
av_for_each_entry(ses, av)
561+
tilen += sizeof(*av) + AV_LEN(av);
562+
563+
len = baselen + tilen + spnlen * sizeof(__le16) + num_avs * sizeof(*av);
564+
rsp = kmalloc(len, GFP_KERNEL);
565+
if (!rsp) {
566+
rc = -ENOMEM;
567+
goto out;
568+
}
569+
570+
memcpy(rsp + baselen, ses->auth_key.response, tilen);
571+
av = (void *)(rsp + baselen + tilen);
572+
av->type = cpu_to_le16(NTLMSSP_AV_TARGET_NAME);
573+
av->length = cpu_to_le16(spnlen * sizeof(__le16));
574+
cifs_strtoUTF16((__le16 *)av->data, spn, spnlen, ses->local_nls);
575+
av = (void *)((__u8 *)av + sizeof(*av) + AV_LEN(av));
576+
av->type = cpu_to_le16(NTLMSSP_AV_EOL);
577+
av->length = 0;
578+
579+
rc = 0;
580+
ses->auth_key.len = len;
581+
out:
582+
ses->auth_key.response = rsp;
583+
return rc;
584+
}
585+
535586
int
536587
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
537588
{
538589
struct shash_desc *hmacmd5 = NULL;
539-
int rc;
540-
int baselen;
541-
unsigned int tilen;
590+
unsigned char *tiblob = NULL; /* target info blob */
542591
struct ntlmv2_resp *ntlmv2;
543592
char ntlmv2_hash[16];
544-
unsigned char *tiblob = NULL; /* target info blob */
545593
__le64 rsp_timestamp;
594+
__u64 cc;
595+
int rc;
546596

547597
if (nls_cp == NULL) {
548598
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)
588638
* (as Windows 7 does)
589639
*/
590640
rsp_timestamp = find_timestamp(ses);
641+
get_random_bytes(&cc, sizeof(cc));
591642

592-
baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
593-
tilen = ses->auth_key.len;
594-
tiblob = ses->auth_key.response;
643+
cifs_server_lock(ses->server);
595644

596-
ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
597-
if (!ses->auth_key.response) {
598-
rc = -ENOMEM;
645+
tiblob = ses->auth_key.response;
646+
rc = set_auth_key_response(ses);
647+
if (rc) {
599648
ses->auth_key.len = 0;
600-
goto setup_ntlmv2_rsp_ret;
649+
goto unlock;
601650
}
602-
ses->auth_key.len += baselen;
603651

604652
ntlmv2 = (struct ntlmv2_resp *)
605653
(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
606654
ntlmv2->blob_signature = cpu_to_le32(0x00000101);
607655
ntlmv2->reserved = 0;
608656
ntlmv2->time = rsp_timestamp;
609-
610-
get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
657+
ntlmv2->client_chal = cc;
611658
ntlmv2->reserved2 = 0;
612659

613-
memcpy(ses->auth_key.response + baselen, tiblob, tilen);
614-
615-
cifs_server_lock(ses->server);
616-
617660
rc = cifs_alloc_hash("hmac(md5)", &hmacmd5);
618661
if (rc) {
619662
cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc);

0 commit comments

Comments
 (0)