diff options
-rw-r--r-- | fs/cifs/Kconfig | 1 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 52 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.h | 8 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 40 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 11 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 48 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 17 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 425 | ||||
-rw-r--r-- | fs/cifs/connect.c | 159 | ||||
-rw-r--r-- | fs/cifs/misc.c | 3 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 29 | ||||
-rw-r--r-- | fs/cifs/sess.c | 95 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 23 | ||||
-rw-r--r-- | fs/cifs/smb2glob.h | 2 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 4 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 48 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 282 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 100 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 4 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 151 | ||||
-rw-r--r-- | fs/cifs/smbfsctl.h | 27 | ||||
-rw-r--r-- | fs/cifs/transport.c | 4 |
24 files changed, 1034 insertions, 505 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 2906ee276408..603f18a65c12 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -10,6 +10,7 @@ config CIFS | |||
10 | select CRYPTO_ECB | 10 | select CRYPTO_ECB |
11 | select CRYPTO_DES | 11 | select CRYPTO_DES |
12 | select CRYPTO_SHA256 | 12 | select CRYPTO_SHA256 |
13 | select CRYPTO_CMAC | ||
13 | help | 14 | help |
14 | This is the client VFS module for the Common Internet File System | 15 | This is the client VFS module for the Common Internet File System |
15 | (CIFS) protocol which is the successor to the Server Message Block | 16 | (CIFS) protocol which is the successor to the Server Message Block |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index d59748346020..f3ac4154cbb6 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -213,7 +213,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
213 | tcon->nativeFileSystem); | 213 | tcon->nativeFileSystem); |
214 | } | 214 | } |
215 | seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" | 215 | seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" |
216 | "\nPathComponentMax: %d Status: 0x%d", | 216 | "\n\tPathComponentMax: %d Status: 0x%d", |
217 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), | 217 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), |
218 | le32_to_cpu(tcon->fsAttrInfo.Attributes), | 218 | le32_to_cpu(tcon->fsAttrInfo.Attributes), |
219 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), | 219 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), |
@@ -224,6 +224,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
224 | seq_puts(m, " type: CDROM "); | 224 | seq_puts(m, " type: CDROM "); |
225 | else | 225 | else |
226 | seq_printf(m, " type: %d ", dev_type); | 226 | seq_printf(m, " type: %d ", dev_type); |
227 | if (server->ops->dump_share_caps) | ||
228 | server->ops->dump_share_caps(m, tcon); | ||
227 | 229 | ||
228 | if (tcon->need_reconnect) | 230 | if (tcon->need_reconnect) |
229 | seq_puts(m, "\tDISCONNECTED "); | 231 | seq_puts(m, "\tDISCONNECTED "); |
@@ -595,9 +597,36 @@ static int cifs_security_flags_proc_open(struct inode *inode, struct file *file) | |||
595 | return single_open(file, cifs_security_flags_proc_show, NULL); | 597 | return single_open(file, cifs_security_flags_proc_show, NULL); |
596 | } | 598 | } |
597 | 599 | ||
600 | /* | ||
601 | * Ensure that if someone sets a MUST flag, that we disable all other MAY | ||
602 | * flags except for the ones corresponding to the given MUST flag. If there are | ||
603 | * multiple MUST flags, then try to prefer more secure ones. | ||
604 | */ | ||
605 | static void | ||
606 | cifs_security_flags_handle_must_flags(unsigned int *flags) | ||
607 | { | ||
608 | unsigned int signflags = *flags & CIFSSEC_MUST_SIGN; | ||
609 | |||
610 | if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) | ||
611 | *flags = CIFSSEC_MUST_KRB5; | ||
612 | else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) | ||
613 | *flags = CIFSSEC_MUST_NTLMSSP; | ||
614 | else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) | ||
615 | *flags = CIFSSEC_MUST_NTLMV2; | ||
616 | else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM) | ||
617 | *flags = CIFSSEC_MUST_NTLM; | ||
618 | else if ((*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN) | ||
619 | *flags = CIFSSEC_MUST_LANMAN; | ||
620 | else if ((*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT) | ||
621 | *flags = CIFSSEC_MUST_PLNTXT; | ||
622 | |||
623 | *flags |= signflags; | ||
624 | } | ||
625 | |||
598 | static ssize_t cifs_security_flags_proc_write(struct file *file, | 626 | static ssize_t cifs_security_flags_proc_write(struct file *file, |
599 | const char __user *buffer, size_t count, loff_t *ppos) | 627 | const char __user *buffer, size_t count, loff_t *ppos) |
600 | { | 628 | { |
629 | int rc; | ||
601 | unsigned int flags; | 630 | unsigned int flags; |
602 | char flags_string[12]; | 631 | char flags_string[12]; |
603 | char c; | 632 | char c; |
@@ -620,26 +649,35 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, | |||
620 | global_secflags = CIFSSEC_MAX; | 649 | global_secflags = CIFSSEC_MAX; |
621 | return count; | 650 | return count; |
622 | } else if (!isdigit(c)) { | 651 | } else if (!isdigit(c)) { |
623 | cifs_dbg(VFS, "invalid flag %c\n", c); | 652 | cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", |
653 | flags_string); | ||
624 | return -EINVAL; | 654 | return -EINVAL; |
625 | } | 655 | } |
626 | } | 656 | } |
627 | /* else we have a number */ | ||
628 | 657 | ||
629 | flags = simple_strtoul(flags_string, NULL, 0); | 658 | /* else we have a number */ |
659 | rc = kstrtouint(flags_string, 0, &flags); | ||
660 | if (rc) { | ||
661 | cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", | ||
662 | flags_string); | ||
663 | return rc; | ||
664 | } | ||
630 | 665 | ||
631 | cifs_dbg(FYI, "sec flags 0x%x\n", flags); | 666 | cifs_dbg(FYI, "sec flags 0x%x\n", flags); |
632 | 667 | ||
633 | if (flags <= 0) { | 668 | if (flags == 0) { |
634 | cifs_dbg(VFS, "invalid security flags %s\n", flags_string); | 669 | cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string); |
635 | return -EINVAL; | 670 | return -EINVAL; |
636 | } | 671 | } |
637 | 672 | ||
638 | if (flags & ~CIFSSEC_MASK) { | 673 | if (flags & ~CIFSSEC_MASK) { |
639 | cifs_dbg(VFS, "attempt to set unsupported security flags 0x%x\n", | 674 | cifs_dbg(VFS, "Unsupported security flags: 0x%x\n", |
640 | flags & ~CIFSSEC_MASK); | 675 | flags & ~CIFSSEC_MASK); |
641 | return -EINVAL; | 676 | return -EINVAL; |
642 | } | 677 | } |
678 | |||
679 | cifs_security_flags_handle_must_flags(&flags); | ||
680 | |||
643 | /* flags look ok - update the global security flags for cifs module */ | 681 | /* flags look ok - update the global security flags for cifs module */ |
644 | global_secflags = flags; | 682 | global_secflags = flags; |
645 | if (global_secflags & CIFSSEC_MUST_SIGN) { | 683 | if (global_secflags & CIFSSEC_MUST_SIGN) { |
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index 4fb097468e21..fe8d6276410a 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h | |||
@@ -327,14 +327,14 @@ UniToupper(register wchar_t uc) | |||
327 | /* | 327 | /* |
328 | * UniStrupr: Upper case a unicode string | 328 | * UniStrupr: Upper case a unicode string |
329 | */ | 329 | */ |
330 | static inline wchar_t * | 330 | static inline __le16 * |
331 | UniStrupr(register wchar_t *upin) | 331 | UniStrupr(register __le16 *upin) |
332 | { | 332 | { |
333 | register wchar_t *up; | 333 | register __le16 *up; |
334 | 334 | ||
335 | up = upin; | 335 | up = upin; |
336 | while (*up) { /* For all characters */ | 336 | while (*up) { /* For all characters */ |
337 | *up = UniToupper(*up); | 337 | *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); |
338 | up++; | 338 | up++; |
339 | } | 339 | } |
340 | return upin; /* Return input pointer */ | 340 | return upin; /* Return input pointer */ |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 71436d1fca13..3d8bf941d126 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -276,7 +276,6 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | |||
276 | strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); | 276 | strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); |
277 | 277 | ||
278 | if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { | 278 | if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { |
279 | memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); | ||
280 | memcpy(lnm_session_key, password_with_pad, | 279 | memcpy(lnm_session_key, password_with_pad, |
281 | CIFS_ENCPWD_SIZE); | 280 | CIFS_ENCPWD_SIZE); |
282 | return 0; | 281 | return 0; |
@@ -414,7 +413,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, | |||
414 | int rc = 0; | 413 | int rc = 0; |
415 | int len; | 414 | int len; |
416 | char nt_hash[CIFS_NTHASH_SIZE]; | 415 | char nt_hash[CIFS_NTHASH_SIZE]; |
417 | wchar_t *user; | 416 | __le16 *user; |
418 | wchar_t *domain; | 417 | wchar_t *domain; |
419 | wchar_t *server; | 418 | wchar_t *server; |
420 | 419 | ||
@@ -439,7 +438,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, | |||
439 | return rc; | 438 | return rc; |
440 | } | 439 | } |
441 | 440 | ||
442 | /* convert ses->user_name to unicode and uppercase */ | 441 | /* convert ses->user_name to unicode */ |
443 | len = ses->user_name ? strlen(ses->user_name) : 0; | 442 | len = ses->user_name ? strlen(ses->user_name) : 0; |
444 | user = kmalloc(2 + (len * 2), GFP_KERNEL); | 443 | user = kmalloc(2 + (len * 2), GFP_KERNEL); |
445 | if (user == NULL) { | 444 | if (user == NULL) { |
@@ -448,7 +447,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, | |||
448 | } | 447 | } |
449 | 448 | ||
450 | if (len) { | 449 | if (len) { |
451 | len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp); | 450 | len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp); |
452 | UniStrupr(user); | 451 | UniStrupr(user); |
453 | } else { | 452 | } else { |
454 | memset(user, '\0', 2); | 453 | memset(user, '\0', 2); |
@@ -536,7 +535,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) | |||
536 | return rc; | 535 | return rc; |
537 | } | 536 | } |
538 | 537 | ||
539 | if (ses->server->secType == RawNTLMSSP) | 538 | if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) |
540 | memcpy(ses->auth_key.response + offset, | 539 | memcpy(ses->auth_key.response + offset, |
541 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); | 540 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
542 | else | 541 | else |
@@ -568,7 +567,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
568 | char ntlmv2_hash[16]; | 567 | char ntlmv2_hash[16]; |
569 | unsigned char *tiblob = NULL; /* target info blob */ | 568 | unsigned char *tiblob = NULL; /* target info blob */ |
570 | 569 | ||
571 | if (ses->server->secType == RawNTLMSSP) { | 570 | if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { |
572 | if (!ses->domainName) { | 571 | if (!ses->domainName) { |
573 | rc = find_domain_name(ses, nls_cp); | 572 | rc = find_domain_name(ses, nls_cp); |
574 | if (rc) { | 573 | if (rc) { |
@@ -706,6 +705,9 @@ calc_seckey(struct cifs_ses *ses) | |||
706 | void | 705 | void |
707 | cifs_crypto_shash_release(struct TCP_Server_Info *server) | 706 | cifs_crypto_shash_release(struct TCP_Server_Info *server) |
708 | { | 707 | { |
708 | if (server->secmech.cmacaes) | ||
709 | crypto_free_shash(server->secmech.cmacaes); | ||
710 | |||
709 | if (server->secmech.hmacsha256) | 711 | if (server->secmech.hmacsha256) |
710 | crypto_free_shash(server->secmech.hmacsha256); | 712 | crypto_free_shash(server->secmech.hmacsha256); |
711 | 713 | ||
@@ -715,6 +717,8 @@ cifs_crypto_shash_release(struct TCP_Server_Info *server) | |||
715 | if (server->secmech.hmacmd5) | 717 | if (server->secmech.hmacmd5) |
716 | crypto_free_shash(server->secmech.hmacmd5); | 718 | crypto_free_shash(server->secmech.hmacmd5); |
717 | 719 | ||
720 | kfree(server->secmech.sdesccmacaes); | ||
721 | |||
718 | kfree(server->secmech.sdeschmacsha256); | 722 | kfree(server->secmech.sdeschmacsha256); |
719 | 723 | ||
720 | kfree(server->secmech.sdeschmacmd5); | 724 | kfree(server->secmech.sdeschmacmd5); |
@@ -748,6 +752,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
748 | goto crypto_allocate_hmacsha256_fail; | 752 | goto crypto_allocate_hmacsha256_fail; |
749 | } | 753 | } |
750 | 754 | ||
755 | server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0); | ||
756 | if (IS_ERR(server->secmech.cmacaes)) { | ||
757 | cifs_dbg(VFS, "could not allocate crypto cmac-aes"); | ||
758 | rc = PTR_ERR(server->secmech.cmacaes); | ||
759 | goto crypto_allocate_cmacaes_fail; | ||
760 | } | ||
761 | |||
751 | size = sizeof(struct shash_desc) + | 762 | size = sizeof(struct shash_desc) + |
752 | crypto_shash_descsize(server->secmech.hmacmd5); | 763 | crypto_shash_descsize(server->secmech.hmacmd5); |
753 | server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); | 764 | server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); |
@@ -778,8 +789,22 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
778 | server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; | 789 | server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; |
779 | server->secmech.sdeschmacsha256->shash.flags = 0x0; | 790 | server->secmech.sdeschmacsha256->shash.flags = 0x0; |
780 | 791 | ||
792 | size = sizeof(struct shash_desc) + | ||
793 | crypto_shash_descsize(server->secmech.cmacaes); | ||
794 | server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL); | ||
795 | if (!server->secmech.sdesccmacaes) { | ||
796 | cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__); | ||
797 | rc = -ENOMEM; | ||
798 | goto crypto_allocate_cmacaes_sdesc_fail; | ||
799 | } | ||
800 | server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes; | ||
801 | server->secmech.sdesccmacaes->shash.flags = 0x0; | ||
802 | |||
781 | return 0; | 803 | return 0; |
782 | 804 | ||
805 | crypto_allocate_cmacaes_sdesc_fail: | ||
806 | kfree(server->secmech.sdeschmacsha256); | ||
807 | |||
783 | crypto_allocate_hmacsha256_sdesc_fail: | 808 | crypto_allocate_hmacsha256_sdesc_fail: |
784 | kfree(server->secmech.sdescmd5); | 809 | kfree(server->secmech.sdescmd5); |
785 | 810 | ||
@@ -787,6 +812,9 @@ crypto_allocate_md5_sdesc_fail: | |||
787 | kfree(server->secmech.sdeschmacmd5); | 812 | kfree(server->secmech.sdeschmacmd5); |
788 | 813 | ||
789 | crypto_allocate_hmacmd5_sdesc_fail: | 814 | crypto_allocate_hmacmd5_sdesc_fail: |
815 | crypto_free_shash(server->secmech.cmacaes); | ||
816 | |||
817 | crypto_allocate_cmacaes_fail: | ||
790 | crypto_free_shash(server->secmech.hmacsha256); | 818 | crypto_free_shash(server->secmech.hmacsha256); |
791 | 819 | ||
792 | crypto_allocate_hmacsha256_fail: | 820 | crypto_allocate_hmacsha256_fail: |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index a445e71746fa..4bdd547dbf6f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -312,11 +312,14 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | |||
312 | } | 312 | } |
313 | 313 | ||
314 | static void | 314 | static void |
315 | cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) | 315 | cifs_show_security(struct seq_file *s, struct cifs_ses *ses) |
316 | { | 316 | { |
317 | if (ses->sectype == Unspecified) | ||
318 | return; | ||
319 | |||
317 | seq_printf(s, ",sec="); | 320 | seq_printf(s, ",sec="); |
318 | 321 | ||
319 | switch (server->secType) { | 322 | switch (ses->sectype) { |
320 | case LANMAN: | 323 | case LANMAN: |
321 | seq_printf(s, "lanman"); | 324 | seq_printf(s, "lanman"); |
322 | break; | 325 | break; |
@@ -338,7 +341,7 @@ cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) | |||
338 | break; | 341 | break; |
339 | } | 342 | } |
340 | 343 | ||
341 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 344 | if (ses->sign) |
342 | seq_printf(s, "i"); | 345 | seq_printf(s, "i"); |
343 | } | 346 | } |
344 | 347 | ||
@@ -369,7 +372,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
369 | srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; | 372 | srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; |
370 | 373 | ||
371 | seq_printf(s, ",vers=%s", tcon->ses->server->vals->version_string); | 374 | seq_printf(s, ",vers=%s", tcon->ses->server->vals->version_string); |
372 | cifs_show_security(s, tcon->ses->server); | 375 | cifs_show_security(s, tcon->ses); |
373 | cifs_show_cache_flavor(s, cifs_sb); | 376 | cifs_show_cache_flavor(s, cifs_sb); |
374 | 377 | ||
375 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) | 378 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index d05b3028e3b9..ea723a5e8226 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -132,5 +132,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
132 | extern const struct export_operations cifs_export_ops; | 132 | extern const struct export_operations cifs_export_ops; |
133 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ | 133 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
134 | 134 | ||
135 | #define CIFS_VERSION "2.0" | 135 | #define CIFS_VERSION "2.01" |
136 | #endif /* _CIFSFS_H */ | 136 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 4f07f6fbe494..e66b08882548 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -101,20 +101,14 @@ enum statusEnum { | |||
101 | }; | 101 | }; |
102 | 102 | ||
103 | enum securityEnum { | 103 | enum securityEnum { |
104 | LANMAN = 0, /* Legacy LANMAN auth */ | 104 | Unspecified = 0, /* not specified */ |
105 | LANMAN, /* Legacy LANMAN auth */ | ||
105 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ | 106 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ |
106 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ | 107 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ |
107 | RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ | 108 | RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ |
108 | /* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */ | ||
109 | Kerberos, /* Kerberos via SPNEGO */ | 109 | Kerberos, /* Kerberos via SPNEGO */ |
110 | }; | 110 | }; |
111 | 111 | ||
112 | enum protocolEnum { | ||
113 | TCP = 0, | ||
114 | SCTP | ||
115 | /* Netbios frames protocol not supported at this time */ | ||
116 | }; | ||
117 | |||
118 | struct session_key { | 112 | struct session_key { |
119 | unsigned int len; | 113 | unsigned int len; |
120 | char *response; | 114 | char *response; |
@@ -131,9 +125,11 @@ struct cifs_secmech { | |||
131 | struct crypto_shash *hmacmd5; /* hmac-md5 hash function */ | 125 | struct crypto_shash *hmacmd5; /* hmac-md5 hash function */ |
132 | struct crypto_shash *md5; /* md5 hash function */ | 126 | struct crypto_shash *md5; /* md5 hash function */ |
133 | struct crypto_shash *hmacsha256; /* hmac-sha256 hash function */ | 127 | struct crypto_shash *hmacsha256; /* hmac-sha256 hash function */ |
128 | struct crypto_shash *cmacaes; /* block-cipher based MAC function */ | ||
134 | struct sdesc *sdeschmacmd5; /* ctxt to generate ntlmv2 hash, CR1 */ | 129 | struct sdesc *sdeschmacmd5; /* ctxt to generate ntlmv2 hash, CR1 */ |
135 | struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ | 130 | struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ |
136 | struct sdesc *sdeschmacsha256; /* ctxt to generate smb2 signature */ | 131 | struct sdesc *sdeschmacsha256; /* ctxt to generate smb2 signature */ |
132 | struct sdesc *sdesccmacaes; /* ctxt to generate smb3 signature */ | ||
137 | }; | 133 | }; |
138 | 134 | ||
139 | /* per smb session structure/fields */ | 135 | /* per smb session structure/fields */ |
@@ -181,6 +177,7 @@ enum smb_version { | |||
181 | Smb_20, | 177 | Smb_20, |
182 | Smb_21, | 178 | Smb_21, |
183 | Smb_30, | 179 | Smb_30, |
180 | Smb_302, | ||
184 | }; | 181 | }; |
185 | 182 | ||
186 | struct mid_q_entry; | 183 | struct mid_q_entry; |
@@ -228,6 +225,7 @@ struct smb_version_operations { | |||
228 | void (*dump_detail)(void *); | 225 | void (*dump_detail)(void *); |
229 | void (*clear_stats)(struct cifs_tcon *); | 226 | void (*clear_stats)(struct cifs_tcon *); |
230 | void (*print_stats)(struct seq_file *m, struct cifs_tcon *); | 227 | void (*print_stats)(struct seq_file *m, struct cifs_tcon *); |
228 | void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); | ||
231 | /* verify the message */ | 229 | /* verify the message */ |
232 | int (*check_message)(char *, unsigned int); | 230 | int (*check_message)(char *, unsigned int); |
233 | bool (*is_oplock_break)(char *, struct TCP_Server_Info *); | 231 | bool (*is_oplock_break)(char *, struct TCP_Server_Info *); |
@@ -367,6 +365,8 @@ struct smb_version_operations { | |||
367 | void (*set_lease_key)(struct inode *, struct cifs_fid *fid); | 365 | void (*set_lease_key)(struct inode *, struct cifs_fid *fid); |
368 | /* generate new lease key */ | 366 | /* generate new lease key */ |
369 | void (*new_lease_key)(struct cifs_fid *fid); | 367 | void (*new_lease_key)(struct cifs_fid *fid); |
368 | /* The next two functions will need to be changed to per smb session */ | ||
369 | void (*generate_signingkey)(struct TCP_Server_Info *server); | ||
370 | int (*calc_signature)(struct smb_rqst *rqst, | 370 | int (*calc_signature)(struct smb_rqst *rqst, |
371 | struct TCP_Server_Info *server); | 371 | struct TCP_Server_Info *server); |
372 | }; | 372 | }; |
@@ -387,6 +387,8 @@ struct smb_version_values { | |||
387 | unsigned int cap_nt_find; | 387 | unsigned int cap_nt_find; |
388 | unsigned int cap_large_files; | 388 | unsigned int cap_large_files; |
389 | unsigned int oplock_read; | 389 | unsigned int oplock_read; |
390 | __u16 signing_enabled; | ||
391 | __u16 signing_required; | ||
390 | }; | 392 | }; |
391 | 393 | ||
392 | #define HEADER_SIZE(server) (server->vals->header_size) | 394 | #define HEADER_SIZE(server) (server->vals->header_size) |
@@ -407,7 +409,8 @@ struct smb_vol { | |||
407 | kgid_t backupgid; | 409 | kgid_t backupgid; |
408 | umode_t file_mode; | 410 | umode_t file_mode; |
409 | umode_t dir_mode; | 411 | umode_t dir_mode; |
410 | unsigned secFlg; | 412 | enum securityEnum sectype; /* sectype requested via mnt opts */ |
413 | bool sign; /* was signing requested via mnt opts? */ | ||
411 | bool retry:1; | 414 | bool retry:1; |
412 | bool intr:1; | 415 | bool intr:1; |
413 | bool setuids:1; | 416 | bool setuids:1; |
@@ -441,6 +444,7 @@ struct smb_vol { | |||
441 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ | 444 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ |
442 | bool multiuser:1; | 445 | bool multiuser:1; |
443 | bool rwpidforward:1; /* pid forward for read/write operations */ | 446 | bool rwpidforward:1; /* pid forward for read/write operations */ |
447 | bool nosharesock; | ||
444 | unsigned int rsize; | 448 | unsigned int rsize; |
445 | unsigned int wsize; | 449 | unsigned int wsize; |
446 | bool sockopt_tcp_nodelay:1; | 450 | bool sockopt_tcp_nodelay:1; |
@@ -514,6 +518,7 @@ struct TCP_Server_Info { | |||
514 | struct task_struct *tsk; | 518 | struct task_struct *tsk; |
515 | char server_GUID[16]; | 519 | char server_GUID[16]; |
516 | __u16 sec_mode; | 520 | __u16 sec_mode; |
521 | bool sign; /* is signing enabled on this connection? */ | ||
517 | bool session_estab; /* mark when very first sess is established */ | 522 | bool session_estab; /* mark when very first sess is established */ |
518 | #ifdef CONFIG_CIFS_SMB2 | 523 | #ifdef CONFIG_CIFS_SMB2 |
519 | int echo_credits; /* echo reserved slots */ | 524 | int echo_credits; /* echo reserved slots */ |
@@ -521,7 +526,6 @@ struct TCP_Server_Info { | |||
521 | bool echoes:1; /* enable echoes */ | 526 | bool echoes:1; /* enable echoes */ |
522 | #endif | 527 | #endif |
523 | u16 dialect; /* dialect index that server chose */ | 528 | u16 dialect; /* dialect index that server chose */ |
524 | enum securityEnum secType; | ||
525 | bool oplocks:1; /* enable oplocks */ | 529 | bool oplocks:1; /* enable oplocks */ |
526 | unsigned int maxReq; /* Clients should submit no more */ | 530 | unsigned int maxReq; /* Clients should submit no more */ |
527 | /* than maxReq distinct unanswered SMBs to the server when using */ | 531 | /* than maxReq distinct unanswered SMBs to the server when using */ |
@@ -540,12 +544,17 @@ struct TCP_Server_Info { | |||
540 | int timeAdj; /* Adjust for difference in server time zone in sec */ | 544 | int timeAdj; /* Adjust for difference in server time zone in sec */ |
541 | __u64 CurrentMid; /* multiplex id - rotating counter */ | 545 | __u64 CurrentMid; /* multiplex id - rotating counter */ |
542 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ | 546 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ |
547 | char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */ | ||
543 | /* 16th byte of RFC1001 workstation name is always null */ | 548 | /* 16th byte of RFC1001 workstation name is always null */ |
544 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 549 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
545 | __u32 sequence_number; /* for signing, protected by srv_mutex */ | 550 | __u32 sequence_number; /* for signing, protected by srv_mutex */ |
546 | struct session_key session_key; | 551 | struct session_key session_key; |
547 | unsigned long lstrp; /* when we got last response from this server */ | 552 | unsigned long lstrp; /* when we got last response from this server */ |
548 | struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ | 553 | struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ |
554 | #define CIFS_NEGFLAVOR_LANMAN 0 /* wct == 13, LANMAN */ | ||
555 | #define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */ | ||
556 | #define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */ | ||
557 | char negflavor; /* NEGOTIATE response flavor */ | ||
549 | /* extended security flavors that server supports */ | 558 | /* extended security flavors that server supports */ |
550 | bool sec_ntlmssp; /* supports NTLMSSP */ | 559 | bool sec_ntlmssp; /* supports NTLMSSP */ |
551 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | 560 | bool sec_kerberosu2u; /* supports U2U Kerberos */ |
@@ -697,7 +706,6 @@ struct cifs_ses { | |||
697 | enum statusEnum status; | 706 | enum statusEnum status; |
698 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ | 707 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ |
699 | __u16 ipc_tid; /* special tid for connection to IPC share */ | 708 | __u16 ipc_tid; /* special tid for connection to IPC share */ |
700 | __u16 flags; | ||
701 | __u16 vcnum; | 709 | __u16 vcnum; |
702 | char *serverOS; /* name of operating system underlying server */ | 710 | char *serverOS; /* name of operating system underlying server */ |
703 | char *serverNOS; /* name of network operating system of server */ | 711 | char *serverNOS; /* name of network operating system of server */ |
@@ -714,21 +722,14 @@ struct cifs_ses { | |||
714 | char *password; | 722 | char *password; |
715 | struct session_key auth_key; | 723 | struct session_key auth_key; |
716 | struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ | 724 | struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ |
725 | enum securityEnum sectype; /* what security flavor was specified? */ | ||
726 | bool sign; /* is signing required? */ | ||
717 | bool need_reconnect:1; /* connection reset, uid now invalid */ | 727 | bool need_reconnect:1; /* connection reset, uid now invalid */ |
718 | #ifdef CONFIG_CIFS_SMB2 | 728 | #ifdef CONFIG_CIFS_SMB2 |
719 | __u16 session_flags; | 729 | __u16 session_flags; |
720 | #endif /* CONFIG_CIFS_SMB2 */ | 730 | #endif /* CONFIG_CIFS_SMB2 */ |
721 | }; | 731 | }; |
722 | 732 | ||
723 | /* no more than one of the following three session flags may be set */ | ||
724 | #define CIFS_SES_NT4 1 | ||
725 | #define CIFS_SES_OS2 2 | ||
726 | #define CIFS_SES_W9X 4 | ||
727 | /* following flag is set for old servers such as OS2 (and Win95?) | ||
728 | which do not negotiate NTLM or POSIX dialects, but instead | ||
729 | negotiate one of the older LANMAN dialects */ | ||
730 | #define CIFS_SES_LANMAN 8 | ||
731 | |||
732 | static inline bool | 733 | static inline bool |
733 | cap_unix(struct cifs_ses *ses) | 734 | cap_unix(struct cifs_ses *ses) |
734 | { | 735 | { |
@@ -816,7 +817,7 @@ struct cifs_tcon { | |||
816 | #ifdef CONFIG_CIFS_SMB2 | 817 | #ifdef CONFIG_CIFS_SMB2 |
817 | bool print:1; /* set if connection to printer share */ | 818 | bool print:1; /* set if connection to printer share */ |
818 | bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */ | 819 | bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */ |
819 | __u32 capabilities; | 820 | __le32 capabilities; |
820 | __u32 share_flags; | 821 | __u32 share_flags; |
821 | __u32 maximal_access; | 822 | __u32 maximal_access; |
822 | __u32 vol_serial_number; | 823 | __u32 vol_serial_number; |
@@ -1348,7 +1349,7 @@ require use of the stronger protocol */ | |||
1348 | #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ | 1349 | #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ |
1349 | #define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ | 1350 | #define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ |
1350 | 1351 | ||
1351 | #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMSSP) | 1352 | #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP) |
1352 | #define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2) | 1353 | #define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2) |
1353 | #define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP) | 1354 | #define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP) |
1354 | /* | 1355 | /* |
@@ -1494,4 +1495,7 @@ extern struct smb_version_values smb21_values; | |||
1494 | #define SMB30_VERSION_STRING "3.0" | 1495 | #define SMB30_VERSION_STRING "3.0" |
1495 | extern struct smb_version_operations smb30_operations; | 1496 | extern struct smb_version_operations smb30_operations; |
1496 | extern struct smb_version_values smb30_values; | 1497 | extern struct smb_version_values smb30_values; |
1498 | #define SMB302_VERSION_STRING "3.02" | ||
1499 | /*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */ | ||
1500 | extern struct smb_version_values smb302_values; | ||
1497 | #endif /* _CIFS_GLOB_H */ | 1501 | #endif /* _CIFS_GLOB_H */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index e996ff6b26d1..11ca24a8e054 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -142,6 +142,11 @@ | |||
142 | */ | 142 | */ |
143 | #define CIFS_SESS_KEY_SIZE (16) | 143 | #define CIFS_SESS_KEY_SIZE (16) |
144 | 144 | ||
145 | /* | ||
146 | * Size of the smb3 signing key | ||
147 | */ | ||
148 | #define SMB3_SIGN_KEY_SIZE (16) | ||
149 | |||
145 | #define CIFS_CLIENT_CHALLENGE_SIZE (8) | 150 | #define CIFS_CLIENT_CHALLENGE_SIZE (8) |
146 | #define CIFS_SERVER_CHALLENGE_SIZE (8) | 151 | #define CIFS_SERVER_CHALLENGE_SIZE (8) |
147 | #define CIFS_HMAC_MD5_HASH_SIZE (16) | 152 | #define CIFS_HMAC_MD5_HASH_SIZE (16) |
@@ -531,7 +536,7 @@ typedef struct lanman_neg_rsp { | |||
531 | #define READ_RAW_ENABLE 1 | 536 | #define READ_RAW_ENABLE 1 |
532 | #define WRITE_RAW_ENABLE 2 | 537 | #define WRITE_RAW_ENABLE 2 |
533 | #define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE) | 538 | #define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE) |
534 | 539 | #define SMB1_CLIENT_GUID_SIZE (16) | |
535 | typedef struct negotiate_rsp { | 540 | typedef struct negotiate_rsp { |
536 | struct smb_hdr hdr; /* wct = 17 */ | 541 | struct smb_hdr hdr; /* wct = 17 */ |
537 | __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */ | 542 | __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */ |
@@ -553,7 +558,7 @@ typedef struct negotiate_rsp { | |||
553 | /* followed by 16 bytes of server GUID */ | 558 | /* followed by 16 bytes of server GUID */ |
554 | /* then security blob if cap_extended_security negotiated */ | 559 | /* then security blob if cap_extended_security negotiated */ |
555 | struct { | 560 | struct { |
556 | unsigned char GUID[16]; | 561 | unsigned char GUID[SMB1_CLIENT_GUID_SIZE]; |
557 | unsigned char SecurityBlob[1]; | 562 | unsigned char SecurityBlob[1]; |
558 | } __attribute__((packed)) extended_response; | 563 | } __attribute__((packed)) extended_response; |
559 | } __attribute__((packed)) u; | 564 | } __attribute__((packed)) u; |
@@ -1315,6 +1320,14 @@ typedef struct smb_com_ntransact_rsp { | |||
1315 | /* parms and data follow */ | 1320 | /* parms and data follow */ |
1316 | } __attribute__((packed)) NTRANSACT_RSP; | 1321 | } __attribute__((packed)) NTRANSACT_RSP; |
1317 | 1322 | ||
1323 | /* See MS-SMB 2.2.7.2.1.1 */ | ||
1324 | struct srv_copychunk { | ||
1325 | __le64 SourceOffset; | ||
1326 | __le64 DestinationOffset; | ||
1327 | __le32 CopyLength; | ||
1328 | __u32 Reserved; | ||
1329 | } __packed; | ||
1330 | |||
1318 | typedef struct smb_com_transaction_ioctl_req { | 1331 | typedef struct smb_com_transaction_ioctl_req { |
1319 | struct smb_hdr hdr; /* wct = 23 */ | 1332 | struct smb_hdr hdr; /* wct = 23 */ |
1320 | __u8 MaxSetupCount; | 1333 | __u8 MaxSetupCount; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index dda188a94332..c8ff018fae68 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -118,6 +118,8 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , | |||
118 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, | 118 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, |
119 | struct cifs_ses *ses, | 119 | struct cifs_ses *ses, |
120 | void **request_buf); | 120 | void **request_buf); |
121 | extern enum securityEnum select_sectype(struct TCP_Server_Info *server, | ||
122 | enum securityEnum requested); | ||
121 | extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | 123 | extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, |
122 | const struct nls_table *nls_cp); | 124 | const struct nls_table *nls_cp); |
123 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); | 125 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); |
@@ -212,6 +214,7 @@ extern int cifs_negotiate_protocol(const unsigned int xid, | |||
212 | struct cifs_ses *ses); | 214 | struct cifs_ses *ses); |
213 | extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | 215 | extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, |
214 | struct nls_table *nls_info); | 216 | struct nls_table *nls_info); |
217 | extern int cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required); | ||
215 | extern int CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses); | 218 | extern int CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses); |
216 | 219 | ||
217 | extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | 220 | extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses, |
@@ -433,6 +436,7 @@ extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); | |||
433 | extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); | 436 | extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); |
434 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | 437 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); |
435 | extern int calc_seckey(struct cifs_ses *); | 438 | extern int calc_seckey(struct cifs_ses *); |
439 | extern void generate_smb3signingkey(struct TCP_Server_Info *); | ||
436 | 440 | ||
437 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 441 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
438 | extern int calc_lanman_hash(const char *password, const char *cryptkey, | 442 | extern int calc_lanman_hash(const char *password, const char *cryptkey, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a58dc77cc443..a89c4cb4e6cf 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -367,6 +367,185 @@ vt2_err: | |||
367 | return -EINVAL; | 367 | return -EINVAL; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int | ||
371 | decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr) | ||
372 | { | ||
373 | int rc = 0; | ||
374 | u16 count; | ||
375 | char *guid = pSMBr->u.extended_response.GUID; | ||
376 | struct TCP_Server_Info *server = ses->server; | ||
377 | |||
378 | count = get_bcc(&pSMBr->hdr); | ||
379 | if (count < SMB1_CLIENT_GUID_SIZE) | ||
380 | return -EIO; | ||
381 | |||
382 | spin_lock(&cifs_tcp_ses_lock); | ||
383 | if (server->srv_count > 1) { | ||
384 | spin_unlock(&cifs_tcp_ses_lock); | ||
385 | if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) { | ||
386 | cifs_dbg(FYI, "server UID changed\n"); | ||
387 | memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE); | ||
388 | } | ||
389 | } else { | ||
390 | spin_unlock(&cifs_tcp_ses_lock); | ||
391 | memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE); | ||
392 | } | ||
393 | |||
394 | if (count == SMB1_CLIENT_GUID_SIZE) { | ||
395 | server->sec_ntlmssp = true; | ||
396 | } else { | ||
397 | count -= SMB1_CLIENT_GUID_SIZE; | ||
398 | rc = decode_negTokenInit( | ||
399 | pSMBr->u.extended_response.SecurityBlob, count, server); | ||
400 | if (rc != 1) | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | int | ||
408 | cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) | ||
409 | { | ||
410 | bool srv_sign_required = server->sec_mode & server->vals->signing_required; | ||
411 | bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled; | ||
412 | bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN; | ||
413 | |||
414 | /* | ||
415 | * Is signing required by mnt options? If not then check | ||
416 | * global_secflags to see if it is there. | ||
417 | */ | ||
418 | if (!mnt_sign_required) | ||
419 | mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) == | ||
420 | CIFSSEC_MUST_SIGN); | ||
421 | |||
422 | /* | ||
423 | * If signing is required then it's automatically enabled too, | ||
424 | * otherwise, check to see if the secflags allow it. | ||
425 | */ | ||
426 | mnt_sign_enabled = mnt_sign_required ? mnt_sign_required : | ||
427 | (global_secflags & CIFSSEC_MAY_SIGN); | ||
428 | |||
429 | /* If server requires signing, does client allow it? */ | ||
430 | if (srv_sign_required) { | ||
431 | if (!mnt_sign_enabled) { | ||
432 | cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!"); | ||
433 | return -ENOTSUPP; | ||
434 | } | ||
435 | server->sign = true; | ||
436 | } | ||
437 | |||
438 | /* If client requires signing, does server allow it? */ | ||
439 | if (mnt_sign_required) { | ||
440 | if (!srv_sign_enabled) { | ||
441 | cifs_dbg(VFS, "Server does not support signing!"); | ||
442 | return -ENOTSUPP; | ||
443 | } | ||
444 | server->sign = true; | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
451 | static int | ||
452 | decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) | ||
453 | { | ||
454 | __s16 tmp; | ||
455 | struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; | ||
456 | |||
457 | if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT) | ||
458 | return -EOPNOTSUPP; | ||
459 | |||
460 | server->sec_mode = le16_to_cpu(rsp->SecurityMode); | ||
461 | server->maxReq = min_t(unsigned int, | ||
462 | le16_to_cpu(rsp->MaxMpxCount), | ||
463 | cifs_max_pending); | ||
464 | set_credits(server, server->maxReq); | ||
465 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); | ||
466 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | ||
467 | /* even though we do not use raw we might as well set this | ||
468 | accurately, in case we ever find a need for it */ | ||
469 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | ||
470 | server->max_rw = 0xFF00; | ||
471 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; | ||
472 | } else { | ||
473 | server->max_rw = 0;/* do not need to use raw anyway */ | ||
474 | server->capabilities = CAP_MPX_MODE; | ||
475 | } | ||
476 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); | ||
477 | if (tmp == -1) { | ||
478 | /* OS/2 often does not set timezone therefore | ||
479 | * we must use server time to calc time zone. | ||
480 | * Could deviate slightly from the right zone. | ||
481 | * Smallest defined timezone difference is 15 minutes | ||
482 | * (i.e. Nepal). Rounding up/down is done to match | ||
483 | * this requirement. | ||
484 | */ | ||
485 | int val, seconds, remain, result; | ||
486 | struct timespec ts, utc; | ||
487 | utc = CURRENT_TIME; | ||
488 | ts = cnvrtDosUnixTm(rsp->SrvTime.Date, | ||
489 | rsp->SrvTime.Time, 0); | ||
490 | cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n", | ||
491 | (int)ts.tv_sec, (int)utc.tv_sec, | ||
492 | (int)(utc.tv_sec - ts.tv_sec)); | ||
493 | val = (int)(utc.tv_sec - ts.tv_sec); | ||
494 | seconds = abs(val); | ||
495 | result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; | ||
496 | remain = seconds % MIN_TZ_ADJ; | ||
497 | if (remain >= (MIN_TZ_ADJ / 2)) | ||
498 | result += MIN_TZ_ADJ; | ||
499 | if (val < 0) | ||
500 | result = -result; | ||
501 | server->timeAdj = result; | ||
502 | } else { | ||
503 | server->timeAdj = (int)tmp; | ||
504 | server->timeAdj *= 60; /* also in seconds */ | ||
505 | } | ||
506 | cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj); | ||
507 | |||
508 | |||
509 | /* BB get server time for time conversions and add | ||
510 | code to use it and timezone since this is not UTC */ | ||
511 | |||
512 | if (rsp->EncryptionKeyLength == | ||
513 | cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { | ||
514 | memcpy(server->cryptkey, rsp->EncryptionKey, | ||
515 | CIFS_CRYPTO_KEY_SIZE); | ||
516 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | ||
517 | return -EIO; /* need cryptkey unless plain text */ | ||
518 | } | ||
519 | |||
520 | cifs_dbg(FYI, "LANMAN negotiated\n"); | ||
521 | return 0; | ||
522 | } | ||
523 | #else | ||
524 | static inline int | ||
525 | decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) | ||
526 | { | ||
527 | cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n"); | ||
528 | return -EOPNOTSUPP; | ||
529 | } | ||
530 | #endif | ||
531 | |||
532 | static bool | ||
533 | should_set_ext_sec_flag(enum securityEnum sectype) | ||
534 | { | ||
535 | switch (sectype) { | ||
536 | case RawNTLMSSP: | ||
537 | case Kerberos: | ||
538 | return true; | ||
539 | case Unspecified: | ||
540 | if (global_secflags & | ||
541 | (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)) | ||
542 | return true; | ||
543 | /* Fallthrough */ | ||
544 | default: | ||
545 | return false; | ||
546 | } | ||
547 | } | ||
548 | |||
370 | int | 549 | int |
371 | CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | 550 | CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) |
372 | { | 551 | { |
@@ -375,41 +554,24 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | |||
375 | int rc = 0; | 554 | int rc = 0; |
376 | int bytes_returned; | 555 | int bytes_returned; |
377 | int i; | 556 | int i; |
378 | struct TCP_Server_Info *server; | 557 | struct TCP_Server_Info *server = ses->server; |
379 | u16 count; | 558 | u16 count; |
380 | unsigned int secFlags; | ||
381 | 559 | ||
382 | if (ses->server) | 560 | if (!server) { |
383 | server = ses->server; | 561 | WARN(1, "%s: server is NULL!\n", __func__); |
384 | else { | 562 | return -EIO; |
385 | rc = -EIO; | ||
386 | return rc; | ||
387 | } | 563 | } |
564 | |||
388 | rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ , | 565 | rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ , |
389 | (void **) &pSMB, (void **) &pSMBr); | 566 | (void **) &pSMB, (void **) &pSMBr); |
390 | if (rc) | 567 | if (rc) |
391 | return rc; | 568 | return rc; |
392 | 569 | ||
393 | /* if any of auth flags (ie not sign or seal) are overriden use them */ | ||
394 | if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
395 | secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */ | ||
396 | else /* if override flags set only sign/seal OR them with global auth */ | ||
397 | secFlags = global_secflags | ses->overrideSecFlg; | ||
398 | |||
399 | cifs_dbg(FYI, "secFlags 0x%x\n", secFlags); | ||
400 | |||
401 | pSMB->hdr.Mid = get_next_mid(server); | 570 | pSMB->hdr.Mid = get_next_mid(server); |
402 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); | 571 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); |
403 | 572 | ||
404 | if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) | 573 | if (should_set_ext_sec_flag(ses->sectype)) { |
405 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 574 | cifs_dbg(FYI, "Requesting extended security."); |
406 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { | ||
407 | cifs_dbg(FYI, "Kerberos only mechanism, enable extended security\n"); | ||
408 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
409 | } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) | ||
410 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
411 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { | ||
412 | cifs_dbg(FYI, "NTLMSSP only mechanism, enable extended security\n"); | ||
413 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 575 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
414 | } | 576 | } |
415 | 577 | ||
@@ -436,127 +598,21 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | |||
436 | could not negotiate a common dialect */ | 598 | could not negotiate a common dialect */ |
437 | rc = -EOPNOTSUPP; | 599 | rc = -EOPNOTSUPP; |
438 | goto neg_err_exit; | 600 | goto neg_err_exit; |
439 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
440 | } else if ((pSMBr->hdr.WordCount == 13) | ||
441 | && ((server->dialect == LANMAN_PROT) | ||
442 | || (server->dialect == LANMAN2_PROT))) { | ||
443 | __s16 tmp; | ||
444 | struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; | ||
445 | |||
446 | if ((secFlags & CIFSSEC_MAY_LANMAN) || | ||
447 | (secFlags & CIFSSEC_MAY_PLNTXT)) | ||
448 | server->secType = LANMAN; | ||
449 | else { | ||
450 | cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n"); | ||
451 | rc = -EOPNOTSUPP; | ||
452 | goto neg_err_exit; | ||
453 | } | ||
454 | server->sec_mode = le16_to_cpu(rsp->SecurityMode); | ||
455 | server->maxReq = min_t(unsigned int, | ||
456 | le16_to_cpu(rsp->MaxMpxCount), | ||
457 | cifs_max_pending); | ||
458 | set_credits(server, server->maxReq); | ||
459 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); | ||
460 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | ||
461 | /* even though we do not use raw we might as well set this | ||
462 | accurately, in case we ever find a need for it */ | ||
463 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | ||
464 | server->max_rw = 0xFF00; | ||
465 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; | ||
466 | } else { | ||
467 | server->max_rw = 0;/* do not need to use raw anyway */ | ||
468 | server->capabilities = CAP_MPX_MODE; | ||
469 | } | ||
470 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); | ||
471 | if (tmp == -1) { | ||
472 | /* OS/2 often does not set timezone therefore | ||
473 | * we must use server time to calc time zone. | ||
474 | * Could deviate slightly from the right zone. | ||
475 | * Smallest defined timezone difference is 15 minutes | ||
476 | * (i.e. Nepal). Rounding up/down is done to match | ||
477 | * this requirement. | ||
478 | */ | ||
479 | int val, seconds, remain, result; | ||
480 | struct timespec ts, utc; | ||
481 | utc = CURRENT_TIME; | ||
482 | ts = cnvrtDosUnixTm(rsp->SrvTime.Date, | ||
483 | rsp->SrvTime.Time, 0); | ||
484 | cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n", | ||
485 | (int)ts.tv_sec, (int)utc.tv_sec, | ||
486 | (int)(utc.tv_sec - ts.tv_sec)); | ||
487 | val = (int)(utc.tv_sec - ts.tv_sec); | ||
488 | seconds = abs(val); | ||
489 | result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; | ||
490 | remain = seconds % MIN_TZ_ADJ; | ||
491 | if (remain >= (MIN_TZ_ADJ / 2)) | ||
492 | result += MIN_TZ_ADJ; | ||
493 | if (val < 0) | ||
494 | result = -result; | ||
495 | server->timeAdj = result; | ||
496 | } else { | ||
497 | server->timeAdj = (int)tmp; | ||
498 | server->timeAdj *= 60; /* also in seconds */ | ||
499 | } | ||
500 | cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj); | ||
501 | |||
502 | |||
503 | /* BB get server time for time conversions and add | ||
504 | code to use it and timezone since this is not UTC */ | ||
505 | |||
506 | if (rsp->EncryptionKeyLength == | ||
507 | cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { | ||
508 | memcpy(ses->server->cryptkey, rsp->EncryptionKey, | ||
509 | CIFS_CRYPTO_KEY_SIZE); | ||
510 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | ||
511 | rc = -EIO; /* need cryptkey unless plain text */ | ||
512 | goto neg_err_exit; | ||
513 | } | ||
514 | |||
515 | cifs_dbg(FYI, "LANMAN negotiated\n"); | ||
516 | /* we will not end up setting signing flags - as no signing | ||
517 | was in LANMAN and server did not return the flags on */ | ||
518 | goto signing_check; | ||
519 | #else /* weak security disabled */ | ||
520 | } else if (pSMBr->hdr.WordCount == 13) { | 601 | } else if (pSMBr->hdr.WordCount == 13) { |
521 | cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n"); | 602 | server->negflavor = CIFS_NEGFLAVOR_LANMAN; |
522 | rc = -EOPNOTSUPP; | 603 | rc = decode_lanman_negprot_rsp(server, pSMBr); |
523 | #endif /* WEAK_PW_HASH */ | 604 | goto signing_check; |
524 | goto neg_err_exit; | ||
525 | } else if (pSMBr->hdr.WordCount != 17) { | 605 | } else if (pSMBr->hdr.WordCount != 17) { |
526 | /* unknown wct */ | 606 | /* unknown wct */ |
527 | rc = -EOPNOTSUPP; | 607 | rc = -EOPNOTSUPP; |
528 | goto neg_err_exit; | 608 | goto neg_err_exit; |
529 | } | 609 | } |
530 | /* else wct == 17 NTLM */ | 610 | /* else wct == 17, NTLM or better */ |
611 | |||
531 | server->sec_mode = pSMBr->SecurityMode; | 612 | server->sec_mode = pSMBr->SecurityMode; |
532 | if ((server->sec_mode & SECMODE_USER) == 0) | 613 | if ((server->sec_mode & SECMODE_USER) == 0) |
533 | cifs_dbg(FYI, "share mode security\n"); | 614 | cifs_dbg(FYI, "share mode security\n"); |
534 | 615 | ||
535 | if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0) | ||
536 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
537 | if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0) | ||
538 | #endif /* CIFS_WEAK_PW_HASH */ | ||
539 | cifs_dbg(VFS, "Server requests plain text password but client support disabled\n"); | ||
540 | |||
541 | if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) | ||
542 | server->secType = NTLMv2; | ||
543 | else if (secFlags & CIFSSEC_MAY_NTLM) | ||
544 | server->secType = NTLM; | ||
545 | else if (secFlags & CIFSSEC_MAY_NTLMV2) | ||
546 | server->secType = NTLMv2; | ||
547 | else if (secFlags & CIFSSEC_MAY_KRB5) | ||
548 | server->secType = Kerberos; | ||
549 | else if (secFlags & CIFSSEC_MAY_NTLMSSP) | ||
550 | server->secType = RawNTLMSSP; | ||
551 | else if (secFlags & CIFSSEC_MAY_LANMAN) | ||
552 | server->secType = LANMAN; | ||
553 | else { | ||
554 | rc = -EOPNOTSUPP; | ||
555 | cifs_dbg(VFS, "Invalid security type\n"); | ||
556 | goto neg_err_exit; | ||
557 | } | ||
558 | /* else ... any others ...? */ | ||
559 | |||
560 | /* one byte, so no need to convert this or EncryptionKeyLen from | 616 | /* one byte, so no need to convert this or EncryptionKeyLen from |
561 | little endian */ | 617 | little endian */ |
562 | server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), | 618 | server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), |
@@ -569,90 +625,26 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | |||
569 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 625 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
570 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); | 626 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); |
571 | server->timeAdj *= 60; | 627 | server->timeAdj *= 60; |
628 | |||
572 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { | 629 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { |
630 | server->negflavor = CIFS_NEGFLAVOR_UNENCAP; | ||
573 | memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, | 631 | memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, |
574 | CIFS_CRYPTO_KEY_SIZE); | 632 | CIFS_CRYPTO_KEY_SIZE); |
575 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || | 633 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || |
576 | server->capabilities & CAP_EXTENDED_SECURITY) && | 634 | server->capabilities & CAP_EXTENDED_SECURITY) && |
577 | (pSMBr->EncryptionKeyLength == 0)) { | 635 | (pSMBr->EncryptionKeyLength == 0)) { |
578 | /* decode security blob */ | 636 | server->negflavor = CIFS_NEGFLAVOR_EXTENDED; |
579 | count = get_bcc(&pSMBr->hdr); | 637 | rc = decode_ext_sec_blob(ses, pSMBr); |
580 | if (count < 16) { | ||
581 | rc = -EIO; | ||
582 | goto neg_err_exit; | ||
583 | } | ||
584 | spin_lock(&cifs_tcp_ses_lock); | ||
585 | if (server->srv_count > 1) { | ||
586 | spin_unlock(&cifs_tcp_ses_lock); | ||
587 | if (memcmp(server->server_GUID, | ||
588 | pSMBr->u.extended_response. | ||
589 | GUID, 16) != 0) { | ||
590 | cifs_dbg(FYI, "server UID changed\n"); | ||
591 | memcpy(server->server_GUID, | ||
592 | pSMBr->u.extended_response.GUID, | ||
593 | 16); | ||
594 | } | ||
595 | } else { | ||
596 | spin_unlock(&cifs_tcp_ses_lock); | ||
597 | memcpy(server->server_GUID, | ||
598 | pSMBr->u.extended_response.GUID, 16); | ||
599 | } | ||
600 | |||
601 | if (count == 16) { | ||
602 | server->secType = RawNTLMSSP; | ||
603 | } else { | ||
604 | rc = decode_negTokenInit(pSMBr->u.extended_response. | ||
605 | SecurityBlob, count - 16, | ||
606 | server); | ||
607 | if (rc == 1) | ||
608 | rc = 0; | ||
609 | else | ||
610 | rc = -EINVAL; | ||
611 | if (server->secType == Kerberos) { | ||
612 | if (!server->sec_kerberos && | ||
613 | !server->sec_mskerberos) | ||
614 | rc = -EOPNOTSUPP; | ||
615 | } else if (server->secType == RawNTLMSSP) { | ||
616 | if (!server->sec_ntlmssp) | ||
617 | rc = -EOPNOTSUPP; | ||
618 | } else | ||
619 | rc = -EOPNOTSUPP; | ||
620 | } | ||
621 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | 638 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { |
622 | rc = -EIO; /* no crypt key only if plain text pwd */ | 639 | rc = -EIO; /* no crypt key only if plain text pwd */ |
623 | goto neg_err_exit; | ||
624 | } else | ||
625 | server->capabilities &= ~CAP_EXTENDED_SECURITY; | ||
626 | |||
627 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
628 | signing_check: | ||
629 | #endif | ||
630 | if ((secFlags & CIFSSEC_MAY_SIGN) == 0) { | ||
631 | /* MUST_SIGN already includes the MAY_SIGN FLAG | ||
632 | so if this is zero it means that signing is disabled */ | ||
633 | cifs_dbg(FYI, "Signing disabled\n"); | ||
634 | if (server->sec_mode & SECMODE_SIGN_REQUIRED) { | ||
635 | cifs_dbg(VFS, "Server requires packet signing to be enabled in /proc/fs/cifs/SecurityFlags\n"); | ||
636 | rc = -EOPNOTSUPP; | ||
637 | } | ||
638 | server->sec_mode &= | ||
639 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
640 | } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { | ||
641 | /* signing required */ | ||
642 | cifs_dbg(FYI, "Must sign - secFlags 0x%x\n", secFlags); | ||
643 | if ((server->sec_mode & | ||
644 | (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { | ||
645 | cifs_dbg(VFS, "signing required but server lacks support\n"); | ||
646 | rc = -EOPNOTSUPP; | ||
647 | } else | ||
648 | server->sec_mode |= SECMODE_SIGN_REQUIRED; | ||
649 | } else { | 640 | } else { |
650 | /* signing optional ie CIFSSEC_MAY_SIGN */ | 641 | server->negflavor = CIFS_NEGFLAVOR_UNENCAP; |
651 | if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0) | 642 | server->capabilities &= ~CAP_EXTENDED_SECURITY; |
652 | server->sec_mode &= | ||
653 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
654 | } | 643 | } |
655 | 644 | ||
645 | signing_check: | ||
646 | if (!rc) | ||
647 | rc = cifs_enable_signing(server, ses->sign); | ||
656 | neg_err_exit: | 648 | neg_err_exit: |
657 | cifs_buf_release(pSMB); | 649 | cifs_buf_release(pSMB); |
658 | 650 | ||
@@ -777,9 +769,8 @@ CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses) | |||
777 | 769 | ||
778 | pSMB->hdr.Mid = get_next_mid(ses->server); | 770 | pSMB->hdr.Mid = get_next_mid(ses->server); |
779 | 771 | ||
780 | if (ses->server->sec_mode & | 772 | if (ses->server->sign) |
781 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 773 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
782 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
783 | 774 | ||
784 | pSMB->hdr.Uid = ses->Suid; | 775 | pSMB->hdr.Uid = ses->Suid; |
785 | 776 | ||
@@ -1540,8 +1531,7 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
1540 | switch (mid->mid_state) { | 1531 | switch (mid->mid_state) { |
1541 | case MID_RESPONSE_RECEIVED: | 1532 | case MID_RESPONSE_RECEIVED: |
1542 | /* result already set, check signature */ | 1533 | /* result already set, check signature */ |
1543 | if (server->sec_mode & | 1534 | if (server->sign) { |
1544 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
1545 | int rc = 0; | 1535 | int rc = 0; |
1546 | 1536 | ||
1547 | rc = cifs_verify_signature(&rqst, server, | 1537 | rc = cifs_verify_signature(&rqst, server, |
@@ -3940,6 +3930,7 @@ QFileInfoRetry: | |||
3940 | pSMB->Pad = 0; | 3930 | pSMB->Pad = 0; |
3941 | pSMB->Fid = netfid; | 3931 | pSMB->Fid = netfid; |
3942 | inc_rfc1001_len(pSMB, byte_count); | 3932 | inc_rfc1001_len(pSMB, byte_count); |
3933 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | ||
3943 | 3934 | ||
3944 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3935 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3945 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3936 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -4108,6 +4099,7 @@ UnixQFileInfoRetry: | |||
4108 | pSMB->Pad = 0; | 4099 | pSMB->Pad = 0; |
4109 | pSMB->Fid = netfid; | 4100 | pSMB->Fid = netfid; |
4110 | inc_rfc1001_len(pSMB, byte_count); | 4101 | inc_rfc1001_len(pSMB, byte_count); |
4102 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | ||
4111 | 4103 | ||
4112 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4104 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
4113 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4105 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -4794,11 +4786,8 @@ getDFSRetry: | |||
4794 | strncpy(pSMB->RequestFileName, search_name, name_len); | 4786 | strncpy(pSMB->RequestFileName, search_name, name_len); |
4795 | } | 4787 | } |
4796 | 4788 | ||
4797 | if (ses->server) { | 4789 | if (ses->server && ses->server->sign) |
4798 | if (ses->server->sec_mode & | 4790 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
4799 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
4800 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
4801 | } | ||
4802 | 4791 | ||
4803 | pSMB->hdr.Uid = ses->Suid; | 4792 | pSMB->hdr.Uid = ses->Suid; |
4804 | 4793 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e3bc39bb9d12..afcb8a1a33b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -85,7 +85,7 @@ enum { | |||
85 | Opt_acl, Opt_noacl, Opt_locallease, | 85 | Opt_acl, Opt_noacl, Opt_locallease, |
86 | Opt_sign, Opt_seal, Opt_noac, | 86 | Opt_sign, Opt_seal, Opt_noac, |
87 | Opt_fsc, Opt_mfsymlinks, | 87 | Opt_fsc, Opt_mfsymlinks, |
88 | Opt_multiuser, Opt_sloppy, | 88 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, |
89 | 89 | ||
90 | /* Mount options which take numeric value */ | 90 | /* Mount options which take numeric value */ |
91 | Opt_backupuid, Opt_backupgid, Opt_uid, | 91 | Opt_backupuid, Opt_backupgid, Opt_uid, |
@@ -165,6 +165,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
165 | { Opt_mfsymlinks, "mfsymlinks" }, | 165 | { Opt_mfsymlinks, "mfsymlinks" }, |
166 | { Opt_multiuser, "multiuser" }, | 166 | { Opt_multiuser, "multiuser" }, |
167 | { Opt_sloppy, "sloppy" }, | 167 | { Opt_sloppy, "sloppy" }, |
168 | { Opt_nosharesock, "nosharesock" }, | ||
168 | 169 | ||
169 | { Opt_backupuid, "backupuid=%s" }, | 170 | { Opt_backupuid, "backupuid=%s" }, |
170 | { Opt_backupgid, "backupgid=%s" }, | 171 | { Opt_backupgid, "backupgid=%s" }, |
@@ -275,6 +276,7 @@ static const match_table_t cifs_smb_version_tokens = { | |||
275 | { Smb_20, SMB20_VERSION_STRING}, | 276 | { Smb_20, SMB20_VERSION_STRING}, |
276 | { Smb_21, SMB21_VERSION_STRING }, | 277 | { Smb_21, SMB21_VERSION_STRING }, |
277 | { Smb_30, SMB30_VERSION_STRING }, | 278 | { Smb_30, SMB30_VERSION_STRING }, |
279 | { Smb_302, SMB302_VERSION_STRING }, | ||
278 | }; | 280 | }; |
279 | 281 | ||
280 | static int ip_connect(struct TCP_Server_Info *server); | 282 | static int ip_connect(struct TCP_Server_Info *server); |
@@ -1024,44 +1026,48 @@ static int cifs_parse_security_flavors(char *value, | |||
1024 | 1026 | ||
1025 | substring_t args[MAX_OPT_ARGS]; | 1027 | substring_t args[MAX_OPT_ARGS]; |
1026 | 1028 | ||
1029 | /* | ||
1030 | * With mount options, the last one should win. Reset any existing | ||
1031 | * settings back to default. | ||
1032 | */ | ||
1033 | vol->sectype = Unspecified; | ||
1034 | vol->sign = false; | ||
1035 | |||
1027 | switch (match_token(value, cifs_secflavor_tokens, args)) { | 1036 | switch (match_token(value, cifs_secflavor_tokens, args)) { |
1028 | case Opt_sec_krb5: | ||
1029 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_SIGN; | ||
1030 | break; | ||
1031 | case Opt_sec_krb5i: | ||
1032 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; | ||
1033 | break; | ||
1034 | case Opt_sec_krb5p: | 1037 | case Opt_sec_krb5p: |
1035 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ | 1038 | cifs_dbg(VFS, "sec=krb5p is not supported!\n"); |
1036 | cifs_dbg(VFS, "Krb5 cifs privacy not supported\n"); | 1039 | return 1; |
1037 | break; | 1040 | case Opt_sec_krb5i: |
1038 | case Opt_sec_ntlmssp: | 1041 | vol->sign = true; |
1039 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; | 1042 | /* Fallthrough */ |
1043 | case Opt_sec_krb5: | ||
1044 | vol->sectype = Kerberos; | ||
1040 | break; | 1045 | break; |
1041 | case Opt_sec_ntlmsspi: | 1046 | case Opt_sec_ntlmsspi: |
1042 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; | 1047 | vol->sign = true; |
1043 | break; | 1048 | /* Fallthrough */ |
1044 | case Opt_ntlm: | 1049 | case Opt_sec_ntlmssp: |
1045 | /* ntlm is default so can be turned off too */ | 1050 | vol->sectype = RawNTLMSSP; |
1046 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
1047 | break; | 1051 | break; |
1048 | case Opt_sec_ntlmi: | 1052 | case Opt_sec_ntlmi: |
1049 | vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; | 1053 | vol->sign = true; |
1050 | break; | 1054 | /* Fallthrough */ |
1051 | case Opt_sec_ntlmv2: | 1055 | case Opt_ntlm: |
1052 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | 1056 | vol->sectype = NTLM; |
1053 | break; | 1057 | break; |
1054 | case Opt_sec_ntlmv2i: | 1058 | case Opt_sec_ntlmv2i: |
1055 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; | 1059 | vol->sign = true; |
1060 | /* Fallthrough */ | ||
1061 | case Opt_sec_ntlmv2: | ||
1062 | vol->sectype = NTLMv2; | ||
1056 | break; | 1063 | break; |
1057 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 1064 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
1058 | case Opt_sec_lanman: | 1065 | case Opt_sec_lanman: |
1059 | vol->secFlg |= CIFSSEC_MAY_LANMAN; | 1066 | vol->sectype = LANMAN; |
1060 | break; | 1067 | break; |
1061 | #endif | 1068 | #endif |
1062 | case Opt_sec_none: | 1069 | case Opt_sec_none: |
1063 | vol->nullauth = 1; | 1070 | vol->nullauth = 1; |
1064 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
1065 | break; | 1071 | break; |
1066 | default: | 1072 | default: |
1067 | cifs_dbg(VFS, "bad security option: %s\n", value); | 1073 | cifs_dbg(VFS, "bad security option: %s\n", value); |
@@ -1119,6 +1125,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) | |||
1119 | vol->ops = &smb30_operations; | 1125 | vol->ops = &smb30_operations; |
1120 | vol->vals = &smb30_values; | 1126 | vol->vals = &smb30_values; |
1121 | break; | 1127 | break; |
1128 | case Smb_302: | ||
1129 | vol->ops = &smb30_operations; /* currently identical with 3.0 */ | ||
1130 | vol->vals = &smb302_values; | ||
1131 | break; | ||
1122 | #endif | 1132 | #endif |
1123 | default: | 1133 | default: |
1124 | cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value); | 1134 | cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value); |
@@ -1424,7 +1434,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1424 | vol->local_lease = 1; | 1434 | vol->local_lease = 1; |
1425 | break; | 1435 | break; |
1426 | case Opt_sign: | 1436 | case Opt_sign: |
1427 | vol->secFlg |= CIFSSEC_MUST_SIGN; | 1437 | vol->sign = true; |
1428 | break; | 1438 | break; |
1429 | case Opt_seal: | 1439 | case Opt_seal: |
1430 | /* we do not do the following in secFlags because seal | 1440 | /* we do not do the following in secFlags because seal |
@@ -1455,6 +1465,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1455 | case Opt_sloppy: | 1465 | case Opt_sloppy: |
1456 | sloppy = true; | 1466 | sloppy = true; |
1457 | break; | 1467 | break; |
1468 | case Opt_nosharesock: | ||
1469 | vol->nosharesock = true; | ||
1470 | break; | ||
1458 | 1471 | ||
1459 | /* Numeric Values */ | 1472 | /* Numeric Values */ |
1460 | case Opt_backupuid: | 1473 | case Opt_backupuid: |
@@ -1978,47 +1991,21 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr, | |||
1978 | static bool | 1991 | static bool |
1979 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) | 1992 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) |
1980 | { | 1993 | { |
1981 | unsigned int secFlags; | 1994 | /* |
1982 | 1995 | * The select_sectype function should either return the vol->sectype | |
1983 | if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | 1996 | * that was specified, or "Unspecified" if that sectype was not |
1984 | secFlags = vol->secFlg; | 1997 | * compatible with the given NEGOTIATE request. |
1985 | else | 1998 | */ |
1986 | secFlags = global_secflags | vol->secFlg; | 1999 | if (select_sectype(server, vol->sectype) == Unspecified) |
1987 | |||
1988 | switch (server->secType) { | ||
1989 | case LANMAN: | ||
1990 | if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT))) | ||
1991 | return false; | ||
1992 | break; | ||
1993 | case NTLMv2: | ||
1994 | if (!(secFlags & CIFSSEC_MAY_NTLMV2)) | ||
1995 | return false; | ||
1996 | break; | ||
1997 | case NTLM: | ||
1998 | if (!(secFlags & CIFSSEC_MAY_NTLM)) | ||
1999 | return false; | ||
2000 | break; | ||
2001 | case Kerberos: | ||
2002 | if (!(secFlags & CIFSSEC_MAY_KRB5)) | ||
2003 | return false; | ||
2004 | break; | ||
2005 | case RawNTLMSSP: | ||
2006 | if (!(secFlags & CIFSSEC_MAY_NTLMSSP)) | ||
2007 | return false; | ||
2008 | break; | ||
2009 | default: | ||
2010 | /* shouldn't happen */ | ||
2011 | return false; | 2000 | return false; |
2012 | } | ||
2013 | 2001 | ||
2014 | /* now check if signing mode is acceptable */ | 2002 | /* |
2015 | if ((secFlags & CIFSSEC_MAY_SIGN) == 0 && | 2003 | * Now check if signing mode is acceptable. No need to check |
2016 | (server->sec_mode & SECMODE_SIGN_REQUIRED)) | 2004 | * global_secflags at this point since if MUST_SIGN is set then |
2017 | return false; | 2005 | * the server->sign had better be too. |
2018 | else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) && | 2006 | */ |
2019 | (server->sec_mode & | 2007 | if (vol->sign && !server->sign) |
2020 | (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0) | 2008 | return false; |
2021 | return false; | ||
2022 | 2009 | ||
2023 | return true; | 2010 | return true; |
2024 | } | 2011 | } |
@@ -2027,6 +2014,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2027 | { | 2014 | { |
2028 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; | 2015 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; |
2029 | 2016 | ||
2017 | if (vol->nosharesock) | ||
2018 | return 0; | ||
2019 | |||
2030 | if ((server->vals != vol->vals) || (server->ops != vol->ops)) | 2020 | if ((server->vals != vol->vals) || (server->ops != vol->ops)) |
2031 | return 0; | 2021 | return 0; |
2032 | 2022 | ||
@@ -2216,7 +2206,11 @@ out_err: | |||
2216 | 2206 | ||
2217 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) | 2207 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) |
2218 | { | 2208 | { |
2219 | switch (ses->server->secType) { | 2209 | if (vol->sectype != Unspecified && |
2210 | vol->sectype != ses->sectype) | ||
2211 | return 0; | ||
2212 | |||
2213 | switch (ses->sectype) { | ||
2220 | case Kerberos: | 2214 | case Kerberos: |
2221 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) | 2215 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) |
2222 | return 0; | 2216 | return 0; |
@@ -2493,7 +2487,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
2493 | ses->cred_uid = volume_info->cred_uid; | 2487 | ses->cred_uid = volume_info->cred_uid; |
2494 | ses->linux_uid = volume_info->linux_uid; | 2488 | ses->linux_uid = volume_info->linux_uid; |
2495 | 2489 | ||
2496 | ses->overrideSecFlg = volume_info->secFlg; | 2490 | ses->sectype = volume_info->sectype; |
2491 | ses->sign = volume_info->sign; | ||
2497 | 2492 | ||
2498 | mutex_lock(&ses->session_mutex); | 2493 | mutex_lock(&ses->session_mutex); |
2499 | rc = cifs_negotiate_protocol(xid, ses); | 2494 | rc = cifs_negotiate_protocol(xid, ses); |
@@ -3656,7 +3651,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3656 | NTLMv2 password here) */ | 3651 | NTLMv2 password here) */ |
3657 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 3652 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
3658 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && | 3653 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && |
3659 | (ses->server->secType == LANMAN)) | 3654 | (ses->sectype == LANMAN)) |
3660 | calc_lanman_hash(tcon->password, ses->server->cryptkey, | 3655 | calc_lanman_hash(tcon->password, ses->server->cryptkey, |
3661 | ses->server->sec_mode & | 3656 | ses->server->sec_mode & |
3662 | SECMODE_PW_ENCRYPT ? true : false, | 3657 | SECMODE_PW_ENCRYPT ? true : false, |
@@ -3674,8 +3669,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3674 | } | 3669 | } |
3675 | } | 3670 | } |
3676 | 3671 | ||
3677 | if (ses->server->sec_mode & | 3672 | if (ses->server->sign) |
3678 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
3679 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 3673 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
3680 | 3674 | ||
3681 | if (ses->capabilities & CAP_STATUS32) { | 3675 | if (ses->capabilities & CAP_STATUS32) { |
@@ -3738,7 +3732,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
3738 | } | 3732 | } |
3739 | bcc_ptr += length + 1; | 3733 | bcc_ptr += length + 1; |
3740 | bytes_left -= (length + 1); | 3734 | bytes_left -= (length + 1); |
3741 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 3735 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
3742 | 3736 | ||
3743 | /* mostly informational -- no need to fail on error here */ | 3737 | /* mostly informational -- no need to fail on error here */ |
3744 | kfree(tcon->nativeFileSystem); | 3738 | kfree(tcon->nativeFileSystem); |
@@ -3827,7 +3821,6 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3827 | int rc = -ENOSYS; | 3821 | int rc = -ENOSYS; |
3828 | struct TCP_Server_Info *server = ses->server; | 3822 | struct TCP_Server_Info *server = ses->server; |
3829 | 3823 | ||
3830 | ses->flags = 0; | ||
3831 | ses->capabilities = server->capabilities; | 3824 | ses->capabilities = server->capabilities; |
3832 | if (linuxExtEnabled == 0) | 3825 | if (linuxExtEnabled == 0) |
3833 | ses->capabilities &= (~server->vals->cap_unix); | 3826 | ses->capabilities &= (~server->vals->cap_unix); |
@@ -3848,6 +3841,8 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3848 | server->sequence_number = 0x2; | 3841 | server->sequence_number = 0x2; |
3849 | server->session_estab = true; | 3842 | server->session_estab = true; |
3850 | ses->auth_key.response = NULL; | 3843 | ses->auth_key.response = NULL; |
3844 | if (server->ops->generate_signingkey) | ||
3845 | server->ops->generate_signingkey(server); | ||
3851 | } | 3846 | } |
3852 | mutex_unlock(&server->srv_mutex); | 3847 | mutex_unlock(&server->srv_mutex); |
3853 | 3848 | ||
@@ -3870,23 +3865,11 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
3870 | static int | 3865 | static int |
3871 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) | 3866 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) |
3872 | { | 3867 | { |
3873 | switch (ses->server->secType) { | 3868 | vol->sectype = ses->sectype; |
3874 | case Kerberos: | 3869 | |
3875 | vol->secFlg = CIFSSEC_MUST_KRB5; | 3870 | /* krb5 is special, since we don't need username or pw */ |
3871 | if (vol->sectype == Kerberos) | ||
3876 | return 0; | 3872 | return 0; |
3877 | case NTLMv2: | ||
3878 | vol->secFlg = CIFSSEC_MUST_NTLMV2; | ||
3879 | break; | ||
3880 | case NTLM: | ||
3881 | vol->secFlg = CIFSSEC_MUST_NTLM; | ||
3882 | break; | ||
3883 | case RawNTLMSSP: | ||
3884 | vol->secFlg = CIFSSEC_MUST_NTLMSSP; | ||
3885 | break; | ||
3886 | case LANMAN: | ||
3887 | vol->secFlg = CIFSSEC_MUST_LANMAN; | ||
3888 | break; | ||
3889 | } | ||
3890 | 3873 | ||
3891 | return cifs_set_cifscreds(vol, ses); | 3874 | return cifs_set_cifscreds(vol, ses); |
3892 | } | 3875 | } |
@@ -3912,6 +3895,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) | |||
3912 | vol_info->nocase = master_tcon->nocase; | 3895 | vol_info->nocase = master_tcon->nocase; |
3913 | vol_info->local_lease = master_tcon->local_lease; | 3896 | vol_info->local_lease = master_tcon->local_lease; |
3914 | vol_info->no_linux_ext = !master_tcon->unix_ext; | 3897 | vol_info->no_linux_ext = !master_tcon->unix_ext; |
3898 | vol_info->sectype = master_tcon->ses->sectype; | ||
3899 | vol_info->sign = master_tcon->ses->sign; | ||
3915 | 3900 | ||
3916 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); | 3901 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); |
3917 | if (rc) { | 3902 | if (rc) { |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1bec014779fd..f7d4b2285efe 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -267,8 +267,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
267 | if (treeCon->nocase) | 267 | if (treeCon->nocase) |
268 | buffer->Flags |= SMBFLG_CASELESS; | 268 | buffer->Flags |= SMBFLG_CASELESS; |
269 | if ((treeCon->ses) && (treeCon->ses->server)) | 269 | if ((treeCon->ses) && (treeCon->ses->server)) |
270 | if (treeCon->ses->server->sec_mode & | 270 | if (treeCon->ses->server->sign) |
271 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
272 | buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 271 | buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
273 | } | 272 | } |
274 | 273 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index f1213799de1a..ab8778469394 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -126,6 +126,22 @@ out: | |||
126 | dput(dentry); | 126 | dput(dentry); |
127 | } | 127 | } |
128 | 128 | ||
129 | /* | ||
130 | * Is it possible that this directory might turn out to be a DFS referral | ||
131 | * once we go to try and use it? | ||
132 | */ | ||
133 | static bool | ||
134 | cifs_dfs_is_possible(struct cifs_sb_info *cifs_sb) | ||
135 | { | ||
136 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
137 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | ||
138 | |||
139 | if (tcon->Flags & SMB_SHARE_IS_IN_DFS) | ||
140 | return true; | ||
141 | #endif | ||
142 | return false; | ||
143 | } | ||
144 | |||
129 | static void | 145 | static void |
130 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | 146 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) |
131 | { | 147 | { |
@@ -135,6 +151,19 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | |||
135 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 151 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
136 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | 152 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
137 | fattr->cf_dtype = DT_DIR; | 153 | fattr->cf_dtype = DT_DIR; |
154 | /* | ||
155 | * Windows CIFS servers generally make DFS referrals look | ||
156 | * like directories in FIND_* responses with the reparse | ||
157 | * attribute flag also set (since DFS junctions are | ||
158 | * reparse points). We must revalidate at least these | ||
159 | * directory inodes before trying to use them (if | ||
160 | * they are DFS we will get PATH_NOT_COVERED back | ||
161 | * when queried directly and can then try to connect | ||
162 | * to the DFS target) | ||
163 | */ | ||
164 | if (cifs_dfs_is_possible(cifs_sb) && | ||
165 | (fattr->cf_cifsattrs & ATTR_REPARSE)) | ||
166 | fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; | ||
138 | } else { | 167 | } else { |
139 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | 168 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; |
140 | fattr->cf_dtype = DT_REG; | 169 | fattr->cf_dtype = DT_REG; |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index f230571a7ab3..79358e341fd2 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -138,8 +138,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) | |||
138 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | 138 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | |
139 | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; | 139 | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; |
140 | 140 | ||
141 | if (ses->server->sec_mode & | 141 | if (ses->server->sign) |
142 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
143 | pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 142 | pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
144 | 143 | ||
145 | if (ses->capabilities & CAP_UNICODE) { | 144 | if (ses->capabilities & CAP_UNICODE) { |
@@ -310,11 +309,10 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, | |||
310 | return; | 309 | return; |
311 | } | 310 | } |
312 | 311 | ||
313 | static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | 312 | static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft, |
314 | struct cifs_ses *ses, | 313 | struct cifs_ses *ses, |
315 | const struct nls_table *nls_cp) | 314 | const struct nls_table *nls_cp) |
316 | { | 315 | { |
317 | int rc = 0; | ||
318 | int len; | 316 | int len; |
319 | char *bcc_ptr = *pbcc_area; | 317 | char *bcc_ptr = *pbcc_area; |
320 | 318 | ||
@@ -322,24 +320,22 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | |||
322 | 320 | ||
323 | len = strnlen(bcc_ptr, bleft); | 321 | len = strnlen(bcc_ptr, bleft); |
324 | if (len >= bleft) | 322 | if (len >= bleft) |
325 | return rc; | 323 | return; |
326 | 324 | ||
327 | kfree(ses->serverOS); | 325 | kfree(ses->serverOS); |
328 | 326 | ||
329 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); | 327 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); |
330 | if (ses->serverOS) | 328 | if (ses->serverOS) |
331 | strncpy(ses->serverOS, bcc_ptr, len); | 329 | strncpy(ses->serverOS, bcc_ptr, len); |
332 | if (strncmp(ses->serverOS, "OS/2", 4) == 0) { | 330 | if (strncmp(ses->serverOS, "OS/2", 4) == 0) |
333 | cifs_dbg(FYI, "OS/2 server\n"); | 331 | cifs_dbg(FYI, "OS/2 server\n"); |
334 | ses->flags |= CIFS_SES_OS2; | ||
335 | } | ||
336 | 332 | ||
337 | bcc_ptr += len + 1; | 333 | bcc_ptr += len + 1; |
338 | bleft -= len + 1; | 334 | bleft -= len + 1; |
339 | 335 | ||
340 | len = strnlen(bcc_ptr, bleft); | 336 | len = strnlen(bcc_ptr, bleft); |
341 | if (len >= bleft) | 337 | if (len >= bleft) |
342 | return rc; | 338 | return; |
343 | 339 | ||
344 | kfree(ses->serverNOS); | 340 | kfree(ses->serverNOS); |
345 | 341 | ||
@@ -352,7 +348,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | |||
352 | 348 | ||
353 | len = strnlen(bcc_ptr, bleft); | 349 | len = strnlen(bcc_ptr, bleft); |
354 | if (len > bleft) | 350 | if (len > bleft) |
355 | return rc; | 351 | return; |
356 | 352 | ||
357 | /* No domain field in LANMAN case. Domain is | 353 | /* No domain field in LANMAN case. Domain is |
358 | returned by old servers in the SMB negprot response */ | 354 | returned by old servers in the SMB negprot response */ |
@@ -360,8 +356,6 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | |||
360 | but thus do return domain here we could add parsing | 356 | but thus do return domain here we could add parsing |
361 | for it later, but it is not very important */ | 357 | for it later, but it is not very important */ |
362 | cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); | 358 | cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); |
363 | |||
364 | return rc; | ||
365 | } | 359 | } |
366 | 360 | ||
367 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | 361 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, |
@@ -432,8 +426,7 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
432 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | | 426 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
433 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 427 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
434 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 428 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
435 | if (ses->server->sec_mode & | 429 | if (ses->server->sign) { |
436 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
437 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 430 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
438 | if (!ses->server->session_estab) | 431 | if (!ses->server->session_estab) |
439 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | 432 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
@@ -471,8 +464,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
471 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | | 464 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | |
472 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 465 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
473 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 466 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
474 | if (ses->server->sec_mode & | 467 | if (ses->server->sign) { |
475 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
476 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 468 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
477 | if (!ses->server->session_estab) | 469 | if (!ses->server->session_estab) |
478 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | 470 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
@@ -558,6 +550,56 @@ setup_ntlmv2_ret: | |||
558 | return rc; | 550 | return rc; |
559 | } | 551 | } |
560 | 552 | ||
553 | enum securityEnum | ||
554 | select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) | ||
555 | { | ||
556 | switch (server->negflavor) { | ||
557 | case CIFS_NEGFLAVOR_EXTENDED: | ||
558 | switch (requested) { | ||
559 | case Kerberos: | ||
560 | case RawNTLMSSP: | ||
561 | return requested; | ||
562 | case Unspecified: | ||
563 | if (server->sec_ntlmssp && | ||
564 | (global_secflags & CIFSSEC_MAY_NTLMSSP)) | ||
565 | return RawNTLMSSP; | ||
566 | if ((server->sec_kerberos || server->sec_mskerberos) && | ||
567 | (global_secflags & CIFSSEC_MAY_KRB5)) | ||
568 | return Kerberos; | ||
569 | /* Fallthrough */ | ||
570 | default: | ||
571 | return Unspecified; | ||
572 | } | ||
573 | case CIFS_NEGFLAVOR_UNENCAP: | ||
574 | switch (requested) { | ||
575 | case NTLM: | ||
576 | case NTLMv2: | ||
577 | return requested; | ||
578 | case Unspecified: | ||
579 | if (global_secflags & CIFSSEC_MAY_NTLMV2) | ||
580 | return NTLMv2; | ||
581 | if (global_secflags & CIFSSEC_MAY_NTLM) | ||
582 | return NTLM; | ||
583 | /* Fallthrough */ | ||
584 | default: | ||
585 | return Unspecified; | ||
586 | } | ||
587 | case CIFS_NEGFLAVOR_LANMAN: | ||
588 | switch (requested) { | ||
589 | case LANMAN: | ||
590 | return requested; | ||
591 | case Unspecified: | ||
592 | if (global_secflags & CIFSSEC_MAY_LANMAN) | ||
593 | return LANMAN; | ||
594 | /* Fallthrough */ | ||
595 | default: | ||
596 | return Unspecified; | ||
597 | } | ||
598 | default: | ||
599 | return Unspecified; | ||
600 | } | ||
601 | } | ||
602 | |||
561 | int | 603 | int |
562 | CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | 604 | CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, |
563 | const struct nls_table *nls_cp) | 605 | const struct nls_table *nls_cp) |
@@ -579,11 +621,18 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | |||
579 | u16 blob_len; | 621 | u16 blob_len; |
580 | char *ntlmsspblob = NULL; | 622 | char *ntlmsspblob = NULL; |
581 | 623 | ||
582 | if (ses == NULL) | 624 | if (ses == NULL) { |
625 | WARN(1, "%s: ses == NULL!", __func__); | ||
583 | return -EINVAL; | 626 | return -EINVAL; |
627 | } | ||
584 | 628 | ||
585 | type = ses->server->secType; | 629 | type = select_sectype(ses->server, ses->sectype); |
586 | cifs_dbg(FYI, "sess setup type %d\n", type); | 630 | cifs_dbg(FYI, "sess setup type %d\n", type); |
631 | if (type == Unspecified) { | ||
632 | cifs_dbg(VFS, "Unable to select appropriate authentication method!"); | ||
633 | return -EINVAL; | ||
634 | } | ||
635 | |||
587 | if (type == RawNTLMSSP) { | 636 | if (type == RawNTLMSSP) { |
588 | /* if memory allocation is successful, caller of this function | 637 | /* if memory allocation is successful, caller of this function |
589 | * frees it. | 638 | * frees it. |
@@ -643,8 +692,6 @@ ssetup_ntlmssp_authenticate: | |||
643 | } | 692 | } |
644 | bcc_ptr = str_area; | 693 | bcc_ptr = str_area; |
645 | 694 | ||
646 | ses->flags &= ~CIFS_SES_LANMAN; | ||
647 | |||
648 | iov[1].iov_base = NULL; | 695 | iov[1].iov_base = NULL; |
649 | iov[1].iov_len = 0; | 696 | iov[1].iov_len = 0; |
650 | 697 | ||
@@ -668,7 +715,6 @@ ssetup_ntlmssp_authenticate: | |||
668 | ses->server->sec_mode & SECMODE_PW_ENCRYPT ? | 715 | ses->server->sec_mode & SECMODE_PW_ENCRYPT ? |
669 | true : false, lnm_session_key); | 716 | true : false, lnm_session_key); |
670 | 717 | ||
671 | ses->flags |= CIFS_SES_LANMAN; | ||
672 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); | 718 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); |
673 | bcc_ptr += CIFS_AUTH_RESP_SIZE; | 719 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
674 | 720 | ||
@@ -938,8 +984,7 @@ ssetup_ntlmssp_authenticate: | |||
938 | } | 984 | } |
939 | decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); | 985 | decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); |
940 | } else { | 986 | } else { |
941 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, | 987 | decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); |
942 | ses, nls_cp); | ||
943 | } | 988 | } |
944 | 989 | ||
945 | ssetup_exit: | 990 | ssetup_exit: |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 3efdb9d5c0b8..e813f04511d8 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -449,8 +449,7 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) | |||
449 | * WRITEX header, not including the 4 byte RFC1001 length. | 449 | * WRITEX header, not including the 4 byte RFC1001 length. |
450 | */ | 450 | */ |
451 | if (!(server->capabilities & CAP_LARGE_WRITE_X) || | 451 | if (!(server->capabilities & CAP_LARGE_WRITE_X) || |
452 | (!(server->capabilities & CAP_UNIX) && | 452 | (!(server->capabilities & CAP_UNIX) && server->sign)) |
453 | (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)))) | ||
454 | wsize = min_t(unsigned int, wsize, | 453 | wsize = min_t(unsigned int, wsize, |
455 | server->maxBuf - sizeof(WRITE_REQ) + 4); | 454 | server->maxBuf - sizeof(WRITE_REQ) + 4); |
456 | 455 | ||
@@ -765,20 +764,14 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
765 | } | 764 | } |
766 | tcon = tlink_tcon(tlink); | 765 | tcon = tlink_tcon(tlink); |
767 | 766 | ||
768 | /* | 767 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, |
769 | * NT4 apparently returns success on this call, but it doesn't really | ||
770 | * work. | ||
771 | */ | ||
772 | if (!(tcon->ses->flags & CIFS_SES_NT4)) { | ||
773 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, | ||
774 | cifs_sb->local_nls, | ||
775 | cifs_sb->mnt_cifs_flags & | 768 | cifs_sb->mnt_cifs_flags & |
776 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 769 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
777 | if (rc == 0) { | 770 | if (rc == 0) { |
778 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); | 771 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); |
779 | goto out; | 772 | goto out; |
780 | } else if (rc != -EOPNOTSUPP && rc != -EINVAL) | 773 | } else if (rc != -EOPNOTSUPP && rc != -EINVAL) { |
781 | goto out; | 774 | goto out; |
782 | } | 775 | } |
783 | 776 | ||
784 | cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); | 777 | cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); |
@@ -964,4 +957,6 @@ struct smb_version_values smb1_values = { | |||
964 | .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND, | 957 | .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND, |
965 | .cap_large_files = CAP_LARGE_FILES, | 958 | .cap_large_files = CAP_LARGE_FILES, |
966 | .oplock_read = OPLOCK_READ, | 959 | .oplock_read = OPLOCK_READ, |
960 | .signing_enabled = SECMODE_SIGN_ENABLED, | ||
961 | .signing_required = SECMODE_SIGN_REQUIRED, | ||
967 | }; | 962 | }; |
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index 7c0e2143e775..c38350851b08 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h | |||
@@ -54,5 +54,7 @@ | |||
54 | #define SMB2_SIGNATURE_SIZE (16) | 54 | #define SMB2_SIGNATURE_SIZE (16) |
55 | #define SMB2_NTLMV2_SESSKEY_SIZE (16) | 55 | #define SMB2_NTLMV2_SESSKEY_SIZE (16) |
56 | #define SMB2_HMACSHA256_SIZE (32) | 56 | #define SMB2_HMACSHA256_SIZE (32) |
57 | #define SMB2_CMACAES_SIZE (16) | ||
58 | #define SMB3_SIGNKEY_SIZE (16) | ||
57 | 59 | ||
58 | #endif /* _SMB2_GLOB_H */ | 60 | #endif /* _SMB2_GLOB_H */ |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 10383d8c015b..b0c43345cd98 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -266,6 +266,10 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
266 | ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength); | 266 | ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength); |
267 | break; | 267 | break; |
268 | case SMB2_IOCTL: | 268 | case SMB2_IOCTL: |
269 | *off = le32_to_cpu( | ||
270 | ((struct smb2_ioctl_rsp *)hdr)->OutputOffset); | ||
271 | *len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount); | ||
272 | break; | ||
269 | case SMB2_CHANGE_NOTIFY: | 273 | case SMB2_CHANGE_NOTIFY: |
270 | default: | 274 | default: |
271 | /* BB FIXME for unimplemented cases above */ | 275 | /* BB FIXME for unimplemented cases above */ |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f2e76f3b0c61..6d15cab95b99 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -281,6 +281,25 @@ smb2_clear_stats(struct cifs_tcon *tcon) | |||
281 | } | 281 | } |
282 | 282 | ||
283 | static void | 283 | static void |
284 | smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon) | ||
285 | { | ||
286 | seq_puts(m, "\n\tShare Capabilities:"); | ||
287 | if (tcon->capabilities & SMB2_SHARE_CAP_DFS) | ||
288 | seq_puts(m, " DFS,"); | ||
289 | if (tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY) | ||
290 | seq_puts(m, " CONTINUOUS AVAILABILITY,"); | ||
291 | if (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT) | ||
292 | seq_puts(m, " SCALEOUT,"); | ||
293 | if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) | ||
294 | seq_puts(m, " CLUSTER,"); | ||
295 | if (tcon->capabilities & SMB2_SHARE_CAP_ASYMMETRIC) | ||
296 | seq_puts(m, " ASYMMETRIC,"); | ||
297 | if (tcon->capabilities == 0) | ||
298 | seq_puts(m, " None"); | ||
299 | seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags); | ||
300 | } | ||
301 | |||
302 | static void | ||
284 | smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon) | 303 | smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon) |
285 | { | 304 | { |
286 | #ifdef CONFIG_CIFS_STATS | 305 | #ifdef CONFIG_CIFS_STATS |
@@ -292,7 +311,6 @@ smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon) | |||
292 | seq_printf(m, "\nSessionSetups: %d sent %d failed", | 311 | seq_printf(m, "\nSessionSetups: %d sent %d failed", |
293 | atomic_read(&sent[SMB2_SESSION_SETUP_HE]), | 312 | atomic_read(&sent[SMB2_SESSION_SETUP_HE]), |
294 | atomic_read(&failed[SMB2_SESSION_SETUP_HE])); | 313 | atomic_read(&failed[SMB2_SESSION_SETUP_HE])); |
295 | #define SMB2LOGOFF 0x0002 /* trivial request/resp */ | ||
296 | seq_printf(m, "\nLogoffs: %d sent %d failed", | 314 | seq_printf(m, "\nLogoffs: %d sent %d failed", |
297 | atomic_read(&sent[SMB2_LOGOFF_HE]), | 315 | atomic_read(&sent[SMB2_LOGOFF_HE]), |
298 | atomic_read(&failed[SMB2_LOGOFF_HE])); | 316 | atomic_read(&failed[SMB2_LOGOFF_HE])); |
@@ -645,6 +663,7 @@ struct smb_version_operations smb30_operations = { | |||
645 | .dump_detail = smb2_dump_detail, | 663 | .dump_detail = smb2_dump_detail, |
646 | .clear_stats = smb2_clear_stats, | 664 | .clear_stats = smb2_clear_stats, |
647 | .print_stats = smb2_print_stats, | 665 | .print_stats = smb2_print_stats, |
666 | .dump_share_caps = smb2_dump_share_caps, | ||
648 | .is_oplock_break = smb2_is_valid_oplock_break, | 667 | .is_oplock_break = smb2_is_valid_oplock_break, |
649 | .need_neg = smb2_need_neg, | 668 | .need_neg = smb2_need_neg, |
650 | .negotiate = smb2_negotiate, | 669 | .negotiate = smb2_negotiate, |
@@ -690,6 +709,7 @@ struct smb_version_operations smb30_operations = { | |||
690 | .get_lease_key = smb2_get_lease_key, | 709 | .get_lease_key = smb2_get_lease_key, |
691 | .set_lease_key = smb2_set_lease_key, | 710 | .set_lease_key = smb2_set_lease_key, |
692 | .new_lease_key = smb2_new_lease_key, | 711 | .new_lease_key = smb2_new_lease_key, |
712 | .generate_signingkey = generate_smb3signingkey, | ||
693 | .calc_signature = smb3_calc_signature, | 713 | .calc_signature = smb3_calc_signature, |
694 | }; | 714 | }; |
695 | 715 | ||
@@ -709,6 +729,8 @@ struct smb_version_values smb20_values = { | |||
709 | .cap_nt_find = SMB2_NT_FIND, | 729 | .cap_nt_find = SMB2_NT_FIND, |
710 | .cap_large_files = SMB2_LARGE_FILES, | 730 | .cap_large_files = SMB2_LARGE_FILES, |
711 | .oplock_read = SMB2_OPLOCK_LEVEL_II, | 731 | .oplock_read = SMB2_OPLOCK_LEVEL_II, |
732 | .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
733 | .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
712 | }; | 734 | }; |
713 | 735 | ||
714 | struct smb_version_values smb21_values = { | 736 | struct smb_version_values smb21_values = { |
@@ -727,6 +749,8 @@ struct smb_version_values smb21_values = { | |||
727 | .cap_nt_find = SMB2_NT_FIND, | 749 | .cap_nt_find = SMB2_NT_FIND, |
728 | .cap_large_files = SMB2_LARGE_FILES, | 750 | .cap_large_files = SMB2_LARGE_FILES, |
729 | .oplock_read = SMB2_OPLOCK_LEVEL_II, | 751 | .oplock_read = SMB2_OPLOCK_LEVEL_II, |
752 | .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
753 | .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
730 | }; | 754 | }; |
731 | 755 | ||
732 | struct smb_version_values smb30_values = { | 756 | struct smb_version_values smb30_values = { |
@@ -745,4 +769,26 @@ struct smb_version_values smb30_values = { | |||
745 | .cap_nt_find = SMB2_NT_FIND, | 769 | .cap_nt_find = SMB2_NT_FIND, |
746 | .cap_large_files = SMB2_LARGE_FILES, | 770 | .cap_large_files = SMB2_LARGE_FILES, |
747 | .oplock_read = SMB2_OPLOCK_LEVEL_II, | 771 | .oplock_read = SMB2_OPLOCK_LEVEL_II, |
772 | .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
773 | .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
774 | }; | ||
775 | |||
776 | struct smb_version_values smb302_values = { | ||
777 | .version_string = SMB302_VERSION_STRING, | ||
778 | .protocol_id = SMB302_PROT_ID, | ||
779 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU, | ||
780 | .large_lock_type = 0, | ||
781 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | ||
782 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | ||
783 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | ||
784 | .header_size = sizeof(struct smb2_hdr), | ||
785 | .max_header_size = MAX_SMB2_HDR_SIZE, | ||
786 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | ||
787 | .lock_cmd = SMB2_LOCK, | ||
788 | .cap_unix = 0, | ||
789 | .cap_nt_find = SMB2_NT_FIND, | ||
790 | .cap_large_files = SMB2_LARGE_FILES, | ||
791 | .oplock_read = SMB2_OPLOCK_LEVEL_II, | ||
792 | .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
793 | .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, | ||
748 | }; | 794 | }; |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2b95ce2b54e8..2b312e4eeaa6 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/smb2pdu.c | 2 | * fs/cifs/smb2pdu.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2009, 2012 | 4 | * Copyright (C) International Business Machines Corp., 2009, 2013 |
5 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
6 | * Author(s): Steve French (sfrench@us.ibm.com) | 6 | * Author(s): Steve French (sfrench@us.ibm.com) |
7 | * Pavel Shilovsky (pshilovsky@samba.org) 2012 | 7 | * Pavel Shilovsky (pshilovsky@samba.org) 2012 |
@@ -108,19 +108,33 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , | |||
108 | if (!tcon) | 108 | if (!tcon) |
109 | goto out; | 109 | goto out; |
110 | 110 | ||
111 | /* BB FIXME when we do write > 64K add +1 for every 64K in req or rsp */ | ||
112 | /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ | ||
113 | /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ | ||
114 | if ((tcon->ses) && | ||
115 | (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) | ||
116 | hdr->CreditCharge = cpu_to_le16(1); | ||
117 | /* else CreditCharge MBZ */ | ||
118 | |||
111 | hdr->TreeId = tcon->tid; | 119 | hdr->TreeId = tcon->tid; |
112 | /* Uid is not converted */ | 120 | /* Uid is not converted */ |
113 | if (tcon->ses) | 121 | if (tcon->ses) |
114 | hdr->SessionId = tcon->ses->Suid; | 122 | hdr->SessionId = tcon->ses->Suid; |
115 | /* BB check following DFS flags BB */ | 123 | |
116 | /* BB do we have to add check for SHI1005_FLAGS_DFS_ROOT too? */ | 124 | /* |
117 | if (tcon->share_flags & SHI1005_FLAGS_DFS) | 125 | * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have |
118 | hdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; | 126 | * to pass the path on the Open SMB prefixed by \\server\share. |
119 | /* BB how does SMB2 do case sensitive? */ | 127 | * Not sure when we would need to do the augmented path (if ever) and |
120 | /* if (tcon->nocase) | 128 | * setting this flag breaks the SMB2 open operation since it is |
121 | hdr->Flags |= SMBFLG_CASELESS; */ | 129 | * illegal to send an empty path name (without \\server\share prefix) |
122 | if (tcon->ses && tcon->ses->server && | 130 | * when the DFS flag is set in the SMB open header. We could |
123 | (tcon->ses->server->sec_mode & SECMODE_SIGN_REQUIRED)) | 131 | * consider setting the flag on all operations other than open |
132 | * but it is safer to net set it for now. | ||
133 | */ | ||
134 | /* if (tcon->share_flags & SHI1005_FLAGS_DFS) | ||
135 | hdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ | ||
136 | |||
137 | if (tcon->ses && tcon->ses->server && tcon->ses->server->sign) | ||
124 | hdr->Flags |= SMB2_FLAGS_SIGNED; | 138 | hdr->Flags |= SMB2_FLAGS_SIGNED; |
125 | out: | 139 | out: |
126 | pdu->StructureSize2 = cpu_to_le16(parmsize); | 140 | pdu->StructureSize2 = cpu_to_le16(parmsize); |
@@ -328,34 +342,22 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
328 | struct kvec iov[1]; | 342 | struct kvec iov[1]; |
329 | int rc = 0; | 343 | int rc = 0; |
330 | int resp_buftype; | 344 | int resp_buftype; |
331 | struct TCP_Server_Info *server; | 345 | struct TCP_Server_Info *server = ses->server; |
332 | unsigned int sec_flags; | ||
333 | u16 temp = 0; | ||
334 | int blob_offset, blob_length; | 346 | int blob_offset, blob_length; |
335 | char *security_blob; | 347 | char *security_blob; |
336 | int flags = CIFS_NEG_OP; | 348 | int flags = CIFS_NEG_OP; |
337 | 349 | ||
338 | cifs_dbg(FYI, "Negotiate protocol\n"); | 350 | cifs_dbg(FYI, "Negotiate protocol\n"); |
339 | 351 | ||
340 | if (ses->server) | 352 | if (!server) { |
341 | server = ses->server; | 353 | WARN(1, "%s: server is NULL!\n", __func__); |
342 | else { | 354 | return -EIO; |
343 | rc = -EIO; | ||
344 | return rc; | ||
345 | } | 355 | } |
346 | 356 | ||
347 | rc = small_smb2_init(SMB2_NEGOTIATE, NULL, (void **) &req); | 357 | rc = small_smb2_init(SMB2_NEGOTIATE, NULL, (void **) &req); |
348 | if (rc) | 358 | if (rc) |
349 | return rc; | 359 | return rc; |
350 | 360 | ||
351 | /* if any of auth flags (ie not sign or seal) are overriden use them */ | ||
352 | if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
353 | sec_flags = ses->overrideSecFlg; /* BB FIXME fix sign flags?*/ | ||
354 | else /* if override flags set only sign/seal OR them with global auth */ | ||
355 | sec_flags = global_secflags | ses->overrideSecFlg; | ||
356 | |||
357 | cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags); | ||
358 | |||
359 | req->hdr.SessionId = 0; | 361 | req->hdr.SessionId = 0; |
360 | 362 | ||
361 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); | 363 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); |
@@ -364,12 +366,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
364 | inc_rfc1001_len(req, 2); | 366 | inc_rfc1001_len(req, 2); |
365 | 367 | ||
366 | /* only one of SMB2 signing flags may be set in SMB2 request */ | 368 | /* only one of SMB2 signing flags may be set in SMB2 request */ |
367 | if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) | 369 | if (ses->sign) |
368 | temp = SMB2_NEGOTIATE_SIGNING_REQUIRED; | 370 | req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); |
369 | else if (sec_flags & CIFSSEC_MAY_SIGN) /* MAY_SIGN is a single flag */ | 371 | else if (global_secflags & CIFSSEC_MAY_SIGN) |
370 | temp = SMB2_NEGOTIATE_SIGNING_ENABLED; | 372 | req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); |
371 | 373 | else | |
372 | req->SecurityMode = cpu_to_le16(temp); | 374 | req->SecurityMode = 0; |
373 | 375 | ||
374 | req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); | 376 | req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); |
375 | 377 | ||
@@ -399,6 +401,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
399 | cifs_dbg(FYI, "negotiated smb2.1 dialect\n"); | 401 | cifs_dbg(FYI, "negotiated smb2.1 dialect\n"); |
400 | else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID)) | 402 | else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID)) |
401 | cifs_dbg(FYI, "negotiated smb3.0 dialect\n"); | 403 | cifs_dbg(FYI, "negotiated smb3.0 dialect\n"); |
404 | else if (rsp->DialectRevision == cpu_to_le16(SMB302_PROT_ID)) | ||
405 | cifs_dbg(FYI, "negotiated smb3.02 dialect\n"); | ||
402 | else { | 406 | else { |
403 | cifs_dbg(VFS, "Illegal dialect returned by server %d\n", | 407 | cifs_dbg(VFS, "Illegal dialect returned by server %d\n", |
404 | le16_to_cpu(rsp->DialectRevision)); | 408 | le16_to_cpu(rsp->DialectRevision)); |
@@ -407,6 +411,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
407 | } | 411 | } |
408 | server->dialect = le16_to_cpu(rsp->DialectRevision); | 412 | server->dialect = le16_to_cpu(rsp->DialectRevision); |
409 | 413 | ||
414 | /* SMB2 only has an extended negflavor */ | ||
415 | server->negflavor = CIFS_NEGFLAVOR_EXTENDED; | ||
410 | server->maxBuf = le32_to_cpu(rsp->MaxTransactSize); | 416 | server->maxBuf = le32_to_cpu(rsp->MaxTransactSize); |
411 | server->max_read = le32_to_cpu(rsp->MaxReadSize); | 417 | server->max_read = le32_to_cpu(rsp->MaxReadSize); |
412 | server->max_write = le32_to_cpu(rsp->MaxWriteSize); | 418 | server->max_write = le32_to_cpu(rsp->MaxWriteSize); |
@@ -418,44 +424,22 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
418 | 424 | ||
419 | security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, | 425 | security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, |
420 | &rsp->hdr); | 426 | &rsp->hdr); |
421 | if (blob_length == 0) { | 427 | /* |
422 | cifs_dbg(VFS, "missing security blob on negprot\n"); | 428 | * See MS-SMB2 section 2.2.4: if no blob, client picks default which |
423 | rc = -EIO; | 429 | * for us will be |
424 | goto neg_exit; | 430 | * ses->sectype = RawNTLMSSP; |
425 | } | 431 | * but for time being this is our only auth choice so doesn't matter. |
426 | 432 | * We just found a server which sets blob length to zero expecting raw. | |
427 | cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags); | 433 | */ |
428 | if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { | 434 | if (blob_length == 0) |
429 | cifs_dbg(FYI, "Signing required\n"); | 435 | cifs_dbg(FYI, "missing security blob on negprot\n"); |
430 | if (!(server->sec_mode & (SMB2_NEGOTIATE_SIGNING_REQUIRED | | ||
431 | SMB2_NEGOTIATE_SIGNING_ENABLED))) { | ||
432 | cifs_dbg(VFS, "signing required but server lacks support\n"); | ||
433 | rc = -EOPNOTSUPP; | ||
434 | goto neg_exit; | ||
435 | } | ||
436 | server->sec_mode |= SECMODE_SIGN_REQUIRED; | ||
437 | } else if (sec_flags & CIFSSEC_MAY_SIGN) { | ||
438 | cifs_dbg(FYI, "Signing optional\n"); | ||
439 | if (server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { | ||
440 | cifs_dbg(FYI, "Server requires signing\n"); | ||
441 | server->sec_mode |= SECMODE_SIGN_REQUIRED; | ||
442 | } else { | ||
443 | server->sec_mode &= | ||
444 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
445 | } | ||
446 | } else { | ||
447 | cifs_dbg(FYI, "Signing disabled\n"); | ||
448 | if (server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { | ||
449 | cifs_dbg(VFS, "Server requires packet signing to be enabled in /proc/fs/cifs/SecurityFlags\n"); | ||
450 | rc = -EOPNOTSUPP; | ||
451 | goto neg_exit; | ||
452 | } | ||
453 | server->sec_mode &= | ||
454 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
455 | } | ||
456 | 436 | ||
437 | rc = cifs_enable_signing(server, ses->sign); | ||
457 | #ifdef CONFIG_SMB2_ASN1 /* BB REMOVEME when updated asn1.c ready */ | 438 | #ifdef CONFIG_SMB2_ASN1 /* BB REMOVEME when updated asn1.c ready */ |
458 | rc = decode_neg_token_init(security_blob, blob_length, | 439 | if (rc) |
440 | goto neg_exit; | ||
441 | if (blob_length) | ||
442 | rc = decode_neg_token_init(security_blob, blob_length, | ||
459 | &server->sec_type); | 443 | &server->sec_type); |
460 | if (rc == 1) | 444 | if (rc == 1) |
461 | rc = 0; | 445 | rc = 0; |
@@ -480,9 +464,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
480 | int rc = 0; | 464 | int rc = 0; |
481 | int resp_buftype; | 465 | int resp_buftype; |
482 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ | 466 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ |
483 | struct TCP_Server_Info *server; | 467 | struct TCP_Server_Info *server = ses->server; |
484 | unsigned int sec_flags; | ||
485 | u8 temp = 0; | ||
486 | u16 blob_length = 0; | 468 | u16 blob_length = 0; |
487 | char *security_blob; | 469 | char *security_blob; |
488 | char *ntlmssp_blob = NULL; | 470 | char *ntlmssp_blob = NULL; |
@@ -490,11 +472,9 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
490 | 472 | ||
491 | cifs_dbg(FYI, "Session Setup\n"); | 473 | cifs_dbg(FYI, "Session Setup\n"); |
492 | 474 | ||
493 | if (ses->server) | 475 | if (!server) { |
494 | server = ses->server; | 476 | WARN(1, "%s: server is NULL!\n", __func__); |
495 | else { | 477 | return -EIO; |
496 | rc = -EIO; | ||
497 | return rc; | ||
498 | } | 478 | } |
499 | 479 | ||
500 | /* | 480 | /* |
@@ -505,7 +485,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
505 | if (!ses->ntlmssp) | 485 | if (!ses->ntlmssp) |
506 | return -ENOMEM; | 486 | return -ENOMEM; |
507 | 487 | ||
508 | ses->server->secType = RawNTLMSSP; | 488 | /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */ |
489 | ses->sectype = RawNTLMSSP; | ||
509 | 490 | ||
510 | ssetup_ntlmssp_authenticate: | 491 | ssetup_ntlmssp_authenticate: |
511 | if (phase == NtLmChallenge) | 492 | if (phase == NtLmChallenge) |
@@ -515,28 +496,19 @@ ssetup_ntlmssp_authenticate: | |||
515 | if (rc) | 496 | if (rc) |
516 | return rc; | 497 | return rc; |
517 | 498 | ||
518 | /* if any of auth flags (ie not sign or seal) are overriden use them */ | ||
519 | if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
520 | sec_flags = ses->overrideSecFlg; /* BB FIXME fix sign flags?*/ | ||
521 | else /* if override flags set only sign/seal OR them with global auth */ | ||
522 | sec_flags = global_secflags | ses->overrideSecFlg; | ||
523 | |||
524 | cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags); | ||
525 | |||
526 | req->hdr.SessionId = 0; /* First session, not a reauthenticate */ | 499 | req->hdr.SessionId = 0; /* First session, not a reauthenticate */ |
527 | req->VcNumber = 0; /* MBZ */ | 500 | req->VcNumber = 0; /* MBZ */ |
528 | /* to enable echos and oplocks */ | 501 | /* to enable echos and oplocks */ |
529 | req->hdr.CreditRequest = cpu_to_le16(3); | 502 | req->hdr.CreditRequest = cpu_to_le16(3); |
530 | 503 | ||
531 | /* only one of SMB2 signing flags may be set in SMB2 request */ | 504 | /* only one of SMB2 signing flags may be set in SMB2 request */ |
532 | if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) | 505 | if (server->sign) |
533 | temp = SMB2_NEGOTIATE_SIGNING_REQUIRED; | 506 | req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED; |
534 | else if (ses->server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) | 507 | else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */ |
535 | temp = SMB2_NEGOTIATE_SIGNING_REQUIRED; | 508 | req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED; |
536 | else if (sec_flags & CIFSSEC_MAY_SIGN) /* MAY_SIGN is a single flag */ | 509 | else |
537 | temp = SMB2_NEGOTIATE_SIGNING_ENABLED; | 510 | req->SecurityMode = 0; |
538 | 511 | ||
539 | req->SecurityMode = temp; | ||
540 | req->Capabilities = 0; | 512 | req->Capabilities = 0; |
541 | req->Channel = 0; /* MBZ */ | 513 | req->Channel = 0; /* MBZ */ |
542 | 514 | ||
@@ -679,7 +651,7 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) | |||
679 | 651 | ||
680 | /* since no tcon, smb2_init can not do this, so do here */ | 652 | /* since no tcon, smb2_init can not do this, so do here */ |
681 | req->hdr.SessionId = ses->Suid; | 653 | req->hdr.SessionId = ses->Suid; |
682 | if (server->sec_mode & SECMODE_SIGN_REQUIRED) | 654 | if (server->sign) |
683 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; | 655 | req->hdr.Flags |= SMB2_FLAGS_SIGNED; |
684 | 656 | ||
685 | rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0); | 657 | rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0); |
@@ -788,11 +760,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
788 | } | 760 | } |
789 | 761 | ||
790 | tcon->share_flags = le32_to_cpu(rsp->ShareFlags); | 762 | tcon->share_flags = le32_to_cpu(rsp->ShareFlags); |
763 | tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */ | ||
791 | tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); | 764 | tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); |
792 | tcon->tidStatus = CifsGood; | 765 | tcon->tidStatus = CifsGood; |
793 | tcon->need_reconnect = false; | 766 | tcon->need_reconnect = false; |
794 | tcon->tid = rsp->hdr.TreeId; | 767 | tcon->tid = rsp->hdr.TreeId; |
795 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 768 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
796 | 769 | ||
797 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && | 770 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && |
798 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) | 771 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
@@ -1036,6 +1009,122 @@ creat_exit: | |||
1036 | return rc; | 1009 | return rc; |
1037 | } | 1010 | } |
1038 | 1011 | ||
1012 | /* | ||
1013 | * SMB2 IOCTL is used for both IOCTLs and FSCTLs | ||
1014 | */ | ||
1015 | int | ||
1016 | SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | ||
1017 | u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, | ||
1018 | u32 indatalen, char **out_data, u32 *plen /* returned data len */) | ||
1019 | { | ||
1020 | struct smb2_ioctl_req *req; | ||
1021 | struct smb2_ioctl_rsp *rsp; | ||
1022 | struct TCP_Server_Info *server; | ||
1023 | struct cifs_ses *ses = tcon->ses; | ||
1024 | struct kvec iov[2]; | ||
1025 | int resp_buftype; | ||
1026 | int num_iovecs; | ||
1027 | int rc = 0; | ||
1028 | |||
1029 | cifs_dbg(FYI, "SMB2 IOCTL\n"); | ||
1030 | |||
1031 | /* zero out returned data len, in case of error */ | ||
1032 | if (plen) | ||
1033 | *plen = 0; | ||
1034 | |||
1035 | if (ses && (ses->server)) | ||
1036 | server = ses->server; | ||
1037 | else | ||
1038 | return -EIO; | ||
1039 | |||
1040 | rc = small_smb2_init(SMB2_IOCTL, tcon, (void **) &req); | ||
1041 | if (rc) | ||
1042 | return rc; | ||
1043 | |||
1044 | req->CtlCode = cpu_to_le32(opcode); | ||
1045 | req->PersistentFileId = persistent_fid; | ||
1046 | req->VolatileFileId = volatile_fid; | ||
1047 | |||
1048 | if (indatalen) { | ||
1049 | req->InputCount = cpu_to_le32(indatalen); | ||
1050 | /* do not set InputOffset if no input data */ | ||
1051 | req->InputOffset = | ||
1052 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer) - 4); | ||
1053 | iov[1].iov_base = in_data; | ||
1054 | iov[1].iov_len = indatalen; | ||
1055 | num_iovecs = 2; | ||
1056 | } else | ||
1057 | num_iovecs = 1; | ||
1058 | |||
1059 | req->OutputOffset = 0; | ||
1060 | req->OutputCount = 0; /* MBZ */ | ||
1061 | |||
1062 | /* | ||
1063 | * Could increase MaxOutputResponse, but that would require more | ||
1064 | * than one credit. Windows typically sets this smaller, but for some | ||
1065 | * ioctls it may be useful to allow server to send more. No point | ||
1066 | * limiting what the server can send as long as fits in one credit | ||
1067 | */ | ||
1068 | req->MaxOutputResponse = cpu_to_le32(0xFF00); /* < 64K uses 1 credit */ | ||
1069 | |||
1070 | if (is_fsctl) | ||
1071 | req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); | ||
1072 | else | ||
1073 | req->Flags = 0; | ||
1074 | |||
1075 | iov[0].iov_base = (char *)req; | ||
1076 | /* 4 for rfc1002 length field */ | ||
1077 | iov[0].iov_len = get_rfc1002_length(req) + 4; | ||
1078 | |||
1079 | if (indatalen) | ||
1080 | inc_rfc1001_len(req, indatalen); | ||
1081 | |||
1082 | rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); | ||
1083 | rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base; | ||
1084 | |||
1085 | if (rc != 0) { | ||
1086 | if (tcon) | ||
1087 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); | ||
1088 | goto ioctl_exit; | ||
1089 | } | ||
1090 | |||
1091 | /* check if caller wants to look at return data or just return rc */ | ||
1092 | if ((plen == NULL) || (out_data == NULL)) | ||
1093 | goto ioctl_exit; | ||
1094 | |||
1095 | *plen = le32_to_cpu(rsp->OutputCount); | ||
1096 | |||
1097 | /* We check for obvious errors in the output buffer length and offset */ | ||
1098 | if (*plen == 0) | ||
1099 | goto ioctl_exit; /* server returned no data */ | ||
1100 | else if (*plen > 0xFF00) { | ||
1101 | cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); | ||
1102 | *plen = 0; | ||
1103 | rc = -EIO; | ||
1104 | goto ioctl_exit; | ||
1105 | } | ||
1106 | |||
1107 | if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) { | ||
1108 | cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, | ||
1109 | le32_to_cpu(rsp->OutputOffset)); | ||
1110 | *plen = 0; | ||
1111 | rc = -EIO; | ||
1112 | goto ioctl_exit; | ||
1113 | } | ||
1114 | |||
1115 | *out_data = kmalloc(*plen, GFP_KERNEL); | ||
1116 | if (*out_data == NULL) { | ||
1117 | rc = -ENOMEM; | ||
1118 | goto ioctl_exit; | ||
1119 | } | ||
1120 | |||
1121 | memcpy(*out_data, rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), | ||
1122 | *plen); | ||
1123 | ioctl_exit: | ||
1124 | free_rsp_buf(resp_buftype, rsp); | ||
1125 | return rc; | ||
1126 | } | ||
1127 | |||
1039 | int | 1128 | int |
1040 | SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | 1129 | SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, |
1041 | u64 persistent_fid, u64 volatile_fid) | 1130 | u64 persistent_fid, u64 volatile_fid) |
@@ -1384,8 +1473,7 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
1384 | case MID_RESPONSE_RECEIVED: | 1473 | case MID_RESPONSE_RECEIVED: |
1385 | credits_received = le16_to_cpu(buf->CreditRequest); | 1474 | credits_received = le16_to_cpu(buf->CreditRequest); |
1386 | /* result already set, check signature */ | 1475 | /* result already set, check signature */ |
1387 | if (server->sec_mode & | 1476 | if (server->sign) { |
1388 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
1389 | int rc; | 1477 | int rc; |
1390 | 1478 | ||
1391 | rc = smb2_verify_signature(&rqst, server); | 1479 | rc = smb2_verify_signature(&rqst, server); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 4cb4ced258cb..f31043b26bd3 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/smb2pdu.h | 2 | * fs/cifs/smb2pdu.h |
3 | * | 3 | * |
4 | * Copyright (c) International Business Machines Corp., 2009, 2010 | 4 | * Copyright (c) International Business Machines Corp., 2009, 2013 |
5 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
6 | * Author(s): Steve French (sfrench@us.ibm.com) | 6 | * Author(s): Steve French (sfrench@us.ibm.com) |
7 | * Pavel Shilovsky (pshilovsky@samba.org) 2012 | 7 | * Pavel Shilovsky (pshilovsky@samba.org) 2012 |
@@ -170,6 +170,7 @@ struct smb2_negotiate_req { | |||
170 | #define SMB20_PROT_ID 0x0202 | 170 | #define SMB20_PROT_ID 0x0202 |
171 | #define SMB21_PROT_ID 0x0210 | 171 | #define SMB21_PROT_ID 0x0210 |
172 | #define SMB30_PROT_ID 0x0300 | 172 | #define SMB30_PROT_ID 0x0300 |
173 | #define SMB302_PROT_ID 0x0302 | ||
173 | #define BAD_PROT_ID 0xFFFF | 174 | #define BAD_PROT_ID 0xFFFF |
174 | 175 | ||
175 | /* SecurityMode flags */ | 176 | /* SecurityMode flags */ |
@@ -283,10 +284,17 @@ struct smb2_tree_connect_rsp { | |||
283 | #define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400 | 284 | #define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400 |
284 | #define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800 | 285 | #define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800 |
285 | #define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000 | 286 | #define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000 |
286 | #define SHI1005_FLAGS_ENABLE_HASH 0x00002000 | 287 | #define SHI1005_FLAGS_ENABLE_HASH_V1 0x00002000 |
288 | #define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000 | ||
289 | #define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000 | ||
290 | #define SHI1005_FLAGS_ALL 0x0000FF33 | ||
287 | 291 | ||
288 | /* Possible share capabilities */ | 292 | /* Possible share capabilities */ |
289 | #define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) | 293 | #define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */ |
294 | #define SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY cpu_to_le32(0x00000010) /* 3.0 */ | ||
295 | #define SMB2_SHARE_CAP_SCALEOUT cpu_to_le32(0x00000020) /* 3.0 */ | ||
296 | #define SMB2_SHARE_CAP_CLUSTER cpu_to_le32(0x00000040) /* 3.0 */ | ||
297 | #define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */ | ||
290 | 298 | ||
291 | struct smb2_tree_disconnect_req { | 299 | struct smb2_tree_disconnect_req { |
292 | struct smb2_hdr hdr; | 300 | struct smb2_hdr hdr; |
@@ -477,6 +485,75 @@ struct create_lease { | |||
477 | struct lease_context lcontext; | 485 | struct lease_context lcontext; |
478 | } __packed; | 486 | } __packed; |
479 | 487 | ||
488 | /* this goes in the ioctl buffer when doing a copychunk request */ | ||
489 | struct copychunk_ioctl { | ||
490 | char SourceKey[24]; | ||
491 | __le32 ChunkCount; /* we are only sending 1 */ | ||
492 | __le32 Reserved; | ||
493 | /* array will only be one chunk long for us */ | ||
494 | __le64 SourceOffset; | ||
495 | __le64 TargetOffset; | ||
496 | __le32 Length; /* how many bytes to copy */ | ||
497 | __u32 Reserved2; | ||
498 | } __packed; | ||
499 | |||
500 | /* Response and Request are the same format */ | ||
501 | struct validate_negotiate_info { | ||
502 | __le32 Capabilities; | ||
503 | __u8 Guid[SMB2_CLIENT_GUID_SIZE]; | ||
504 | __le16 SecurityMode; | ||
505 | __le16 DialectCount; | ||
506 | __le16 Dialect[1]; | ||
507 | } __packed; | ||
508 | |||
509 | #define RSS_CAPABLE 0x00000001 | ||
510 | #define RDMA_CAPABLE 0x00000002 | ||
511 | |||
512 | struct network_interface_info_ioctl_rsp { | ||
513 | __le32 Next; /* next interface. zero if this is last one */ | ||
514 | __le32 IfIndex; | ||
515 | __le32 Capability; /* RSS or RDMA Capable */ | ||
516 | __le32 Reserved; | ||
517 | __le64 LinkSpeed; | ||
518 | char SockAddr_Storage[128]; | ||
519 | } __packed; | ||
520 | |||
521 | #define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */ | ||
522 | |||
523 | struct smb2_ioctl_req { | ||
524 | struct smb2_hdr hdr; | ||
525 | __le16 StructureSize; /* Must be 57 */ | ||
526 | __u16 Reserved; | ||
527 | __le32 CtlCode; | ||
528 | __u64 PersistentFileId; /* opaque endianness */ | ||
529 | __u64 VolatileFileId; /* opaque endianness */ | ||
530 | __le32 InputOffset; | ||
531 | __le32 InputCount; | ||
532 | __le32 MaxInputResponse; | ||
533 | __le32 OutputOffset; | ||
534 | __le32 OutputCount; | ||
535 | __le32 MaxOutputResponse; | ||
536 | __le32 Flags; | ||
537 | __u32 Reserved2; | ||
538 | char Buffer[0]; | ||
539 | } __packed; | ||
540 | |||
541 | struct smb2_ioctl_rsp { | ||
542 | struct smb2_hdr hdr; | ||
543 | __le16 StructureSize; /* Must be 57 */ | ||
544 | __u16 Reserved; | ||
545 | __le32 CtlCode; | ||
546 | __u64 PersistentFileId; /* opaque endianness */ | ||
547 | __u64 VolatileFileId; /* opaque endianness */ | ||
548 | __le32 InputOffset; | ||
549 | __le32 InputCount; | ||
550 | __le32 OutputOffset; | ||
551 | __le32 OutputCount; | ||
552 | __le32 Flags; | ||
553 | __u32 Reserved2; | ||
554 | /* char * buffer[] */ | ||
555 | } __packed; | ||
556 | |||
480 | /* Currently defined values for close flags */ | 557 | /* Currently defined values for close flags */ |
481 | #define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001) | 558 | #define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001) |
482 | struct smb2_close_req { | 559 | struct smb2_close_req { |
@@ -517,17 +594,25 @@ struct smb2_flush_rsp { | |||
517 | __le16 Reserved; | 594 | __le16 Reserved; |
518 | } __packed; | 595 | } __packed; |
519 | 596 | ||
597 | /* For read request Flags field below, following flag is defined for SMB3.02 */ | ||
598 | #define SMB2_READFLAG_READ_UNBUFFERED 0x01 | ||
599 | |||
600 | /* Channel field for read and write: exactly one of following flags can be set*/ | ||
601 | #define SMB2_CHANNEL_NONE 0x00000000 | ||
602 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ | ||
603 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ | ||
604 | |||
520 | struct smb2_read_req { | 605 | struct smb2_read_req { |
521 | struct smb2_hdr hdr; | 606 | struct smb2_hdr hdr; |
522 | __le16 StructureSize; /* Must be 49 */ | 607 | __le16 StructureSize; /* Must be 49 */ |
523 | __u8 Padding; /* offset from start of SMB2 header to place read */ | 608 | __u8 Padding; /* offset from start of SMB2 header to place read */ |
524 | __u8 Reserved; | 609 | __u8 Flags; /* MBZ unless SMB3.02 or later */ |
525 | __le32 Length; | 610 | __le32 Length; |
526 | __le64 Offset; | 611 | __le64 Offset; |
527 | __u64 PersistentFileId; /* opaque endianness */ | 612 | __u64 PersistentFileId; /* opaque endianness */ |
528 | __u64 VolatileFileId; /* opaque endianness */ | 613 | __u64 VolatileFileId; /* opaque endianness */ |
529 | __le32 MinimumCount; | 614 | __le32 MinimumCount; |
530 | __le32 Channel; /* Reserved MBZ */ | 615 | __le32 Channel; /* MBZ except for SMB3 or later */ |
531 | __le32 RemainingBytes; | 616 | __le32 RemainingBytes; |
532 | __le16 ReadChannelInfoOffset; /* Reserved MBZ */ | 617 | __le16 ReadChannelInfoOffset; /* Reserved MBZ */ |
533 | __le16 ReadChannelInfoLength; /* Reserved MBZ */ | 618 | __le16 ReadChannelInfoLength; /* Reserved MBZ */ |
@@ -545,8 +630,9 @@ struct smb2_read_rsp { | |||
545 | __u8 Buffer[1]; | 630 | __u8 Buffer[1]; |
546 | } __packed; | 631 | } __packed; |
547 | 632 | ||
548 | /* For write request Flags field below the following flag is defined: */ | 633 | /* For write request Flags field below the following flags are defined: */ |
549 | #define SMB2_WRITEFLAG_WRITE_THROUGH 0x00000001 | 634 | #define SMB2_WRITEFLAG_WRITE_THROUGH 0x00000001 /* SMB2.1 or later */ |
635 | #define SMB2_WRITEFLAG_WRITE_UNBUFFERED 0x00000002 /* SMB3.02 or later */ | ||
550 | 636 | ||
551 | struct smb2_write_req { | 637 | struct smb2_write_req { |
552 | struct smb2_hdr hdr; | 638 | struct smb2_hdr hdr; |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 2aa3535e38ce..d4e1eb807457 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -111,6 +111,10 @@ extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, | |||
111 | __u32 desired_access, __u32 create_disposition, | 111 | __u32 desired_access, __u32 create_disposition, |
112 | __u32 file_attributes, __u32 create_options, | 112 | __u32 file_attributes, __u32 create_options, |
113 | __u8 *oplock, struct smb2_file_all_info *buf); | 113 | __u8 *oplock, struct smb2_file_all_info *buf); |
114 | extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, | ||
115 | u64 persistent_fid, u64 volatile_fid, u32 opcode, | ||
116 | bool is_fsctl, char *in_data, u32 indatalen, | ||
117 | char **out_data, u32 *plen /* returned data len */); | ||
114 | extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | 118 | extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, |
115 | u64 persistent_file_id, u64 volatile_file_id); | 119 | u64 persistent_file_id, u64 volatile_file_id); |
116 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, | 120 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 01f0ac800780..09b4fbaadeb6 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -116,11 +116,155 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
116 | return rc; | 116 | return rc; |
117 | } | 117 | } |
118 | 118 | ||
119 | void | ||
120 | generate_smb3signingkey(struct TCP_Server_Info *server) | ||
121 | { | ||
122 | unsigned char zero = 0x0; | ||
123 | __u8 i[4] = {0, 0, 0, 1}; | ||
124 | __u8 L[4] = {0, 0, 0, 128}; | ||
125 | int rc = 0; | ||
126 | unsigned char prfhash[SMB2_HMACSHA256_SIZE]; | ||
127 | unsigned char *hashptr = prfhash; | ||
128 | |||
129 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); | ||
130 | memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); | ||
131 | |||
132 | rc = crypto_shash_setkey(server->secmech.hmacsha256, | ||
133 | server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); | ||
134 | if (rc) { | ||
135 | cifs_dbg(VFS, "%s: Could not set with session key\n", __func__); | ||
136 | goto smb3signkey_ret; | ||
137 | } | ||
138 | |||
139 | rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); | ||
140 | if (rc) { | ||
141 | cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__); | ||
142 | goto smb3signkey_ret; | ||
143 | } | ||
144 | |||
145 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | ||
146 | i, 4); | ||
147 | if (rc) { | ||
148 | cifs_dbg(VFS, "%s: Could not update with n\n", __func__); | ||
149 | goto smb3signkey_ret; | ||
150 | } | ||
151 | |||
152 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | ||
153 | "SMB2AESCMAC", 12); | ||
154 | if (rc) { | ||
155 | cifs_dbg(VFS, "%s: Could not update with label\n", __func__); | ||
156 | goto smb3signkey_ret; | ||
157 | } | ||
158 | |||
159 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | ||
160 | &zero, 1); | ||
161 | if (rc) { | ||
162 | cifs_dbg(VFS, "%s: Could not update with zero\n", __func__); | ||
163 | goto smb3signkey_ret; | ||
164 | } | ||
165 | |||
166 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | ||
167 | "SmbSign", 8); | ||
168 | if (rc) { | ||
169 | cifs_dbg(VFS, "%s: Could not update with context\n", __func__); | ||
170 | goto smb3signkey_ret; | ||
171 | } | ||
172 | |||
173 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, | ||
174 | L, 4); | ||
175 | if (rc) { | ||
176 | cifs_dbg(VFS, "%s: Could not update with L\n", __func__); | ||
177 | goto smb3signkey_ret; | ||
178 | } | ||
179 | |||
180 | rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, | ||
181 | hashptr); | ||
182 | if (rc) { | ||
183 | cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); | ||
184 | goto smb3signkey_ret; | ||
185 | } | ||
186 | |||
187 | memcpy(server->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE); | ||
188 | |||
189 | smb3signkey_ret: | ||
190 | return; | ||
191 | } | ||
192 | |||
119 | int | 193 | int |
120 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 194 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
121 | { | 195 | { |
122 | cifs_dbg(FYI, "smb3 signatures not supported yet\n"); | 196 | int i, rc; |
123 | return -EOPNOTSUPP; | 197 | unsigned char smb3_signature[SMB2_CMACAES_SIZE]; |
198 | unsigned char *sigptr = smb3_signature; | ||
199 | struct kvec *iov = rqst->rq_iov; | ||
200 | int n_vec = rqst->rq_nvec; | ||
201 | struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; | ||
202 | |||
203 | memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); | ||
204 | memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); | ||
205 | |||
206 | rc = crypto_shash_setkey(server->secmech.cmacaes, | ||
207 | server->smb3signingkey, SMB2_CMACAES_SIZE); | ||
208 | if (rc) { | ||
209 | cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); | ||
210 | return rc; | ||
211 | } | ||
212 | |||
213 | rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash); | ||
214 | if (rc) { | ||
215 | cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); | ||
216 | return rc; | ||
217 | } | ||
218 | |||
219 | for (i = 0; i < n_vec; i++) { | ||
220 | if (iov[i].iov_len == 0) | ||
221 | continue; | ||
222 | if (iov[i].iov_base == NULL) { | ||
223 | cifs_dbg(VFS, "null iovec entry"); | ||
224 | return -EIO; | ||
225 | } | ||
226 | /* | ||
227 | * The first entry includes a length field (which does not get | ||
228 | * signed that occupies the first 4 bytes before the header). | ||
229 | */ | ||
230 | if (i == 0) { | ||
231 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ | ||
232 | break; /* nothing to sign or corrupt header */ | ||
233 | rc = | ||
234 | crypto_shash_update( | ||
235 | &server->secmech.sdesccmacaes->shash, | ||
236 | iov[i].iov_base + 4, iov[i].iov_len - 4); | ||
237 | } else { | ||
238 | rc = | ||
239 | crypto_shash_update( | ||
240 | &server->secmech.sdesccmacaes->shash, | ||
241 | iov[i].iov_base, iov[i].iov_len); | ||
242 | } | ||
243 | if (rc) { | ||
244 | cifs_dbg(VFS, "%s: Couldn't update cmac aes with payload\n", | ||
245 | __func__); | ||
246 | return rc; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | /* now hash over the rq_pages array */ | ||
251 | for (i = 0; i < rqst->rq_npages; i++) { | ||
252 | struct kvec p_iov; | ||
253 | |||
254 | cifs_rqst_page_to_kvec(rqst, i, &p_iov); | ||
255 | crypto_shash_update(&server->secmech.sdesccmacaes->shash, | ||
256 | p_iov.iov_base, p_iov.iov_len); | ||
257 | kunmap(rqst->rq_pages[i]); | ||
258 | } | ||
259 | |||
260 | rc = crypto_shash_final(&server->secmech.sdesccmacaes->shash, | ||
261 | sigptr); | ||
262 | if (rc) | ||
263 | cifs_dbg(VFS, "%s: Could not generate cmac aes\n", __func__); | ||
264 | |||
265 | memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | ||
266 | |||
267 | return rc; | ||
124 | } | 268 | } |
125 | 269 | ||
126 | /* must be called with server->srv_mutex held */ | 270 | /* must be called with server->srv_mutex held */ |
@@ -275,8 +419,7 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
275 | 419 | ||
276 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); | 420 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); |
277 | /* convert the length into a more usable form */ | 421 | /* convert the length into a more usable form */ |
278 | if ((len > 24) && | 422 | if (len > 24 && server->sign) { |
279 | (server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) { | ||
280 | int rc; | 423 | int rc; |
281 | 424 | ||
282 | rc = smb2_verify_signature(&rqst, server); | 425 | rc = smb2_verify_signature(&rqst, server); |
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h index 7056b891e087..d952ee48f4dc 100644 --- a/fs/cifs/smbfsctl.h +++ b/fs/cifs/smbfsctl.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions | 2 | * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions |
3 | * | 3 | * |
4 | * Copyright (c) International Business Machines Corp., 2002,2009 | 4 | * Copyright (c) International Business Machines Corp., 2002,2013 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -22,7 +22,7 @@ | |||
22 | /* IOCTL information */ | 22 | /* IOCTL information */ |
23 | /* | 23 | /* |
24 | * List of ioctl/fsctl function codes that are or could be useful in the | 24 | * List of ioctl/fsctl function codes that are or could be useful in the |
25 | * future to remote clients like cifs or SMB2 client. There is probably | 25 | * future to remote clients like cifs or SMB2/SMB3 client. This is probably |
26 | * a slightly larger set of fsctls that NTFS local filesystem could handle, | 26 | * a slightly larger set of fsctls that NTFS local filesystem could handle, |
27 | * including the seven below that we do not have struct definitions for. | 27 | * including the seven below that we do not have struct definitions for. |
28 | * Even with protocol definitions for most of these now available, we still | 28 | * Even with protocol definitions for most of these now available, we still |
@@ -30,7 +30,13 @@ | |||
30 | * remotely. Some of the following, such as the encryption/compression ones | 30 | * remotely. Some of the following, such as the encryption/compression ones |
31 | * could be invoked from tools via a specialized hook into the VFS rather | 31 | * could be invoked from tools via a specialized hook into the VFS rather |
32 | * than via the standard vfs entry points | 32 | * than via the standard vfs entry points |
33 | * | ||
34 | * See MS-SMB2 Section 2.2.31 (last checked June 2013, all of that list are | ||
35 | * below). Additional detail on less common ones can be found in MS-FSCC | ||
36 | * section 2.3. | ||
33 | */ | 37 | */ |
38 | #define FSCTL_DFS_GET_REFERRALS 0x00060194 | ||
39 | #define FSCTL_DFS_GET_REFERRALS_EX 0x000601B0 | ||
34 | #define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 | 40 | #define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 |
35 | #define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 | 41 | #define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 |
36 | #define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 | 42 | #define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 |
@@ -71,14 +77,31 @@ | |||
71 | #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ | 77 | #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ |
72 | #define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */ | 78 | #define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */ |
73 | #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ | 79 | #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ |
80 | #define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */ | ||
74 | #define FSCTL_SIS_LINK_FILES 0x0009C104 | 81 | #define FSCTL_SIS_LINK_FILES 0x0009C104 |
75 | #define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */ | 82 | #define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */ |
76 | #define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */ | 83 | #define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */ |
77 | /* strange that the number for this op is not sequential with previous op */ | 84 | /* strange that the number for this op is not sequential with previous op */ |
78 | #define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */ | 85 | #define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */ |
86 | /* Enumerate previous versions of a file */ | ||
87 | #define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064 | ||
88 | /* Retrieve an opaque file reference for server-side data movement ie copy */ | ||
89 | #define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078 | ||
90 | #define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4 /* BB add struct */ | ||
79 | #define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */ | 91 | #define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */ |
80 | #define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */ | 92 | #define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */ |
93 | #define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204 /* BB add struct */ | ||
94 | /* Perform server-side data movement */ | ||
95 | #define FSCTL_SRV_COPYCHUNK 0x001440F2 | ||
96 | #define FSCTL_SRV_COPYCHUNK_WRITE 0x001480F2 | ||
97 | #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */ | ||
98 | #define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */ | ||
81 | 99 | ||
82 | #define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 | 100 | #define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 |
83 | #define IO_REPARSE_TAG_HSM 0xC0000004 | 101 | #define IO_REPARSE_TAG_HSM 0xC0000004 |
84 | #define IO_REPARSE_TAG_SIS 0x80000007 | 102 | #define IO_REPARSE_TAG_SIS 0x80000007 |
103 | |||
104 | /* fsctl flags */ | ||
105 | /* If Flags is set to this value, the request is an FSCTL not ioctl request */ | ||
106 | #define SMB2_0_IOCTL_IS_FSCTL 0x00000001 | ||
107 | |||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index bfbf4700d160..1996d6ceb833 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -463,7 +463,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) | |||
463 | struct mid_q_entry *mid; | 463 | struct mid_q_entry *mid; |
464 | 464 | ||
465 | /* enable signing if server requires it */ | 465 | /* enable signing if server requires it */ |
466 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 466 | if (server->sign) |
467 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 467 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
468 | 468 | ||
469 | mid = AllocMidQEntry(hdr, server); | 469 | mid = AllocMidQEntry(hdr, server); |
@@ -612,7 +612,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
612 | dump_smb(mid->resp_buf, min_t(u32, 92, len)); | 612 | dump_smb(mid->resp_buf, min_t(u32, 92, len)); |
613 | 613 | ||
614 | /* convert the length into a more usable form */ | 614 | /* convert the length into a more usable form */ |
615 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 615 | if (server->sign) { |
616 | struct kvec iov; | 616 | struct kvec iov; |
617 | int rc = 0; | 617 | int rc = 0; |
618 | struct smb_rqst rqst = { .rq_iov = &iov, | 618 | struct smb_rqst rqst = { .rq_iov = &iov, |