aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig40
-rw-r--r--fs/cifs/CHANGES14
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README32
-rw-r--r--fs/cifs/asn1.c10
-rw-r--r--fs/cifs/cifs_debug.c134
-rw-r--r--fs/cifs/cifs_debug.h4
-rw-r--r--fs/cifs/cifs_unicode.c1
-rw-r--r--fs/cifs/cifsencrypt.c106
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsfs.h3
-rw-r--r--fs/cifs/cifsglob.h70
-rw-r--r--fs/cifs/cifspdu.h98
-rw-r--r--fs/cifs/cifsproto.h6
-rw-r--r--fs/cifs/cifssmb.c271
-rw-r--r--fs/cifs/connect.c86
-rw-r--r--fs/cifs/dir.c15
-rw-r--r--fs/cifs/fcntl.c4
-rw-r--r--fs/cifs/file.c43
-rw-r--r--fs/cifs/inode.c39
-rw-r--r--fs/cifs/link.c7
-rw-r--r--fs/cifs/misc.c10
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/ntlmssp.c143
-rw-r--r--fs/cifs/readdir.c184
-rw-r--r--fs/cifs/sess.c528
-rw-r--r--fs/cifs/smbencrypt.c1
-rw-r--r--fs/cifs/transport.c3
28 files changed, 1419 insertions, 443 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index f9b5842c8d2d..d49b2a8c0be6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1663,7 +1663,7 @@ config CIFS_STATS
1663 mounted by the cifs client to be displayed in /proc/fs/cifs/Stats 1663 mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
1664 1664
1665config CIFS_STATS2 1665config CIFS_STATS2
1666 bool "CIFS extended statistics" 1666 bool "Extended statistics"
1667 depends on CIFS_STATS 1667 depends on CIFS_STATS
1668 help 1668 help
1669 Enabling this option will allow more detailed statistics on SMB 1669 Enabling this option will allow more detailed statistics on SMB
@@ -1676,6 +1676,32 @@ config CIFS_STATS2
1676 Unless you are a developer or are doing network performance analysis 1676 Unless you are a developer or are doing network performance analysis
1677 or tuning, say N. 1677 or tuning, say N.
1678 1678
1679config CIFS_WEAK_PW_HASH
1680 bool "Support legacy servers which use weaker LANMAN security"
1681 depends on CIFS
1682 help
1683 Modern CIFS servers including Samba and most Windows versions
1684 (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
1685 security mechanisms. These hash the password more securely
1686 than the mechanisms used in the older LANMAN version of the
1687 SMB protocol needed to establish sessions with old SMB servers.
1688
1689 Enabling this option allows the cifs module to mount to older
1690 LANMAN based servers such as OS/2 and Windows 95, but such
1691 mounts may be less secure than mounts using NTLM or more recent
1692 security mechanisms if you are on a public network. Unless you
1693 have a need to access old SMB servers (and are on a private
1694 network) you probably want to say N. Even if this support
1695 is enabled in the kernel build, they will not be used
1696 automatically. At runtime LANMAN mounts are disabled but
1697 can be set to required (or optional) either in
1698 /proc/fs/cifs (see fs/cifs/README for more detail) or via an
1699 option on the mount command. This support is disabled by
1700 default in order to reduce the possibility of a downgrade
1701 attack.
1702
1703 If unsure, say N.
1704
1679config CIFS_XATTR 1705config CIFS_XATTR
1680 bool "CIFS extended attributes" 1706 bool "CIFS extended attributes"
1681 depends on CIFS 1707 depends on CIFS
@@ -1704,6 +1730,16 @@ config CIFS_POSIX
1704 (such as Samba 3.10 and later) which can negotiate 1730 (such as Samba 3.10 and later) which can negotiate
1705 CIFS POSIX ACL support. If unsure, say N. 1731 CIFS POSIX ACL support. If unsure, say N.
1706 1732
1733config CIFS_DEBUG2
1734 bool "Enable additional CIFS debugging routines"
1735 help
1736 Enabling this option adds a few more debugging routines
1737 to the cifs code which slightly increases the size of
1738 the cifs module and can cause additional logging of debug
1739 messages in some error paths, slowing performance. This
1740 option can be turned off unless you are debugging
1741 cifs problems. If unsure, say N.
1742
1707config CIFS_EXPERIMENTAL 1743config CIFS_EXPERIMENTAL
1708 bool "CIFS Experimental Features (EXPERIMENTAL)" 1744 bool "CIFS Experimental Features (EXPERIMENTAL)"
1709 depends on CIFS && EXPERIMENTAL 1745 depends on CIFS && EXPERIMENTAL
@@ -1719,7 +1755,7 @@ config CIFS_EXPERIMENTAL
1719 If unsure, say N. 1755 If unsure, say N.
1720 1756
1721config CIFS_UPCALL 1757config CIFS_UPCALL
1722 bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" 1758 bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
1723 depends on CIFS_EXPERIMENTAL 1759 depends on CIFS_EXPERIMENTAL
1724 select CONNECTOR 1760 select CONNECTOR
1725 help 1761 help
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 7271bb0257f6..7e0058bc3dd9 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,9 +1,21 @@
1Version 1.44
2------------
3Rewritten sessionsetup support, including support for legacy SMB
4session setup needed for OS/2 and older servers such as Windows 95 and 98.
5Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst
6so we can do search (ls etc.) to OS/2. Do not send NTCreateX
7or recent levels of FindFirst unless server says it supports NT SMBs
8(instead use legacy equivalents from LANMAN dialect).
9
1Version 1.43 10Version 1.43
2------------ 11------------
3POSIX locking to servers which support CIFS POSIX Extensions 12POSIX locking to servers which support CIFS POSIX Extensions
4(disabled by default controlled by proc/fs/cifs/Experimental). 13(disabled by default controlled by proc/fs/cifs/Experimental).
5Handle conversion of long share names (especially Asian languages) 14Handle conversion of long share names (especially Asian languages)
6to Unicode during mount. 15to Unicode during mount. Fix memory leak in sess struct on reconnect.
16Fix rare oops after acpi suspend. Fix O_TRUNC opens to overwrite on
17cifs open which helps rare case when setpathinfo fails or server does
18not support it.
7 19
8Version 1.42 20Version 1.42
9------------ 21------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 58c77254a23b..a26f26ed5a17 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
3# 3#
4obj-$(CONFIG_CIFS) += cifs.o 4obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o 6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o
diff --git a/fs/cifs/README b/fs/cifs/README
index 0355003f4f0a..a68f8e3db2d2 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -485,14 +485,34 @@ PacketSigningEnabled If set to one, cifs packet signing is enabled
485 it. If set to two, cifs packet signing is 485 it. If set to two, cifs packet signing is
486 required even if the server considers packet 486 required even if the server considers packet
487 signing optional. (default 1) 487 signing optional. (default 1)
488SecurityFlags Flags which control security negotiation and
489 also packet signing. Authentication (may/must)
490 flags (e.g. for NTLM and/or NTLMv2) may be combined with
491 the signing flags. Specifying two different password
492 hashing mechanisms (as "must use") on the other hand
493 does not make much sense. Default flags are
494 0x07007
495 (NTLM, NTLMv2 and packet signing allowed). Maximum
496 allowable flags if you want to allow mounts to servers
497 using weaker password hashes is 0x37037 (lanman,
498 plaintext, ntlm, ntlmv2, signing allowed):
499
500 may use packet signing 0x00001
501 must use packet signing 0x01001
502 may use NTLM (most common password hash) 0x00002
503 must use NTLM 0x02002
504 may use NTLMv2 0x00004
505 must use NTLMv2 0x04004
506 may use Kerberos security (not implemented yet) 0x00008
507 must use Kerberos (not implemented yet) 0x08008
508 may use lanman (weak) password hash 0x00010
509 must use lanman password hash 0x10010
510 may use plaintext passwords 0x00020
511 must use plaintext passwords 0x20020
512 (reserved for future packet encryption) 0x00040
513
488cifsFYI If set to one, additional debug information is 514cifsFYI If set to one, additional debug information is
489 logged to the system error log. (default 0) 515 logged to the system error log. (default 0)
490ExtendedSecurity If set to one, SPNEGO session establishment
491 is allowed which enables more advanced
492 secure CIFS session establishment (default 0)
493NTLMV2Enabled If set to one, more secure password hashes
494 are used when the server supports them and
495 when kerberos is not negotiated (default 0)
496traceSMB If set to one, debug information is logged to the 516traceSMB If set to one, debug information is logged to the
497 system error log with the start of smb requests 517 system error log with the start of smb requests
498 and responses (default 0) 518 and responses (default 0)
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 086ae8f4a207..031cdf293256 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -467,7 +467,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
467 asn1_open(&ctx, security_blob, length); 467 asn1_open(&ctx, security_blob, length);
468 468
469 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 469 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
470 cFYI(1, ("Error decoding negTokenInit header ")); 470 cFYI(1, ("Error decoding negTokenInit header"));
471 return 0; 471 return 0;
472 } else if ((cls != ASN1_APL) || (con != ASN1_CON) 472 } else if ((cls != ASN1_APL) || (con != ASN1_CON)
473 || (tag != ASN1_EOC)) { 473 || (tag != ASN1_EOC)) {
@@ -495,7 +495,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
495 } 495 }
496 496
497 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 497 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
498 cFYI(1, ("Error decoding negTokenInit ")); 498 cFYI(1, ("Error decoding negTokenInit"));
499 return 0; 499 return 0;
500 } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 500 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
501 || (tag != ASN1_EOC)) { 501 || (tag != ASN1_EOC)) {
@@ -505,7 +505,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
505 } 505 }
506 506
507 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 507 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
508 cFYI(1, ("Error decoding negTokenInit ")); 508 cFYI(1, ("Error decoding negTokenInit"));
509 return 0; 509 return 0;
510 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 510 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
511 || (tag != ASN1_SEQ)) { 511 || (tag != ASN1_SEQ)) {
@@ -515,7 +515,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
515 } 515 }
516 516
517 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 517 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
518 cFYI(1, ("Error decoding 2nd part of negTokenInit ")); 518 cFYI(1, ("Error decoding 2nd part of negTokenInit"));
519 return 0; 519 return 0;
520 } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 520 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
521 || (tag != ASN1_EOC)) { 521 || (tag != ASN1_EOC)) {
@@ -527,7 +527,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
527 527
528 if (asn1_header_decode 528 if (asn1_header_decode
529 (&ctx, &sequence_end, &cls, &con, &tag) == 0) { 529 (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
530 cFYI(1, ("Error decoding 2nd part of negTokenInit ")); 530 cFYI(1, ("Error decoding 2nd part of negTokenInit"));
531 return 0; 531 return 0;
532 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 532 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
533 || (tag != ASN1_SEQ)) { 533 || (tag != ASN1_SEQ)) {
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index f4124a32bef8..96abeb738978 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
39 char *charptr = data; 39 char *charptr = data;
40 char buf[10], line[80]; 40 char buf[10], line[80];
41 41
42 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", 42 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
43 label, length, data); 43 label, length, data);
44 for (i = 0; i < length; i += 16) { 44 for (i = 0; i < length; i += 16) {
45 line[0] = 0; 45 line[0] = 0;
@@ -57,6 +57,57 @@ cifs_dump_mem(char *label, void *data, int length)
57 } 57 }
58} 58}
59 59
60#ifdef CONFIG_CIFS_DEBUG2
61void cifs_dump_detail(struct smb_hdr * smb)
62{
63 cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
64 smb->Command, smb->Status.CifsError,
65 smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
66 cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
67}
68
69
70void cifs_dump_mids(struct TCP_Server_Info * server)
71{
72 struct list_head *tmp;
73 struct mid_q_entry * mid_entry;
74
75 if(server == NULL)
76 return;
77
78 cERROR(1,("Dump pending requests:"));
79 spin_lock(&GlobalMid_Lock);
80 list_for_each(tmp, &server->pending_mid_q) {
81 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
82 if(mid_entry) {
83 cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
84 mid_entry->midState,
85 (int)mid_entry->command,
86 mid_entry->pid,
87 mid_entry->tsk,
88 mid_entry->mid));
89#ifdef CONFIG_CIFS_STATS2
90 cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
91 mid_entry->largeBuf,
92 mid_entry->resp_buf,
93 mid_entry->when_received,
94 jiffies));
95#endif /* STATS2 */
96 cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
97 mid_entry->multiEnd));
98 if(mid_entry->resp_buf) {
99 cifs_dump_detail(mid_entry->resp_buf);
100 cifs_dump_mem("existing buf: ",
101 mid_entry->resp_buf,
102 62 /* fixme */);
103 }
104
105 }
106 }
107 spin_unlock(&GlobalMid_Lock);
108}
109#endif /* CONFIG_CIFS_DEBUG2 */
110
60#ifdef CONFIG_PROC_FS 111#ifdef CONFIG_PROC_FS
61static int 112static int
62cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, 113cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
@@ -73,7 +124,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
73 124
74 *beginBuffer = buf + offset; 125 *beginBuffer = buf + offset;
75 126
76
77 length = 127 length =
78 sprintf(buf, 128 sprintf(buf,
79 "Display Internal CIFS Data Structures for Debugging\n" 129 "Display Internal CIFS Data Structures for Debugging\n"
@@ -395,12 +445,12 @@ static read_proc_t traceSMB_read;
395static write_proc_t traceSMB_write; 445static write_proc_t traceSMB_write;
396static read_proc_t multiuser_mount_read; 446static read_proc_t multiuser_mount_read;
397static write_proc_t multiuser_mount_write; 447static write_proc_t multiuser_mount_write;
398static read_proc_t extended_security_read; 448static read_proc_t security_flags_read;
399static write_proc_t extended_security_write; 449static write_proc_t security_flags_write;
400static read_proc_t ntlmv2_enabled_read; 450/* static read_proc_t ntlmv2_enabled_read;
401static write_proc_t ntlmv2_enabled_write; 451static write_proc_t ntlmv2_enabled_write;
402static read_proc_t packet_signing_enabled_read; 452static read_proc_t packet_signing_enabled_read;
403static write_proc_t packet_signing_enabled_write; 453static write_proc_t packet_signing_enabled_write;*/
404static read_proc_t experimEnabled_read; 454static read_proc_t experimEnabled_read;
405static write_proc_t experimEnabled_write; 455static write_proc_t experimEnabled_write;
406static read_proc_t linuxExtensionsEnabled_read; 456static read_proc_t linuxExtensionsEnabled_read;
@@ -458,10 +508,10 @@ cifs_proc_init(void)
458 pde->write_proc = multiuser_mount_write; 508 pde->write_proc = multiuser_mount_write;
459 509
460 pde = 510 pde =
461 create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs, 511 create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
462 extended_security_read, NULL); 512 security_flags_read, NULL);
463 if (pde) 513 if (pde)
464 pde->write_proc = extended_security_write; 514 pde->write_proc = security_flags_write;
465 515
466 pde = 516 pde =
467 create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs, 517 create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
@@ -469,7 +519,7 @@ cifs_proc_init(void)
469 if (pde) 519 if (pde)
470 pde->write_proc = lookupFlag_write; 520 pde->write_proc = lookupFlag_write;
471 521
472 pde = 522/* pde =
473 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs, 523 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
474 ntlmv2_enabled_read, NULL); 524 ntlmv2_enabled_read, NULL);
475 if (pde) 525 if (pde)
@@ -479,7 +529,7 @@ cifs_proc_init(void)
479 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs, 529 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
480 packet_signing_enabled_read, NULL); 530 packet_signing_enabled_read, NULL);
481 if (pde) 531 if (pde)
482 pde->write_proc = packet_signing_enabled_write; 532 pde->write_proc = packet_signing_enabled_write;*/
483} 533}
484 534
485void 535void
@@ -496,9 +546,9 @@ cifs_proc_clean(void)
496#endif 546#endif
497 remove_proc_entry("MultiuserMount", proc_fs_cifs); 547 remove_proc_entry("MultiuserMount", proc_fs_cifs);
498 remove_proc_entry("OplockEnabled", proc_fs_cifs); 548 remove_proc_entry("OplockEnabled", proc_fs_cifs);
499 remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); 549/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
500 remove_proc_entry("ExtendedSecurity",proc_fs_cifs); 550 remove_proc_entry("SecurityFlags",proc_fs_cifs);
501 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); 551/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
502 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); 552 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
503 remove_proc_entry("Experimental",proc_fs_cifs); 553 remove_proc_entry("Experimental",proc_fs_cifs);
504 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); 554 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
@@ -782,12 +832,12 @@ multiuser_mount_write(struct file *file, const char __user *buffer,
782} 832}
783 833
784static int 834static int
785extended_security_read(char *page, char **start, off_t off, 835security_flags_read(char *page, char **start, off_t off,
786 int count, int *eof, void *data) 836 int count, int *eof, void *data)
787{ 837{
788 int len; 838 int len;
789 839
790 len = sprintf(page, "%d\n", extended_security); 840 len = sprintf(page, "0x%x\n", extended_security);
791 841
792 len -= off; 842 len -= off;
793 *start = page + off; 843 *start = page + off;
@@ -803,24 +853,52 @@ extended_security_read(char *page, char **start, off_t off,
803 return len; 853 return len;
804} 854}
805static int 855static int
806extended_security_write(struct file *file, const char __user *buffer, 856security_flags_write(struct file *file, const char __user *buffer,
807 unsigned long count, void *data) 857 unsigned long count, void *data)
808{ 858{
859 unsigned int flags;
860 char flags_string[12];
809 char c; 861 char c;
810 int rc;
811 862
812 rc = get_user(c, buffer); 863 if((count < 1) || (count > 11))
813 if (rc) 864 return -EINVAL;
814 return rc; 865
815 if (c == '0' || c == 'n' || c == 'N') 866 memset(flags_string, 0, 12);
816 extended_security = 0; 867
817 else if (c == '1' || c == 'y' || c == 'Y') 868 if(copy_from_user(flags_string, buffer, count))
818 extended_security = 1; 869 return -EFAULT;
870
871 if(count < 3) {
872 /* single char or single char followed by null */
873 c = flags_string[0];
874 if (c == '0' || c == 'n' || c == 'N')
875 extended_security = CIFSSEC_DEF; /* default */
876 else if (c == '1' || c == 'y' || c == 'Y')
877 extended_security = CIFSSEC_MAX;
878 return count;
879 }
880 /* else we have a number */
881
882 flags = simple_strtoul(flags_string, NULL, 0);
883
884 cFYI(1,("sec flags 0x%x", flags));
885
886 if(flags <= 0) {
887 cERROR(1,("invalid security flags %s",flags_string));
888 return -EINVAL;
889 }
819 890
891 if(flags & ~CIFSSEC_MASK) {
892 cERROR(1,("attempt to set unsupported security flags 0x%x",
893 flags & ~CIFSSEC_MASK));
894 return -EINVAL;
895 }
896 /* flags look ok - update the global security flags for cifs module */
897 extended_security = flags;
820 return count; 898 return count;
821} 899}
822 900
823static int 901/* static int
824ntlmv2_enabled_read(char *page, char **start, off_t off, 902ntlmv2_enabled_read(char *page, char **start, off_t off,
825 int count, int *eof, void *data) 903 int count, int *eof, void *data)
826{ 904{
@@ -855,6 +933,8 @@ ntlmv2_enabled_write(struct file *file, const char __user *buffer,
855 ntlmv2_support = 0; 933 ntlmv2_support = 0;
856 else if (c == '1' || c == 'y' || c == 'Y') 934 else if (c == '1' || c == 'y' || c == 'Y')
857 ntlmv2_support = 1; 935 ntlmv2_support = 1;
936 else if (c == '2')
937 ntlmv2_support = 2;
858 938
859 return count; 939 return count;
860} 940}
@@ -898,7 +978,7 @@ packet_signing_enabled_write(struct file *file, const char __user *buffer,
898 sign_CIFS_PDUs = 2; 978 sign_CIFS_PDUs = 2;
899 979
900 return count; 980 return count;
901} 981} */
902 982
903 983
904#endif 984#endif
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 4304d9dcfb6c..c26cd0d2c6d5 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -24,6 +24,10 @@
24#define _H_CIFS_DEBUG 24#define _H_CIFS_DEBUG
25 25
26void cifs_dump_mem(char *label, void *data, int length); 26void cifs_dump_mem(char *label, void *data, int length);
27#ifdef CONFIG_CIFS_DEBUG2
28void cifs_dump_detail(struct smb_hdr *);
29void cifs_dump_mids(struct TCP_Server_Info *);
30#endif
27extern int traceSMB; /* flag which enables the function below */ 31extern int traceSMB; /* flag which enables the function below */
28void dump_smb(struct smb_hdr *, int); 32void dump_smb(struct smb_hdr *, int);
29#define CIFS_INFO 0x01 33#define CIFS_INFO 0x01
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index d2b128255944..d2a8b2941fc2 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -22,6 +22,7 @@
22#include "cifs_unicode.h" 22#include "cifs_unicode.h"
23#include "cifs_uniupr.h" 23#include "cifs_uniupr.h"
24#include "cifspdu.h" 24#include "cifspdu.h"
25#include "cifsglob.h"
25#include "cifs_debug.h" 26#include "cifs_debug.h"
26 27
27/* 28/*
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index e7d63737e651..8bcb1da3270e 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -26,6 +26,8 @@
26#include "md5.h" 26#include "md5.h"
27#include "cifs_unicode.h" 27#include "cifs_unicode.h"
28#include "cifsproto.h" 28#include "cifsproto.h"
29#include <linux/ctype.h>
30#include <linux/random.h>
29 31
30/* Calculate and return the CIFS signature based on the mac key and the smb pdu */ 32/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
31/* the 16 byte signature must be allocated by the caller */ 33/* the 16 byte signature must be allocated by the caller */
@@ -35,6 +37,8 @@
35 37
36extern void mdfour(unsigned char *out, unsigned char *in, int n); 38extern void mdfour(unsigned char *out, unsigned char *in, int n);
37extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); 39extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
40extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
41 unsigned char *p24);
38 42
39static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, 43static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
40 const char * key, char * signature) 44 const char * key, char * signature)
@@ -45,7 +49,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
45 return -EINVAL; 49 return -EINVAL;
46 50
47 MD5Init(&context); 51 MD5Init(&context);
48 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); 52 MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
49 MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); 53 MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
50 MD5Final(signature,&context); 54 MD5Final(signature,&context);
51 return 0; 55 return 0;
@@ -90,7 +94,7 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
90 return -EINVAL; 94 return -EINVAL;
91 95
92 MD5Init(&context); 96 MD5Init(&context);
93 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); 97 MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
94 for(i=0;i<n_vec;i++) { 98 for(i=0;i<n_vec;i++) {
95 if(iov[i].iov_base == NULL) { 99 if(iov[i].iov_base == NULL) {
96 cERROR(1,("null iovec entry")); 100 cERROR(1,("null iovec entry"));
@@ -204,7 +208,7 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
204 208
205 E_md4hash(password, temp_key); 209 E_md4hash(password, temp_key);
206 mdfour(key,temp_key,16); 210 mdfour(key,temp_key,16);
207 memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE); 211 memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
208 return 0; 212 return 0;
209} 213}
210 214
@@ -225,6 +229,8 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
225 user_name_len = strlen(ses->userName); 229 user_name_len = strlen(ses->userName);
226 if(user_name_len > MAX_USERNAME_SIZE) 230 if(user_name_len > MAX_USERNAME_SIZE)
227 return -EINVAL; 231 return -EINVAL;
232 if(ses->domainName == NULL)
233 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
228 dom_name_len = strlen(ses->domainName); 234 dom_name_len = strlen(ses->domainName);
229 if(dom_name_len > MAX_USERNAME_SIZE) 235 if(dom_name_len > MAX_USERNAME_SIZE)
230 return -EINVAL; 236 return -EINVAL;
@@ -259,6 +265,100 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
259 kfree(unicode_buf); 265 kfree(unicode_buf);
260 return 0; 266 return 0;
261} 267}
268
269#ifdef CONFIG_CIFS_WEAK_PW_HASH
270void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
271{
272 int i;
273 char password_with_pad[CIFS_ENCPWD_SIZE];
274
275 if(ses->server == NULL)
276 return;
277
278 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
279 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
280
281 if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
282 if(extended_security & CIFSSEC_MAY_PLNTXT) {
283 memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
284 return;
285 }
286
287 /* calculate old style session key */
288 /* calling toupper is less broken than repeatedly
289 calling nls_toupper would be since that will never
290 work for UTF8, but neither handles multibyte code pages
291 but the only alternative would be converting to UCS-16 (Unicode)
292 (using a routine something like UniStrupr) then
293 uppercasing and then converting back from Unicode - which
294 would only worth doing it if we knew it were utf8. Basically
295 utf8 and other multibyte codepages each need their own strupper
296 function since a byte at a time will ont work. */
297
298 for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
299 password_with_pad[i] = toupper(password_with_pad[i]);
300 }
301
302 SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
303 /* clear password before we return/free memory */
304 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
305}
306#endif /* CIFS_WEAK_PW_HASH */
307
308static int calc_ntlmv2_hash(const struct cifsSesInfo *ses,
309 char * ntv2_hash)
310{
311 int rc = 0;
312 int len;
313 char nt_hash[16];
314 struct HMACMD5Context * pctxt;
315
316 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
317
318 if(pctxt == NULL)
319 return -ENOMEM;
320
321 /* calculate md4 hash of password */
322 E_md4hash(ses->password, nt_hash);
323
324 /* convERT Domainname to unicode and uppercase */
325 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
326
327 /* convert ses->userName to unicode and uppercase */
328
329 /* len = ... */ /* BB FIXME BB */
330
331 /* hmac_md5_update(user, len, pctxt); */
332
333 /* convert ses->domainName to unicode and uppercase */
334
335 /* len = ... */ /* BB FIXME BB */
336 /* hmac_md5_update(domain, len, pctxt); */
337
338 hmac_md5_final(ntv2_hash, pctxt);
339
340 return rc;
341}
342
343void setup_ntlmv2_rsp(const struct cifsSesInfo * ses, char * resp_buf)
344{
345 int rc;
346 struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
347
348 buf->blob_signature = cpu_to_le32(0x00000101);
349 buf->reserved = 0;
350 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
351 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
352 buf->reserved2 = 0;
353 buf->names[0].type = 0;
354 buf->names[0].length = 0;
355
356 /* calculate buf->ntlmv2_hash */
357 rc = calc_ntlmv2_hash(ses,buf->ntlmv2_hash);
358 if(rc)
359 cERROR(1,("could not get v2 hash rc %d",rc));
360}
361
262void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) 362void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
263{ 363{
264 struct HMACMD5Context context; 364 struct HMACMD5Context context;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c262d8874ce9..700570522b23 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -56,8 +56,8 @@ unsigned int experimEnabled = 0;
56unsigned int linuxExtEnabled = 1; 56unsigned int linuxExtEnabled = 1;
57unsigned int lookupCacheEnabled = 1; 57unsigned int lookupCacheEnabled = 1;
58unsigned int multiuser_mount = 0; 58unsigned int multiuser_mount = 0;
59unsigned int extended_security = 0; 59unsigned int extended_security = CIFSSEC_DEF;
60unsigned int ntlmv2_support = 0; 60/* unsigned int ntlmv2_support = 0; */
61unsigned int sign_CIFS_PDUs = 1; 61unsigned int sign_CIFS_PDUs = 1;
62extern struct task_struct * oplockThread; /* remove sparse warning */ 62extern struct task_struct * oplockThread; /* remove sparse warning */
63struct task_struct * oplockThread = NULL; 63struct task_struct * oplockThread = NULL;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index c98755dca868..3011df988bd5 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -33,6 +33,7 @@
33#endif 33#endif
34 34
35extern struct address_space_operations cifs_addr_ops; 35extern struct address_space_operations cifs_addr_ops;
36extern struct address_space_operations cifs_addr_ops_smallbuf;
36 37
37/* Functions related to super block operations */ 38/* Functions related to super block operations */
38extern struct super_operations cifs_super_ops; 39extern struct super_operations cifs_super_ops;
@@ -99,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
100extern int cifs_ioctl (struct inode * inode, struct file * filep, 101extern int cifs_ioctl (struct inode * inode, struct file * filep,
101 unsigned int command, unsigned long arg); 102 unsigned int command, unsigned long arg);
102#define CIFS_VERSION "1.43" 103#define CIFS_VERSION "1.44"
103#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 006eb33bff5f..87453a6bcaf8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -88,7 +88,8 @@ enum statusEnum {
88}; 88};
89 89
90enum securityEnum { 90enum securityEnum {
91 NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */ 91 LANMAN = 0, /* Legacy LANMAN auth */
92 NTLM, /* Legacy NTLM012 auth with NTLM hash */
92 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 93 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
93 RawNTLMSSP, /* NTLMSSP without SPNEGO */ 94 RawNTLMSSP, /* NTLMSSP without SPNEGO */
94 NTLMSSP, /* NTLMSSP via SPNEGO */ 95 NTLMSSP, /* NTLMSSP via SPNEGO */
@@ -157,7 +158,7 @@ struct TCP_Server_Info {
157 /* 16th byte of RFC1001 workstation name is always null */ 158 /* 16th byte of RFC1001 workstation name is always null */
158 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; 159 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
159 __u32 sequence_number; /* needed for CIFS PDU signature */ 160 __u32 sequence_number; /* needed for CIFS PDU signature */
160 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 161 char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
161}; 162};
162 163
163/* 164/*
@@ -179,7 +180,9 @@ struct cifsUidInfo {
179struct cifsSesInfo { 180struct cifsSesInfo {
180 struct list_head cifsSessionList; 181 struct list_head cifsSessionList;
181 struct semaphore sesSem; 182 struct semaphore sesSem;
183#if 0
182 struct cifsUidInfo *uidInfo; /* pointer to user info */ 184 struct cifsUidInfo *uidInfo; /* pointer to user info */
185#endif
183 struct TCP_Server_Info *server; /* pointer to server info */ 186 struct TCP_Server_Info *server; /* pointer to server info */
184 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 187 atomic_t inUse; /* # of mounts (tree connections) on this ses */
185 enum statusEnum status; 188 enum statusEnum status;
@@ -194,7 +197,7 @@ struct cifsSesInfo {
194 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for 197 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
195 TCP names - will ipv6 and sctp addresses fit? */ 198 TCP names - will ipv6 and sctp addresses fit? */
196 char userName[MAX_USERNAME_SIZE + 1]; 199 char userName[MAX_USERNAME_SIZE + 1];
197 char domainName[MAX_USERNAME_SIZE + 1]; 200 char * domainName;
198 char * password; 201 char * password;
199}; 202};
200/* session flags */ 203/* session flags */
@@ -209,12 +212,12 @@ struct cifsTconInfo {
209 struct list_head openFileList; 212 struct list_head openFileList;
210 struct semaphore tconSem; 213 struct semaphore tconSem;
211 struct cifsSesInfo *ses; /* pointer to session associated with */ 214 struct cifsSesInfo *ses; /* pointer to session associated with */
212 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */ 215 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
213 char *nativeFileSystem; 216 char *nativeFileSystem;
214 __u16 tid; /* The 2 byte tree id */ 217 __u16 tid; /* The 2 byte tree id */
215 __u16 Flags; /* optional support bits */ 218 __u16 Flags; /* optional support bits */
216 enum statusEnum tidStatus; 219 enum statusEnum tidStatus;
217 atomic_t useCount; /* how many mounts (explicit or implicit) to this share */ 220 atomic_t useCount; /* how many explicit/implicit mounts to share */
218#ifdef CONFIG_CIFS_STATS 221#ifdef CONFIG_CIFS_STATS
219 atomic_t num_smbs_sent; 222 atomic_t num_smbs_sent;
220 atomic_t num_writes; 223 atomic_t num_writes;
@@ -254,7 +257,7 @@ struct cifsTconInfo {
254 spinlock_t stat_lock; 257 spinlock_t stat_lock;
255#endif /* CONFIG_CIFS_STATS */ 258#endif /* CONFIG_CIFS_STATS */
256 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 259 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
257 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ 260 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
258 FILE_SYSTEM_UNIX_INFO fsUnixInfo; 261 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
259 unsigned retry:1; 262 unsigned retry:1;
260 unsigned nocase:1; 263 unsigned nocase:1;
@@ -305,7 +308,6 @@ struct cifsFileInfo {
305 atomic_t wrtPending; /* handle in use - defer close */ 308 atomic_t wrtPending; /* handle in use - defer close */
306 struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 309 struct semaphore fh_sem; /* prevents reopen race after dead ses*/
307 char * search_resume_name; /* BB removeme BB */ 310 char * search_resume_name; /* BB removeme BB */
308 unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
309 struct cifs_search_info srch_inf; 311 struct cifs_search_info srch_inf;
310}; 312};
311 313
@@ -391,9 +393,9 @@ struct mid_q_entry {
391 struct smb_hdr *resp_buf; /* response buffer */ 393 struct smb_hdr *resp_buf; /* response buffer */
392 int midState; /* wish this were enum but can not pass to wait_event */ 394 int midState; /* wish this were enum but can not pass to wait_event */
393 __u8 command; /* smb command code */ 395 __u8 command; /* smb command code */
394 unsigned multiPart:1; /* multiple responses to one SMB request */
395 unsigned largeBuf:1; /* if valid response, is pointer to large buf */ 396 unsigned largeBuf:1; /* if valid response, is pointer to large buf */
396 unsigned multiResp:1; /* multiple trans2 responses for one request */ 397 unsigned multiRsp:1; /* multiple trans2 responses for one request */
398 unsigned multiEnd:1; /* both received */
397}; 399};
398 400
399struct oplock_q_entry { 401struct oplock_q_entry {
@@ -430,15 +432,35 @@ struct dir_notify_req {
430#define CIFS_LARGE_BUFFER 2 432#define CIFS_LARGE_BUFFER 2
431#define CIFS_IOVEC 4 /* array of response buffers */ 433#define CIFS_IOVEC 4 /* array of response buffers */
432 434
433/* Type of session setup needed */ 435/* Security Flags: indicate type of session setup needed */
434#define CIFS_PLAINTEXT 0 436#define CIFSSEC_MAY_SIGN 0x00001
435#define CIFS_LANMAN 1 437#define CIFSSEC_MAY_NTLM 0x00002
436#define CIFS_NTLM 2 438#define CIFSSEC_MAY_NTLMV2 0x00004
437#define CIFS_NTLMSSP_NEG 3 439#define CIFSSEC_MAY_KRB5 0x00008
438#define CIFS_NTLMSSP_AUTH 4 440#ifdef CONFIG_CIFS_WEAK_PW_HASH
439#define CIFS_SPNEGO_INIT 5 441#define CIFSSEC_MAY_LANMAN 0x00010
440#define CIFS_SPNEGO_TARG 6 442#define CIFSSEC_MAY_PLNTXT 0x00020
441 443#endif /* weak passwords */
444#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
445
446#define CIFSSEC_MUST_SIGN 0x01001
447/* note that only one of the following can be set so the
448result of setting MUST flags more than once will be to
449require use of the stronger protocol */
450#define CIFSSEC_MUST_NTLM 0x02002
451#define CIFSSEC_MUST_NTLMV2 0x04004
452#define CIFSSEC_MUST_KRB5 0x08008
453#ifdef CONFIG_CIFS_WEAK_PW_HASH
454#define CIFSSEC_MUST_LANMAN 0x10010
455#define CIFSSEC_MUST_PLNTXT 0x20020
456#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
457#else
458#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
459#endif /* WEAK_PW_HASH */
460#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
461
462#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
463#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
442/* 464/*
443 ***************************************************************** 465 *****************************************************************
444 * All constants go here 466 * All constants go here
@@ -500,16 +522,16 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
500GLOBAL_EXTERN struct list_head GlobalOplock_Q; 522GLOBAL_EXTERN struct list_head GlobalOplock_Q;
501 523
502GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ 524GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
503GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */ 525GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */
504 526
505/* 527/*
506 * Global transaction id (XID) information 528 * Global transaction id (XID) information
507 */ 529 */
508GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ 530GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
509GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ 531GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
510GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ 532GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
511GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */ 533GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */
512 /* on midQ entries */ 534 /* on midQ entries */
513GLOBAL_EXTERN char Local_System_Name[15]; 535GLOBAL_EXTERN char Local_System_Name[15];
514 536
515/* 537/*
@@ -531,7 +553,7 @@ GLOBAL_EXTERN atomic_t smBufAllocCount;
531GLOBAL_EXTERN atomic_t midCount; 553GLOBAL_EXTERN atomic_t midCount;
532 554
533/* Misc globals */ 555/* Misc globals */
534GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions 556GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
535 to be established on existing mount if we 557 to be established on existing mount if we
536 have the uid/password or Kerberos credential 558 have the uid/password or Kerberos credential
537 or equivalent for current user */ 559 or equivalent for current user */
@@ -540,8 +562,8 @@ GLOBAL_EXTERN unsigned int experimEnabled;
540GLOBAL_EXTERN unsigned int lookupCacheEnabled; 562GLOBAL_EXTERN unsigned int lookupCacheEnabled;
541GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent 563GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
542 with more secure ntlmssp2 challenge/resp */ 564 with more secure ntlmssp2 challenge/resp */
543GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
544GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ 565GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
566GLOBAL_EXTERN unsigned int secFlags;
545GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ 567GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
546GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ 568GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
547GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ 569GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b2233ac05bd2..86239023545b 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -16,7 +16,7 @@
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public License 17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software 18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#ifndef _CIFSPDU_H 22#ifndef _CIFSPDU_H
@@ -24,8 +24,14 @@
24 24
25#include <net/sock.h> 25#include <net/sock.h>
26 26
27#ifdef CONFIG_CIFS_WEAK_PW_HASH
28#define LANMAN_PROT 0
29#define CIFS_PROT 1
30#else
27#define CIFS_PROT 0 31#define CIFS_PROT 0
28#define BAD_PROT CIFS_PROT+1 32#endif
33#define POSIX_PROT CIFS_PROT+1
34#define BAD_PROT 0xFFFF
29 35
30/* SMB command codes */ 36/* SMB command codes */
31/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses 37/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
@@ -110,7 +116,7 @@
110/* 116/*
111 * Size of the session key (crypto key encrypted with the password 117 * Size of the session key (crypto key encrypted with the password
112 */ 118 */
113#define CIFS_SESSION_KEY_SIZE (24) 119#define CIFS_SESS_KEY_SIZE (24)
114 120
115/* 121/*
116 * Maximum user name length 122 * Maximum user name length
@@ -400,6 +406,29 @@ typedef struct negotiate_req {
400 unsigned char DialectsArray[1]; 406 unsigned char DialectsArray[1];
401} __attribute__((packed)) NEGOTIATE_REQ; 407} __attribute__((packed)) NEGOTIATE_REQ;
402 408
409/* Dialect index is 13 for LANMAN */
410
411typedef struct lanman_neg_rsp {
412 struct smb_hdr hdr; /* wct = 13 */
413 __le16 DialectIndex;
414 __le16 SecurityMode;
415 __le16 MaxBufSize;
416 __le16 MaxMpxCount;
417 __le16 MaxNumberVcs;
418 __le16 RawMode;
419 __le32 SessionKey;
420 __le32 ServerTime;
421 __le16 ServerTimeZone;
422 __le16 EncryptionKeyLength;
423 __le16 Reserved;
424 __u16 ByteCount;
425 unsigned char EncryptionKey[1];
426} __attribute__((packed)) LANMAN_NEG_RSP;
427
428#define READ_RAW_ENABLE 1
429#define WRITE_RAW_ENABLE 2
430#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
431
403typedef struct negotiate_rsp { 432typedef struct negotiate_rsp {
404 struct smb_hdr hdr; /* wct = 17 */ 433 struct smb_hdr hdr; /* wct = 17 */
405 __le16 DialectIndex; 434 __le16 DialectIndex;
@@ -509,7 +538,7 @@ typedef union smb_com_session_setup_andx {
509/* unsigned char * NativeOS; */ 538/* unsigned char * NativeOS; */
510/* unsigned char * NativeLanMan; */ 539/* unsigned char * NativeLanMan; */
511/* unsigned char * PrimaryDomain; */ 540/* unsigned char * PrimaryDomain; */
512 } __attribute__((packed)) resp; /* NTLM response format (with or without extended security */ 541 } __attribute__((packed)) resp; /* NTLM response with or without extended sec*/
513 542
514 struct { /* request format */ 543 struct { /* request format */
515 struct smb_hdr hdr; /* wct = 10 */ 544 struct smb_hdr hdr; /* wct = 10 */
@@ -520,8 +549,8 @@ typedef union smb_com_session_setup_andx {
520 __le16 MaxMpxCount; 549 __le16 MaxMpxCount;
521 __le16 VcNumber; 550 __le16 VcNumber;
522 __u32 SessionKey; 551 __u32 SessionKey;
523 __le16 PassswordLength; 552 __le16 PasswordLength;
524 __u32 Reserved; 553 __u32 Reserved; /* encrypt key len and offset */
525 __le16 ByteCount; 554 __le16 ByteCount;
526 unsigned char AccountPassword[1]; /* followed by */ 555 unsigned char AccountPassword[1]; /* followed by */
527 /* STRING AccountName */ 556 /* STRING AccountName */
@@ -543,6 +572,26 @@ typedef union smb_com_session_setup_andx {
543 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */ 572 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
544} __attribute__((packed)) SESSION_SETUP_ANDX; 573} __attribute__((packed)) SESSION_SETUP_ANDX;
545 574
575/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
576
577struct ntlmssp2_name {
578 __le16 type;
579 __le16 length;
580/* char name[length]; */
581} __attribute__((packed));
582
583struct ntlmv2_resp {
584 char ntlmv2_hash[CIFS_ENCPWD_SIZE];
585 __le32 blob_signature;
586 __u32 reserved;
587 __le64 time;
588 __u64 client_chal; /* random */
589 __u32 reserved2;
590 struct ntlmssp2_name names[1];
591 /* array of name entries could follow ending in minimum 4 byte struct */
592} __attribute__((packed));
593
594
546#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" 595#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
547 596
548/* Capabilities bits (for NTLM SessSetup request) */ 597/* Capabilities bits (for NTLM SessSetup request) */
@@ -573,7 +622,9 @@ typedef struct smb_com_tconx_req {
573} __attribute__((packed)) TCONX_REQ; 622} __attribute__((packed)) TCONX_REQ;
574 623
575typedef struct smb_com_tconx_rsp { 624typedef struct smb_com_tconx_rsp {
576 struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */ 625 struct smb_hdr hdr; /* wct = 3 note that Win2000 has sent wct = 7
626 in some cases on responses. Four unspecified
627 words followed OptionalSupport */
577 __u8 AndXCommand; 628 __u8 AndXCommand;
578 __u8 AndXReserved; 629 __u8 AndXReserved;
579 __le16 AndXOffset; 630 __le16 AndXOffset;
@@ -1323,6 +1374,9 @@ struct smb_t2_rsp {
1323#define SMB_FILE_MAXIMUM_INFO 0x40d 1374#define SMB_FILE_MAXIMUM_INFO 0x40d
1324 1375
1325/* Find File infolevels */ 1376/* Find File infolevels */
1377#define SMB_FIND_FILE_INFO_STANDARD 0x001
1378#define SMB_FIND_FILE_QUERY_EA_SIZE 0x002
1379#define SMB_FIND_FILE_QUERY_EAS_FROM_LIST 0x003
1326#define SMB_FIND_FILE_DIRECTORY_INFO 0x101 1380#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
1327#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 1381#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
1328#define SMB_FIND_FILE_NAMES_INFO 0x103 1382#define SMB_FIND_FILE_NAMES_INFO 0x103
@@ -1844,13 +1898,13 @@ typedef struct {
1844typedef struct { 1898typedef struct {
1845 __le32 DeviceType; 1899 __le32 DeviceType;
1846 __le32 DeviceCharacteristics; 1900 __le32 DeviceCharacteristics;
1847} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */ 1901} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
1848 1902
1849typedef struct { 1903typedef struct {
1850 __le32 Attributes; 1904 __le32 Attributes;
1851 __le32 MaxPathNameComponentLength; 1905 __le32 MaxPathNameComponentLength;
1852 __le32 FileSystemNameLen; 1906 __le32 FileSystemNameLen;
1853 char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ 1907 char FileSystemName[52]; /* do not have to save this - get subset? */
1854} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO; 1908} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
1855 1909
1856/******************************************************************************/ 1910/******************************************************************************/
@@ -1947,7 +2001,8 @@ typedef struct {
1947 2001
1948struct file_allocation_info { 2002struct file_allocation_info {
1949 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ 2003 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
1950} __attribute__((packed)); /* size used on disk, level 0x103 for set, 0x105 for query */ 2004} __attribute__((packed)); /* size used on disk, for level 0x103 for set,
2005 0x105 for query */
1951 2006
1952struct file_end_of_file_info { 2007struct file_end_of_file_info {
1953 __le64 FileSize; /* offset to end of file */ 2008 __le64 FileSize; /* offset to end of file */
@@ -2054,7 +2109,7 @@ typedef struct {
2054 __le32 ExtFileAttributes; 2109 __le32 ExtFileAttributes;
2055 __le32 FileNameLength; 2110 __le32 FileNameLength;
2056 char FileName[1]; 2111 char FileName[1];
2057} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */ 2112} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */
2058 2113
2059typedef struct { 2114typedef struct {
2060 __le32 NextEntryOffset; 2115 __le32 NextEntryOffset;
@@ -2069,7 +2124,7 @@ typedef struct {
2069 __le32 FileNameLength; 2124 __le32 FileNameLength;
2070 __le32 EaSize; /* length of the xattrs */ 2125 __le32 EaSize; /* length of the xattrs */
2071 char FileName[1]; 2126 char FileName[1];
2072} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */ 2127} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */
2073 2128
2074typedef struct { 2129typedef struct {
2075 __le32 NextEntryOffset; 2130 __le32 NextEntryOffset;
@@ -2086,7 +2141,7 @@ typedef struct {
2086 __le32 Reserved; 2141 __le32 Reserved;
2087 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ 2142 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
2088 char FileName[1]; 2143 char FileName[1];
2089} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */ 2144} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
2090 2145
2091typedef struct { 2146typedef struct {
2092 __le32 NextEntryOffset; 2147 __le32 NextEntryOffset;
@@ -2104,7 +2159,22 @@ typedef struct {
2104 __u8 Reserved; 2159 __u8 Reserved;
2105 __u8 ShortName[12]; 2160 __u8 ShortName[12];
2106 char FileName[1]; 2161 char FileName[1];
2107} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ 2162} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
2163
2164typedef struct {
2165 __u32 ResumeKey;
2166 __le16 CreationDate; /* SMB Date */
2167 __le16 CreationTime; /* SMB Time */
2168 __le16 LastAccessDate;
2169 __le16 LastAccessTime;
2170 __le16 LastWriteDate;
2171 __le16 LastWriteTime;
2172 __le32 DataSize; /* File Size (EOF) */
2173 __le32 AllocationSize;
2174 __le16 Attributes; /* verify not u32 */
2175 __u8 FileNameLength;
2176 char FileName[1];
2177} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
2108 2178
2109 2179
2110struct win_dev { 2180struct win_dev {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 310ea2f0e0bf..824afb937a6f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -69,7 +69,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
69 struct cifsSesInfo *ses, 69 struct cifsSesInfo *ses,
70 void ** request_buf); 70 void ** request_buf);
71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, 71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
72 const int stage, int * pNTLMv2_flg, 72 const int stage,
73 const struct nls_table *nls_cp); 73 const struct nls_table *nls_cp);
74#endif 74#endif
75extern __u16 GetNextMid(struct TCP_Server_Info *server); 75extern __u16 GetNextMid(struct TCP_Server_Info *server);
@@ -287,6 +287,10 @@ extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
287extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 287extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
288extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); 288extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); 289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
290extern void setup_ntlmv2_rsp(const struct cifsSesInfo *, char *);
291#ifdef CONFIG_CIFS_WEAK_PW_HASH
292extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
293#endif /* CIFS_WEAK_PW_HASH */
290extern int CIFSSMBCopy(int xid, 294extern int CIFSSMBCopy(int xid,
291 struct cifsTconInfo *source_tcon, 295 struct cifsTconInfo *source_tcon,
292 const char *fromName, 296 const char *fromName,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 925881e00ff2..acae58313b0c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -44,8 +44,11 @@ static struct {
44 int index; 44 int index;
45 char *name; 45 char *name;
46} protocols[] = { 46} protocols[] = {
47#ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49#endif /* weak password hashing for legacy clients */
47 {CIFS_PROT, "\2NT LM 0.12"}, 50 {CIFS_PROT, "\2NT LM 0.12"},
48 {CIFS_PROT, "\2POSIX 2"}, 51 {POSIX_PROT, "\2POSIX 2"},
49 {BAD_PROT, "\2"} 52 {BAD_PROT, "\2"}
50}; 53};
51#else 54#else
@@ -53,11 +56,29 @@ static struct {
53 int index; 56 int index;
54 char *name; 57 char *name;
55} protocols[] = { 58} protocols[] = {
59#ifdef CONFIG_CIFS_WEAK_PW_HASH
60 {LANMAN_PROT, "\2LM1.2X002"},
61#endif /* weak password hashing for legacy clients */
56 {CIFS_PROT, "\2NT LM 0.12"}, 62 {CIFS_PROT, "\2NT LM 0.12"},
57 {BAD_PROT, "\2"} 63 {BAD_PROT, "\2"}
58}; 64};
59#endif 65#endif
60 66
67/* define the number of elements in the cifs dialect array */
68#ifdef CONFIG_CIFS_POSIX
69#ifdef CONFIG_CIFS_WEAK_PW_HASH
70#define CIFS_NUM_PROT 3
71#else
72#define CIFS_NUM_PROT 2
73#endif /* CIFS_WEAK_PW_HASH */
74#else /* not posix */
75#ifdef CONFIG_CIFS_WEAK_PW_HASH
76#define CIFS_NUM_PROT 2
77#else
78#define CIFS_NUM_PROT 1
79#endif /* CONFIG_CIFS_WEAK_PW_HASH */
80#endif /* CIFS_POSIX */
81
61 82
62/* Mark as invalid, all open files on tree connections since they 83/* Mark as invalid, all open files on tree connections since they
63 were closed when session to server was lost */ 84 were closed when session to server was lost */
@@ -322,7 +343,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
322 /* potential retries of smb operations it turns out we can determine */ 343 /* potential retries of smb operations it turns out we can determine */
323 /* from the mid flags when the request buffer can be resent without */ 344 /* from the mid flags when the request buffer can be resent without */
324 /* having to use a second distinct buffer for the response */ 345 /* having to use a second distinct buffer for the response */
325 *response_buf = *request_buf; 346 if(response_buf)
347 *response_buf = *request_buf;
326 348
327 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 349 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
328 wct /*wct */ ); 350 wct /*wct */ );
@@ -373,6 +395,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
373 NEGOTIATE_RSP *pSMBr; 395 NEGOTIATE_RSP *pSMBr;
374 int rc = 0; 396 int rc = 0;
375 int bytes_returned; 397 int bytes_returned;
398 int i;
376 struct TCP_Server_Info * server; 399 struct TCP_Server_Info * server;
377 u16 count; 400 u16 count;
378 401
@@ -388,99 +411,185 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
388 return rc; 411 return rc;
389 pSMB->hdr.Mid = GetNextMid(server); 412 pSMB->hdr.Mid = GetNextMid(server);
390 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 413 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
391 if (extended_security) 414 if((extended_security & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
392 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 415 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
393 416
394 count = strlen(protocols[0].name) + 1; 417 count = 0;
395 strncpy(pSMB->DialectsArray, protocols[0].name, 30); 418 for(i=0;i<CIFS_NUM_PROT;i++) {
396 /* null guaranteed to be at end of source and target buffers anyway */ 419 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
397 420 count += strlen(protocols[i].name) + 1;
421 /* null at end of source and target buffers anyway */
422 }
398 pSMB->hdr.smb_buf_length += count; 423 pSMB->hdr.smb_buf_length += count;
399 pSMB->ByteCount = cpu_to_le16(count); 424 pSMB->ByteCount = cpu_to_le16(count);
400 425
401 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, 426 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
402 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 427 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
403 if (rc == 0) { 428 if (rc != 0)
404 server->secMode = pSMBr->SecurityMode; 429 goto neg_err_exit;
405 if((server->secMode & SECMODE_USER) == 0) 430
406 cFYI(1,("share mode security")); 431 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
407 server->secType = NTLM; /* BB override default for 432 /* Check wct = 1 error case */
408 NTLMv2 or kerberos v5 */ 433 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
409 /* one byte - no need to convert this or EncryptionKeyLen 434 /* core returns wct = 1, but we do not ask for core - otherwise
410 from little endian */ 435 small wct just comes when dialect index is -1 indicating we
411 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 436 could not negotiate a common dialect */
412 /* probably no need to store and check maxvcs */ 437 rc = -EOPNOTSUPP;
413 server->maxBuf = 438 goto neg_err_exit;
414 min(le32_to_cpu(pSMBr->MaxBufferSize), 439#ifdef CONFIG_CIFS_WEAK_PW_HASH
440 } else if((pSMBr->hdr.WordCount == 13)
441 && (pSMBr->DialectIndex == LANMAN_PROT)) {
442 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
443
444 if((extended_security & CIFSSEC_MAY_LANMAN) ||
445 (extended_security & CIFSSEC_MAY_PLNTXT))
446 server->secType = LANMAN;
447 else {
448 cERROR(1, ("mount failed weak security disabled"
449 " in /proc/fs/cifs/SecurityFlags"));
450 rc = -EOPNOTSUPP;
451 goto neg_err_exit;
452 }
453 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
454 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
455 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
456 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
457 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
458 /* even though we do not use raw we might as well set this
459 accurately, in case we ever find a need for it */
460 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
461 server->maxRw = 0xFF00;
462 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
463 } else {
464 server->maxRw = 0;/* we do not need to use raw anyway */
465 server->capabilities = CAP_MPX_MODE;
466 }
467 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
468
469 /* BB get server time for time conversions and add
470 code to use it and timezone since this is not UTC */
471
472 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
473 memcpy(server->cryptKey, rsp->EncryptionKey,
474 CIFS_CRYPTO_KEY_SIZE);
475 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
476 rc = -EIO; /* need cryptkey unless plain text */
477 goto neg_err_exit;
478 }
479
480 cFYI(1,("LANMAN negotiated"));
481 /* we will not end up setting signing flags - as no signing
482 was in LANMAN and server did not return the flags on */
483 goto signing_check;
484#else /* weak security disabled */
485 } else if(pSMBr->hdr.WordCount == 13) {
486 cERROR(1,("mount failed, cifs module not built "
487 "with CIFS_WEAK_PW_HASH support"));
488 rc = -EOPNOTSUPP;
489#endif /* WEAK_PW_HASH */
490 goto neg_err_exit;
491 } else if(pSMBr->hdr.WordCount != 17) {
492 /* unknown wct */
493 rc = -EOPNOTSUPP;
494 goto neg_err_exit;
495 }
496 /* else wct == 17 NTLM */
497 server->secMode = pSMBr->SecurityMode;
498 if((server->secMode & SECMODE_USER) == 0)
499 cFYI(1,("share mode security"));
500
501 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
502#ifdef CONFIG_CIFS_WEAK_PW_HASH
503 if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0)
504#endif /* CIFS_WEAK_PW_HASH */
505 cERROR(1,("Server requests plain text password"
506 " but client support disabled"));
507
508 if(extended_security & CIFSSEC_MUST_NTLMV2)
509 server->secType = NTLMv2;
510 else
511 server->secType = NTLM;
512 /* else krb5 ... */
513
514 /* one byte, so no need to convert this or EncryptionKeyLen from
515 little endian */
516 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
517 /* probably no need to store and check maxvcs */
518 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
415 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 519 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
416 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 520 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
417 cFYI(0, ("Max buf = %d", ses->server->maxBuf)); 521 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
418 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 522 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
419 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 523 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
420 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); 524 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
421 /* BB with UTC do we ever need to be using srvr timezone? */ 525 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
422 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 526 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
423 memcpy(server->cryptKey, pSMBr->u.EncryptionKey, 527 CIFS_CRYPTO_KEY_SIZE);
424 CIFS_CRYPTO_KEY_SIZE); 528 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
425 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) 529 && (pSMBr->EncryptionKeyLength == 0)) {
426 && (pSMBr->EncryptionKeyLength == 0)) { 530 /* decode security blob */
427 /* decode security blob */ 531 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
428 } else 532 rc = -EIO; /* no crypt key only if plain text pwd */
429 rc = -EIO; 533 goto neg_err_exit;
534 }
430 535
431 /* BB might be helpful to save off the domain of server here */ 536 /* BB might be helpful to save off the domain of server here */
432 537
433 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 538 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
434 (server->capabilities & CAP_EXTENDED_SECURITY)) { 539 (server->capabilities & CAP_EXTENDED_SECURITY)) {
435 count = pSMBr->ByteCount; 540 count = pSMBr->ByteCount;
436 if (count < 16) 541 if (count < 16)
437 rc = -EIO; 542 rc = -EIO;
438 else if (count == 16) { 543 else if (count == 16) {
439 server->secType = RawNTLMSSP; 544 server->secType = RawNTLMSSP;
440 if (server->socketUseCount.counter > 1) { 545 if (server->socketUseCount.counter > 1) {
441 if (memcmp 546 if (memcmp(server->server_GUID,
442 (server->server_GUID, 547 pSMBr->u.extended_response.
443 pSMBr->u.extended_response. 548 GUID, 16) != 0) {
444 GUID, 16) != 0) { 549 cFYI(1, ("server UID changed"));
445 cFYI(1, ("server UID changed"));
446 memcpy(server->
447 server_GUID,
448 pSMBr->u.
449 extended_response.
450 GUID, 16);
451 }
452 } else
453 memcpy(server->server_GUID, 550 memcpy(server->server_GUID,
454 pSMBr->u.extended_response. 551 pSMBr->u.extended_response.GUID,
455 GUID, 16); 552 16);
456 } else {
457 rc = decode_negTokenInit(pSMBr->u.
458 extended_response.
459 SecurityBlob,
460 count - 16,
461 &server->secType);
462 if(rc == 1) {
463 /* BB Need to fill struct for sessetup here */
464 rc = -EOPNOTSUPP;
465 } else {
466 rc = -EINVAL;
467 } 553 }
554 } else
555 memcpy(server->server_GUID,
556 pSMBr->u.extended_response.GUID, 16);
557 } else {
558 rc = decode_negTokenInit(pSMBr->u.extended_response.
559 SecurityBlob,
560 count - 16,
561 &server->secType);
562 if(rc == 1) {
563 /* BB Need to fill struct for sessetup here */
564 rc = -EOPNOTSUPP;
565 } else {
566 rc = -EINVAL;
468 } 567 }
469 } else
470 server->capabilities &= ~CAP_EXTENDED_SECURITY;
471 if(sign_CIFS_PDUs == FALSE) {
472 if(server->secMode & SECMODE_SIGN_REQUIRED)
473 cERROR(1,
474 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
475 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
476 } else if(sign_CIFS_PDUs == 1) {
477 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
478 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
479 } 568 }
480 569 } else
570 server->capabilities &= ~CAP_EXTENDED_SECURITY;
571
572signing_check:
573 if(sign_CIFS_PDUs == FALSE) {
574 if(server->secMode & SECMODE_SIGN_REQUIRED)
575 cERROR(1,("Server requires "
576 "/proc/fs/cifs/PacketSigningEnabled to be on"));
577 server->secMode &=
578 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
579 } else if(sign_CIFS_PDUs == 1) {
580 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
581 server->secMode &=
582 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
583 } else if(sign_CIFS_PDUs == 2) {
584 if((server->secMode &
585 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
586 cERROR(1,("signing required but server lacks support"));
587 }
481 } 588 }
482 589neg_err_exit:
483 cifs_buf_release(pSMB); 590 cifs_buf_release(pSMB);
591
592 cFYI(1,("negprot rc %d",rc));
484 return rc; 593 return rc;
485} 594}
486 595
@@ -2239,7 +2348,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2239 } 2348 }
2240 symlinkinfo[buflen] = 0; /* just in case so the caller 2349 symlinkinfo[buflen] = 0; /* just in case so the caller
2241 does not go off the end of the buffer */ 2350 does not go off the end of the buffer */
2242 cFYI(1,("readlink result - %s ",symlinkinfo)); 2351 cFYI(1,("readlink result - %s",symlinkinfo));
2243 } 2352 }
2244 } 2353 }
2245qreparse_out: 2354qreparse_out:
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bae1479318d1..e6f3d2fff6c0 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -49,8 +49,6 @@
49 49
50static DECLARE_COMPLETION(cifsd_complete); 50static DECLARE_COMPLETION(cifsd_complete);
51 51
52extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24); 53 unsigned char *p24);
56 54
@@ -585,9 +583,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
585 /* merge response - fix up 1st*/ 583 /* merge response - fix up 1st*/
586 if(coalesce_t2(smb_buffer, 584 if(coalesce_t2(smb_buffer,
587 mid_entry->resp_buf)) { 585 mid_entry->resp_buf)) {
586 mid_entry->multiRsp = 1;
588 break; 587 break;
589 } else { 588 } else {
590 /* all parts received */ 589 /* all parts received */
590 mid_entry->multiEnd = 1;
591 goto multi_t2_fnd; 591 goto multi_t2_fnd;
592 } 592 }
593 } else { 593 } else {
@@ -632,9 +632,14 @@ multi_t2_fnd:
632 wake_up_process(task_to_wake); 632 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) 633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) { 634 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd!")); 635 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer, 636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr)); 637 sizeof(struct smb_hdr));
638#ifdef CONFIG_CIFS_DEBUG2
639 cifs_dump_detail(smb_buffer);
640 cifs_dump_mids(server);
641#endif /* CIFS_DEBUG2 */
642
638 } 643 }
639 } /* end while !EXITING */ 644 } /* end while !EXITING */
640 645
@@ -976,7 +981,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
976 } 981 }
977 /* BB are there cases in which a comma can be valid in 982 /* BB are there cases in which a comma can be valid in
978 a domain name and need special handling? */ 983 a domain name and need special handling? */
979 if (strnlen(value, 65) < 65) { 984 if (strnlen(value, 256) < 256) {
980 vol->domainname = value; 985 vol->domainname = value;
981 cFYI(1, ("Domain name set")); 986 cFYI(1, ("Domain name set"));
982 } else { 987 } else {
@@ -1762,9 +1767,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1762 if (volume_info.username) 1767 if (volume_info.username)
1763 strncpy(pSesInfo->userName, 1768 strncpy(pSesInfo->userName,
1764 volume_info.username,MAX_USERNAME_SIZE); 1769 volume_info.username,MAX_USERNAME_SIZE);
1765 if (volume_info.domainname) 1770 if (volume_info.domainname) {
1766 strncpy(pSesInfo->domainName, 1771 int len = strlen(volume_info.domainname);
1767 volume_info.domainname,MAX_USERNAME_SIZE); 1772 pSesInfo->domainName =
1773 kmalloc(len + 1, GFP_KERNEL);
1774 if(pSesInfo->domainName)
1775 strcpy(pSesInfo->domainName,
1776 volume_info.domainname);
1777 }
1768 pSesInfo->linux_uid = volume_info.linux_uid; 1778 pSesInfo->linux_uid = volume_info.linux_uid;
1769 down(&pSesInfo->sesSem); 1779 down(&pSesInfo->sesSem);
1770 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1780 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
@@ -1980,7 +1990,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1980 1990
1981static int 1991static int
1982CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, 1992CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1983 char session_key[CIFS_SESSION_KEY_SIZE], 1993 char session_key[CIFS_SESS_KEY_SIZE],
1984 const struct nls_table *nls_codepage) 1994 const struct nls_table *nls_codepage)
1985{ 1995{
1986 struct smb_hdr *smb_buffer; 1996 struct smb_hdr *smb_buffer;
@@ -2038,15 +2048,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2038 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 2048 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2039 2049
2040 pSMB->req_no_secext.CaseInsensitivePasswordLength = 2050 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2041 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2051 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2042 2052
2043 pSMB->req_no_secext.CaseSensitivePasswordLength = 2053 pSMB->req_no_secext.CaseSensitivePasswordLength =
2044 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2054 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2045 bcc_ptr = pByteArea(smb_buffer); 2055 bcc_ptr = pByteArea(smb_buffer);
2046 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2056 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2047 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2057 bcc_ptr += CIFS_SESS_KEY_SIZE;
2048 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2058 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2049 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2059 bcc_ptr += CIFS_SESS_KEY_SIZE;
2050 2060
2051 if (ses->capabilities & CAP_UNICODE) { 2061 if (ses->capabilities & CAP_UNICODE) {
2052 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ 2062 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
@@ -2054,7 +2064,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2054 bcc_ptr++; 2064 bcc_ptr++;
2055 } 2065 }
2056 if(user == NULL) 2066 if(user == NULL)
2057 bytes_returned = 0; /* skill null user */ 2067 bytes_returned = 0; /* skip null user */
2058 else 2068 else
2059 bytes_returned = 2069 bytes_returned =
2060 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, 2070 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
@@ -2635,8 +2645,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2635 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2645 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2636 if(sign_CIFS_PDUs) 2646 if(sign_CIFS_PDUs)
2637 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2647 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2638 if(ntlmv2_support) 2648/* if(ntlmv2_support)
2639 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; 2649 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2640 /* setup pointers to domain name and workstation name */ 2650 /* setup pointers to domain name and workstation name */
2641 bcc_ptr += SecurityBlobLength; 2651 bcc_ptr += SecurityBlobLength;
2642 2652
@@ -2994,14 +3004,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2994 SecurityBlob->LmChallengeResponse.Buffer = 0; 3004 SecurityBlob->LmChallengeResponse.Buffer = 0;
2995 3005
2996 SecurityBlob->NtChallengeResponse.Length = 3006 SecurityBlob->NtChallengeResponse.Length =
2997 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 3007 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2998 SecurityBlob->NtChallengeResponse.MaximumLength = 3008 SecurityBlob->NtChallengeResponse.MaximumLength =
2999 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 3009 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3000 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); 3010 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3001 SecurityBlob->NtChallengeResponse.Buffer = 3011 SecurityBlob->NtChallengeResponse.Buffer =
3002 cpu_to_le32(SecurityBlobLength); 3012 cpu_to_le32(SecurityBlobLength);
3003 SecurityBlobLength += CIFS_SESSION_KEY_SIZE; 3013 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3004 bcc_ptr += CIFS_SESSION_KEY_SIZE; 3014 bcc_ptr += CIFS_SESS_KEY_SIZE;
3005 3015
3006 if (ses->capabilities & CAP_UNICODE) { 3016 if (ses->capabilities & CAP_UNICODE) {
3007 if (domain == NULL) { 3017 if (domain == NULL) {
@@ -3340,22 +3350,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3340 bcc_ptr = &pSMB->Password[0]; 3350 bcc_ptr = &pSMB->Password[0];
3341 if((ses->server->secMode) & SECMODE_USER) { 3351 if((ses->server->secMode) & SECMODE_USER) {
3342 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ 3352 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3353 *bcc_ptr = 0; /* password is null byte */
3343 bcc_ptr++; /* skip password */ 3354 bcc_ptr++; /* skip password */
3355 /* already aligned so no need to do it below */
3344 } else { 3356 } else {
3345 pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); 3357 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3346 /* BB FIXME add code to fail this if NTLMv2 or Kerberos 3358 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3347 specified as required (when that support is added to 3359 specified as required (when that support is added to
3348 the vfs in the future) as only NTLM or the much 3360 the vfs in the future) as only NTLM or the much
3349 weaker LANMAN (which we do not send) is accepted 3361 weaker LANMAN (which we do not send by default) is accepted
3350 by Samba (not sure whether other servers allow 3362 by Samba (not sure whether other servers allow
3351 NTLMv2 password here) */ 3363 NTLMv2 password here) */
3364#ifdef CONFIG_CIFS_WEAK_PW_HASH
3365 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3366 (ses->server->secType == LANMAN))
3367 calc_lanman_hash(ses, bcc_ptr);
3368 else
3369#endif /* CIFS_WEAK_PW_HASH */
3352 SMBNTencrypt(ses->password, 3370 SMBNTencrypt(ses->password,
3353 ses->server->cryptKey, 3371 ses->server->cryptKey,
3354 bcc_ptr); 3372 bcc_ptr);
3355 3373
3356 bcc_ptr += CIFS_SESSION_KEY_SIZE; 3374 bcc_ptr += CIFS_SESS_KEY_SIZE;
3357 *bcc_ptr = 0; 3375 if(ses->capabilities & CAP_UNICODE) {
3358 bcc_ptr++; /* align */ 3376 /* must align unicode strings */
3377 *bcc_ptr = 0; /* null byte password */
3378 bcc_ptr++;
3379 }
3359 } 3380 }
3360 3381
3361 if(ses->server->secMode & 3382 if(ses->server->secMode &
@@ -3429,7 +3450,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3429 } 3450 }
3430 /* else do not bother copying these informational fields */ 3451 /* else do not bother copying these informational fields */
3431 } 3452 }
3432 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); 3453 if(smb_buffer_response->WordCount == 3)
3454 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3455 else
3456 tcon->Flags = 0;
3433 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); 3457 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3434 } else if ((rc == 0) && tcon == NULL) { 3458 } else if ((rc == 0) && tcon == NULL) {
3435 /* all we need to save for IPC$ connection */ 3459 /* all we need to save for IPC$ connection */
@@ -3494,7 +3518,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3494 struct nls_table * nls_info) 3518 struct nls_table * nls_info)
3495{ 3519{
3496 int rc = 0; 3520 int rc = 0;
3497 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 3521 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3498 int ntlmv2_flag = FALSE; 3522 int ntlmv2_flag = FALSE;
3499 int first_time = 0; 3523 int first_time = 0;
3500 3524
@@ -3528,8 +3552,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3528 pSesInfo->server->timeZone)); 3552 pSesInfo->server->timeZone));
3529#ifdef CONFIG_CIFS_EXPERIMENTAL 3553#ifdef CONFIG_CIFS_EXPERIMENTAL
3530 if(experimEnabled > 1) 3554 if(experimEnabled > 1)
3531 rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, 3555 rc = CIFS_SessSetup(xid, pSesInfo,
3532 &ntlmv2_flag, nls_info); 3556 first_time, nls_info);
3533 else 3557 else
3534#endif 3558#endif
3535 if (extended_security 3559 if (extended_security
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 82315edc77d7..ba4cbe9b0684 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -113,7 +113,7 @@ cifs_bp_rename_retry:
113 full_path[namelen+2] = 0; 113 full_path[namelen+2] = 0;
114BB remove above eight lines BB */ 114BB remove above eight lines BB */
115 115
116/* Inode operations in similar order to how they appear in the Linux file fs.h */ 116/* Inode operations in similar order to how they appear in Linux file fs.h */
117 117
118int 118int
119cifs_create(struct inode *inode, struct dentry *direntry, int mode, 119cifs_create(struct inode *inode, struct dentry *direntry, int mode,
@@ -178,11 +178,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
178 FreeXid(xid); 178 FreeXid(xid);
179 return -ENOMEM; 179 return -ENOMEM;
180 } 180 }
181 181 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
182 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 182 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
183 desiredAccess, CREATE_NOT_DIR, 183 desiredAccess, CREATE_NOT_DIR,
184 &fileHandle, &oplock, buf, cifs_sb->local_nls, 184 &fileHandle, &oplock, buf, cifs_sb->local_nls,
185 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 185 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
186 else
187 rc = -EIO; /* no NT SMB support fall into legacy open below */
188
186 if(rc == -EIO) { 189 if(rc == -EIO) {
187 /* old server, retry the open legacy style */ 190 /* old server, retry the open legacy style */
188 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 191 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -191,7 +194,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
191 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 194 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
192 } 195 }
193 if (rc) { 196 if (rc) {
194 cFYI(1, ("cifs_create returned 0x%x ", rc)); 197 cFYI(1, ("cifs_create returned 0x%x", rc));
195 } else { 198 } else {
196 /* If Open reported that we actually created a file 199 /* If Open reported that we actually created a file
197 then we now have to set the mode if possible */ 200 then we now have to set the mode if possible */
@@ -369,6 +372,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
369 cifs_sb->mnt_cifs_flags & 372 cifs_sb->mnt_cifs_flags &
370 CIFS_MOUNT_MAP_SPECIAL_CHR); 373 CIFS_MOUNT_MAP_SPECIAL_CHR);
371 374
375 /* BB FIXME - add handling for backlevel servers
376 which need legacy open and check for all
377 calls to SMBOpen for fallback to
378 SMBLeagcyOpen */
372 if(!rc) { 379 if(!rc) {
373 /* BB Do not bother to decode buf since no 380 /* BB Do not bother to decode buf since no
374 local inode yet to put timestamps in, 381 local inode yet to put timestamps in,
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 633a93811328..d91a3d44e9e3 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -91,14 +91,14 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
91 if(full_path == NULL) { 91 if(full_path == NULL) {
92 rc = -ENOMEM; 92 rc = -ENOMEM;
93 } else { 93 } else {
94 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ 94 cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
95 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 95 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
96 GENERIC_READ | SYNCHRONIZE, 0 /* create options */, 96 GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
97 &netfid, &oplock,NULL, cifs_sb->local_nls, 97 &netfid, &oplock,NULL, cifs_sb->local_nls,
98 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 98 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
99 /* BB fixme - add this handle to a notify handle list */ 99 /* BB fixme - add this handle to a notify handle list */
100 if(rc) { 100 if(rc) {
101 cERROR(1,("Could not open directory for notify")); /* BB remove BB */ 101 cFYI(1,("Could not open directory for notify"));
102 } else { 102 } else {
103 filter = convert_to_cifs_notify_flags(arg); 103 filter = convert_to_cifs_notify_flags(arg);
104 if(filter != 0) { 104 if(filter != 0) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e2b4ce1dad66..fafdcdffba62 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -201,7 +201,7 @@ int cifs_open(struct inode *inode, struct file *file)
201 } else { 201 } else {
202 if (file->f_flags & O_EXCL) 202 if (file->f_flags & O_EXCL)
203 cERROR(1, ("could not find file instance for " 203 cERROR(1, ("could not find file instance for "
204 "new file %p ", file)); 204 "new file %p", file));
205 } 205 }
206 } 206 }
207 207
@@ -260,10 +260,15 @@ int cifs_open(struct inode *inode, struct file *file)
260 rc = -ENOMEM; 260 rc = -ENOMEM;
261 goto out; 261 goto out;
262 } 262 }
263 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 263
264 CREATE_NOT_DIR, &netfid, &oplock, buf, 264 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
265 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
266 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
265 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 267 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
266 & CIFS_MOUNT_MAP_SPECIAL_CHR); 268 & CIFS_MOUNT_MAP_SPECIAL_CHR);
269 else
270 rc = -EIO; /* no NT SMB support fall into legacy open below */
271
267 if (rc == -EIO) { 272 if (rc == -EIO) {
268 /* Old server, try legacy style OpenX */ 273 /* Old server, try legacy style OpenX */
269 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 274 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -272,7 +277,7 @@ int cifs_open(struct inode *inode, struct file *file)
272 & CIFS_MOUNT_MAP_SPECIAL_CHR); 277 & CIFS_MOUNT_MAP_SPECIAL_CHR);
273 } 278 }
274 if (rc) { 279 if (rc) {
275 cFYI(1, ("cifs_open returned 0x%x ", rc)); 280 cFYI(1, ("cifs_open returned 0x%x", rc));
276 goto out; 281 goto out;
277 } 282 }
278 file->private_data = 283 file->private_data =
@@ -409,8 +414,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
409 CIFS_MOUNT_MAP_SPECIAL_CHR); 414 CIFS_MOUNT_MAP_SPECIAL_CHR);
410 if (rc) { 415 if (rc) {
411 up(&pCifsFile->fh_sem); 416 up(&pCifsFile->fh_sem);
412 cFYI(1, ("cifs_open returned 0x%x ", rc)); 417 cFYI(1, ("cifs_open returned 0x%x", rc));
413 cFYI(1, ("oplock: %d ", oplock)); 418 cFYI(1, ("oplock: %d", oplock));
414 } else { 419 } else {
415 pCifsFile->netfid = netfid; 420 pCifsFile->netfid = netfid;
416 pCifsFile->invalidHandle = FALSE; 421 pCifsFile->invalidHandle = FALSE;
@@ -531,7 +536,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
531 (struct cifsFileInfo *)file->private_data; 536 (struct cifsFileInfo *)file->private_data;
532 char *ptmp; 537 char *ptmp;
533 538
534 cFYI(1, ("Closedir inode = 0x%p with ", inode)); 539 cFYI(1, ("Closedir inode = 0x%p", inode));
535 540
536 xid = GetXid(); 541 xid = GetXid();
537 542
@@ -605,7 +610,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
605 } 610 }
606 if (pfLock->fl_flags & FL_ACCESS) 611 if (pfLock->fl_flags & FL_ACCESS)
607 cFYI(1, ("Process suspended by mandatory locking - " 612 cFYI(1, ("Process suspended by mandatory locking - "
608 "not implemented yet ")); 613 "not implemented yet"));
609 if (pfLock->fl_flags & FL_LEASE) 614 if (pfLock->fl_flags & FL_LEASE)
610 cFYI(1, ("Lease on file - not implemented yet")); 615 cFYI(1, ("Lease on file - not implemented yet"));
611 if (pfLock->fl_flags & 616 if (pfLock->fl_flags &
@@ -1377,7 +1382,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1377 1382
1378 xid = GetXid(); 1383 xid = GetXid();
1379 1384
1380 cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 1385 cFYI(1, ("Sync file - name: %s datasync: 0x%x",
1381 dentry->d_name.name, datasync)); 1386 dentry->d_name.name, datasync));
1382 1387
1383 rc = filemap_fdatawrite(inode->i_mapping); 1388 rc = filemap_fdatawrite(inode->i_mapping);
@@ -1406,7 +1411,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1406/* fill in rpages then 1411/* fill in rpages then
1407 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ 1412 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1408 1413
1409/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); 1414/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
1410 1415
1411#if 0 1416#if 0
1412 if (rc < 0) 1417 if (rc < 0)
@@ -1838,7 +1843,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
1838 if (rc < 0) 1843 if (rc < 0)
1839 goto io_error; 1844 goto io_error;
1840 else 1845 else
1841 cFYI(1, ("Bytes read %d ",rc)); 1846 cFYI(1, ("Bytes read %d",rc));
1842 1847
1843 file->f_dentry->d_inode->i_atime = 1848 file->f_dentry->d_inode->i_atime =
1844 current_fs_time(file->f_dentry->d_inode->i_sb); 1849 current_fs_time(file->f_dentry->d_inode->i_sb);
@@ -1959,3 +1964,19 @@ struct address_space_operations cifs_addr_ops = {
1959 /* .sync_page = cifs_sync_page, */ 1964 /* .sync_page = cifs_sync_page, */
1960 /* .direct_IO = */ 1965 /* .direct_IO = */
1961}; 1966};
1967
1968/*
1969 * cifs_readpages requires the server to support a buffer large enough to
1970 * contain the header plus one complete page of data. Otherwise, we need
1971 * to leave cifs_readpages out of the address space operations.
1972 */
1973struct address_space_operations cifs_addr_ops_smallbuf = {
1974 .readpage = cifs_readpage,
1975 .writepage = cifs_writepage,
1976 .writepages = cifs_writepages,
1977 .prepare_write = cifs_prepare_write,
1978 .commit_write = cifs_commit_write,
1979 .set_page_dirty = __set_page_dirty_nobuffers,
1980 /* .sync_page = cifs_sync_page, */
1981 /* .direct_IO = */
1982};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 4093764ef461..b88147c1dc27 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
41 char *tmp_path; 41 char *tmp_path;
42 42
43 pTcon = cifs_sb->tcon; 43 pTcon = cifs_sb->tcon;
44 cFYI(1, ("Getting info on %s ", search_path)); 44 cFYI(1, ("Getting info on %s", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
97 inode = *pinode; 97 inode = *pinode;
98 cifsInfo = CIFS_I(inode); 98 cifsInfo = CIFS_I(inode);
99 99
100 cFYI(1, ("Old time %ld ", cifsInfo->time)); 100 cFYI(1, ("Old time %ld", cifsInfo->time));
101 cifsInfo->time = jiffies; 101 cifsInfo->time = jiffies;
102 cFYI(1, ("New time %ld ", cifsInfo->time)); 102 cFYI(1, ("New time %ld", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */ 103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1); 104 atomic_set(&cifsInfo->inUse,1);
105 105
@@ -180,11 +180,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
180 else /* not direct, send byte range locks */ 180 else /* not direct, send byte range locks */
181 inode->i_fop = &cifs_file_ops; 181 inode->i_fop = &cifs_file_ops;
182 182
183 inode->i_data.a_ops = &cifs_addr_ops;
184 /* check if server can support readpages */ 183 /* check if server can support readpages */
185 if(pTcon->ses->server->maxBuf < 184 if(pTcon->ses->server->maxBuf <
186 4096 + MAX_CIFS_HDR_SIZE) 185 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
187 inode->i_data.a_ops->readpages = NULL; 186 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
187 else
188 inode->i_data.a_ops = &cifs_addr_ops;
188 } else if (S_ISDIR(inode->i_mode)) { 189 } else if (S_ISDIR(inode->i_mode)) {
189 cFYI(1, ("Directory inode")); 190 cFYI(1, ("Directory inode"));
190 inode->i_op = &cifs_dir_inode_ops; 191 inode->i_op = &cifs_dir_inode_ops;
@@ -421,23 +422,23 @@ int cifs_get_inode_info(struct inode **pinode,
421 inode = *pinode; 422 inode = *pinode;
422 cifsInfo = CIFS_I(inode); 423 cifsInfo = CIFS_I(inode);
423 cifsInfo->cifsAttrs = attr; 424 cifsInfo->cifsAttrs = attr;
424 cFYI(1, ("Old time %ld ", cifsInfo->time)); 425 cFYI(1, ("Old time %ld", cifsInfo->time));
425 cifsInfo->time = jiffies; 426 cifsInfo->time = jiffies;
426 cFYI(1, ("New time %ld ", cifsInfo->time)); 427 cFYI(1, ("New time %ld", cifsInfo->time));
427 428
428 /* blksize needs to be multiple of two. So safer to default to 429 /* blksize needs to be multiple of two. So safer to default to
429 blksize and blkbits set in superblock so 2**blkbits and blksize 430 blksize and blkbits set in superblock so 2**blkbits and blksize
430 will match rather than setting to: 431 will match rather than setting to:
431 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ 432 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
432 433
433 /* Linux can not store file creation time unfortunately so we ignore it */ 434 /* Linux can not store file creation time so ignore it */
434 inode->i_atime = 435 inode->i_atime =
435 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 436 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
436 inode->i_mtime = 437 inode->i_mtime =
437 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 438 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
438 inode->i_ctime = 439 inode->i_ctime =
439 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 440 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
440 cFYI(0, ("Attributes came in as 0x%x ", attr)); 441 cFYI(0, ("Attributes came in as 0x%x", attr));
441 442
442 /* set default mode. will override for dirs below */ 443 /* set default mode. will override for dirs below */
443 if (atomic_read(&cifsInfo->inUse) == 0) 444 if (atomic_read(&cifsInfo->inUse) == 0)
@@ -519,10 +520,11 @@ int cifs_get_inode_info(struct inode **pinode,
519 else /* not direct, send byte range locks */ 520 else /* not direct, send byte range locks */
520 inode->i_fop = &cifs_file_ops; 521 inode->i_fop = &cifs_file_ops;
521 522
522 inode->i_data.a_ops = &cifs_addr_ops;
523 if(pTcon->ses->server->maxBuf < 523 if(pTcon->ses->server->maxBuf <
524 4096 + MAX_CIFS_HDR_SIZE) 524 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
525 inode->i_data.a_ops->readpages = NULL; 525 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
526 else
527 inode->i_data.a_ops = &cifs_addr_ops;
526 } else if (S_ISDIR(inode->i_mode)) { 528 } else if (S_ISDIR(inode->i_mode)) {
527 cFYI(1, ("Directory inode")); 529 cFYI(1, ("Directory inode"));
528 inode->i_op = &cifs_dir_inode_ops; 530 inode->i_op = &cifs_dir_inode_ops;
@@ -731,7 +733,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
731 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, 733 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
732 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 734 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
733 if (rc) { 735 if (rc) {
734 cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); 736 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
735 d_drop(direntry); 737 d_drop(direntry);
736 } else { 738 } else {
737 inode->i_nlink++; 739 inode->i_nlink++;
@@ -798,7 +800,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
798 char *full_path = NULL; 800 char *full_path = NULL;
799 struct cifsInodeInfo *cifsInode; 801 struct cifsInodeInfo *cifsInode;
800 802
801 cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode)); 803 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
802 804
803 xid = GetXid(); 805 xid = GetXid();
804 806
@@ -1121,7 +1123,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1121 1123
1122 xid = GetXid(); 1124 xid = GetXid();
1123 1125
1124 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ", 1126 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1125 direntry->d_name.name, attrs->ia_valid)); 1127 direntry->d_name.name, attrs->ia_valid));
1126 1128
1127 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1129 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
@@ -1157,6 +1159,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1157 when the local oplock break takes longer to flush 1159 when the local oplock break takes longer to flush
1158 writebehind data than the SMB timeout for the SetPathInfo 1160 writebehind data than the SMB timeout for the SetPathInfo
1159 request would allow */ 1161 request would allow */
1162
1160 open_file = find_writable_file(cifsInode); 1163 open_file = find_writable_file(cifsInode);
1161 if (open_file) { 1164 if (open_file) {
1162 __u16 nfid = open_file->netfid; 1165 __u16 nfid = open_file->netfid;
@@ -1289,7 +1292,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1289 it may be useful to Windows - but we do 1292 it may be useful to Windows - but we do
1290 not want to set ctime unless some other 1293 not want to set ctime unless some other
1291 timestamp is changing */ 1294 timestamp is changing */
1292 cFYI(1, ("CIFS - CTIME changed ")); 1295 cFYI(1, ("CIFS - CTIME changed"));
1293 time_buf.ChangeTime = 1296 time_buf.ChangeTime =
1294 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); 1297 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1295 } else 1298 } else
@@ -1356,7 +1359,7 @@ cifs_setattr_exit:
1356 1359
1357void cifs_delete_inode(struct inode *inode) 1360void cifs_delete_inode(struct inode *inode)
1358{ 1361{
1359 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode)); 1362 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1360 /* may have to add back in if and when safe distributed caching of 1363 /* may have to add back in if and when safe distributed caching of
1361 directories added e.g. via FindNotify */ 1364 directories added e.g. via FindNotify */
1362} 1365}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 2ec99f833142..a57f5d6e6213 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -167,7 +167,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
167 return -ENOMEM; 167 return -ENOMEM;
168 } 168 }
169 169
170 cFYI(1, ("Full path: %s ", full_path)); 170 cFYI(1, ("Full path: %s", full_path));
171 cFYI(1, ("symname is %s", symname)); 171 cFYI(1, ("symname is %s", symname));
172 172
173 /* BB what if DFS and this volume is on different share? BB */ 173 /* BB what if DFS and this volume is on different share? BB */
@@ -186,8 +186,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
186 inode->i_sb,xid); 186 inode->i_sb,xid);
187 187
188 if (rc != 0) { 188 if (rc != 0) {
189 cFYI(1, 189 cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
190 ("Create symlink worked but get_inode_info failed with rc = %d ",
191 rc)); 190 rc));
192 } else { 191 } else {
193 if (pTcon->nocase) 192 if (pTcon->nocase)
@@ -289,7 +288,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
289 else { 288 else {
290 cFYI(1,("num referral: %d",num_referrals)); 289 cFYI(1,("num referral: %d",num_referrals));
291 if(referrals) { 290 if(referrals) {
292 cFYI(1,("referral string: %s ",referrals)); 291 cFYI(1,("referral string: %s",referrals));
293 strncpy(tmpbuffer, referrals, len-1); 292 strncpy(tmpbuffer, referrals, len-1);
294 } 293 }
295 } 294 }
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index fafd056426e4..22c937e5884f 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -101,6 +101,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
101 kfree(buf_to_free->serverDomain); 101 kfree(buf_to_free->serverDomain);
102 kfree(buf_to_free->serverNOS); 102 kfree(buf_to_free->serverNOS);
103 kfree(buf_to_free->password); 103 kfree(buf_to_free->password);
104 kfree(buf_to_free->domainName);
104 kfree(buf_to_free); 105 kfree(buf_to_free);
105} 106}
106 107
@@ -499,11 +500,12 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
499 if(pSMBr->ByteCount > sizeof(struct file_notify_information)) { 500 if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
500 data_offset = le32_to_cpu(pSMBr->DataOffset); 501 data_offset = le32_to_cpu(pSMBr->DataOffset);
501 502
502 pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol 503 pnotify = (struct file_notify_information *)
503 + data_offset); 504 ((char *)&pSMBr->hdr.Protocol + data_offset);
504 cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName, 505 cFYI(1,("dnotify on %s Action: 0x%x",pnotify->FileName,
505 pnotify->Action)); /* BB removeme BB */ 506 pnotify->Action)); /* BB removeme BB */
506 /* cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */ 507 /* cifs_dump_mem("Rcvd notify Data: ",buf,
508 sizeof(struct smb_hdr)+60); */
507 return TRUE; 509 return TRUE;
508 } 510 }
509 if(pSMBr->hdr.Status.CifsError) { 511 if(pSMBr->hdr.Status.CifsError) {
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 5de74d216fdd..b66eff5dc624 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -84,11 +84,11 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
84 84
85static const struct smb_to_posix_error mapping_table_ERRSRV[] = { 85static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
86 {ERRerror, -EIO}, 86 {ERRerror, -EIO},
87 {ERRbadpw, -EPERM}, 87 {ERRbadpw, -EACCES}, /* was EPERM */
88 {ERRbadtype, -EREMOTE}, 88 {ERRbadtype, -EREMOTE},
89 {ERRaccess, -EACCES}, 89 {ERRaccess, -EACCES},
90 {ERRinvtid, -ENXIO}, 90 {ERRinvtid, -ENXIO},
91 {ERRinvnetname, -ENODEV}, 91 {ERRinvnetname, -ENXIO},
92 {ERRinvdevice, -ENXIO}, 92 {ERRinvdevice, -ENXIO},
93 {ERRqfull, -ENOSPC}, 93 {ERRqfull, -ENOSPC},
94 {ERRqtoobig, -ENOSPC}, 94 {ERRqtoobig, -ENOSPC},
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
deleted file mode 100644
index 115359cc7a32..000000000000
--- a/fs/cifs/ntlmssp.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 * fs/cifs/ntlmssp.h
3 *
4 * Copyright (c) International Business Machines Corp., 2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "cifspdu.h"
23#include "cifsglob.h"
24#include "cifsproto.h"
25#include "cifs_unicode.h"
26#include "cifs_debug.h"
27#include "ntlmssp.h"
28#include "nterr.h"
29
30#ifdef CONFIG_CIFS_EXPERIMENTAL
31static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
32{
33 __u32 capabilities = 0;
34
35 /* init fields common to all four types of SessSetup */
36 /* note that header is initialized to zero in header_assemble */
37 pSMB->req.AndXCommand = 0xFF;
38 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
39 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
40
41 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
42
43 /* BB verify whether signing required on neg or just on auth frame
44 (and NTLM case) */
45
46 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
47 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
48
49 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
50 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
51
52 if (ses->capabilities & CAP_UNICODE) {
53 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
54 capabilities |= CAP_UNICODE;
55 }
56 if (ses->capabilities & CAP_STATUS32) {
57 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
58 capabilities |= CAP_STATUS32;
59 }
60 if (ses->capabilities & CAP_DFS) {
61 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
62 capabilities |= CAP_DFS;
63 }
64
65 /* BB check whether to init vcnum BB */
66 return capabilities;
67}
68int
69CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
70 int * pNTLMv2_flg, const struct nls_table *nls_cp)
71{
72 int rc = 0;
73 int wct;
74 struct smb_hdr *smb_buffer;
75 char *bcc_ptr;
76 SESSION_SETUP_ANDX *pSMB;
77 __u32 capabilities;
78
79 if(ses == NULL)
80 return -EINVAL;
81
82 cFYI(1,("SStp type: %d",type));
83 if(type < CIFS_NTLM) {
84#ifndef CONFIG_CIFS_WEAK_PW_HASH
85 /* LANMAN and plaintext are less secure and off by default.
86 So we make this explicitly be turned on in kconfig (in the
87 build) and turned on at runtime (changed from the default)
88 in proc/fs/cifs or via mount parm. Unfortunately this is
89 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
90 return -EOPNOTSUPP;
91#endif
92 wct = 10; /* lanman 2 style sessionsetup */
93 } else if(type < CIFS_NTLMSSP_NEG)
94 wct = 13; /* old style NTLM sessionsetup */
95 else /* same size for negotiate or auth, NTLMSSP or extended security */
96 wct = 12;
97
98 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
99 (void **)&smb_buffer);
100 if(rc)
101 return rc;
102
103 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
104
105 capabilities = cifs_ssetup_hdr(ses, pSMB);
106 bcc_ptr = pByteArea(smb_buffer);
107 if(type > CIFS_NTLM) {
108 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
109 capabilities |= CAP_EXTENDED_SECURITY;
110 pSMB->req.Capabilities = cpu_to_le32(capabilities);
111 /* BB set password lengths */
112 } else if(type < CIFS_NTLM) /* lanman */ {
113 /* no capabilities flags in old lanman negotiation */
114 /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
115 } else /* type CIFS_NTLM */ {
116 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
117 pSMB->req_no_secext.CaseInsensitivePasswordLength =
118 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
119 pSMB->req_no_secext.CaseSensitivePasswordLength =
120 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
121 }
122
123
124 /* copy session key */
125
126 /* if Unicode, align strings to two byte boundary */
127
128 /* copy user name */ /* BB Do we need to special case null user name? */
129
130 /* copy domain name */
131
132 /* copy Linux version */
133
134 /* copy network operating system name */
135
136 /* update bcc and smb buffer length */
137
138/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
139 /* SMB request buf freed in SendReceive2 */
140
141 return rc;
142}
143#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b689c5035124..03bbcb377913 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -21,6 +21,7 @@
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/pagemap.h>
24#include <linux/stat.h> 25#include <linux/stat.h>
25#include <linux/smp_lock.h> 26#include <linux/smp_lock.h>
26#include "cifspdu.h" 27#include "cifspdu.h"
@@ -31,8 +32,8 @@
31#include "cifs_fs_sb.h" 32#include "cifs_fs_sb.h"
32#include "cifsfs.h" 33#include "cifsfs.h"
33 34
34/* BB fixme - add debug wrappers around this function to disable it fixme BB */ 35#ifdef CONFIG_CIFS_DEBUG2
35/* static void dump_cifs_file_struct(struct file *file, char *label) 36static void dump_cifs_file_struct(struct file *file, char *label)
36{ 37{
37 struct cifsFileInfo * cf; 38 struct cifsFileInfo * cf;
38 39
@@ -53,7 +54,8 @@
53 } 54 }
54 55
55 } 56 }
56} */ 57}
58#endif /* DEBUG2 */
57 59
58/* Returns one if new inode created (which therefore needs to be hashed) */ 60/* Returns one if new inode created (which therefore needs to be hashed) */
59/* Might check in the future if inode number changed so we can rehash inode */ 61/* Might check in the future if inode number changed so we can rehash inode */
@@ -107,32 +109,52 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
107 return rc; 109 return rc;
108} 110}
109 111
110static void fill_in_inode(struct inode *tmp_inode, 112static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
111 FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode) 113 char * buf, int *pobject_type, int isNewInode)
112{ 114{
113 loff_t local_size; 115 loff_t local_size;
114 struct timespec local_mtime; 116 struct timespec local_mtime;
115 117
116 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 118 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
117 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 119 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
118 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes); 120 __u32 attr;
119 __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize); 121 __u64 allocation_size;
120 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); 122 __u64 end_of_file;
121
122 cifsInfo->cifsAttrs = attr;
123 cifsInfo->time = jiffies;
124 123
125 /* save mtime and size */ 124 /* save mtime and size */
126 local_mtime = tmp_inode->i_mtime; 125 local_mtime = tmp_inode->i_mtime;
127 local_size = tmp_inode->i_size; 126 local_size = tmp_inode->i_size;
128 127
128 if(new_buf_type) {
129 FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
130
131 attr = le32_to_cpu(pfindData->ExtFileAttributes);
132 allocation_size = le64_to_cpu(pfindData->AllocationSize);
133 end_of_file = le64_to_cpu(pfindData->EndOfFile);
134 tmp_inode->i_atime =
135 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
136 tmp_inode->i_mtime =
137 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
138 tmp_inode->i_ctime =
139 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
140 } else { /* legacy, OS2 and DOS style */
141 FIND_FILE_STANDARD_INFO * pfindData =
142 (FIND_FILE_STANDARD_INFO *)buf;
143
144 attr = le16_to_cpu(pfindData->Attributes);
145 allocation_size = le32_to_cpu(pfindData->AllocationSize);
146 end_of_file = le32_to_cpu(pfindData->DataSize);
147 tmp_inode->i_atime = CURRENT_TIME;
148 /* tmp_inode->i_mtime = BB FIXME - add dos time handling
149 tmp_inode->i_ctime = 0; BB FIXME */
150
151 }
152
129 /* Linux can not store file creation time unfortunately so ignore it */ 153 /* Linux can not store file creation time unfortunately so ignore it */
130 tmp_inode->i_atime = 154
131 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 155 cifsInfo->cifsAttrs = attr;
132 tmp_inode->i_mtime = 156 cifsInfo->time = jiffies;
133 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 157
134 tmp_inode->i_ctime =
135 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
136 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ 158 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
137 /* 2767 perms - indicate mandatory locking */ 159 /* 2767 perms - indicate mandatory locking */
138 /* BB fill in uid and gid here? with help from winbind? 160 /* BB fill in uid and gid here? with help from winbind?
@@ -215,11 +237,13 @@ static void fill_in_inode(struct inode *tmp_inode,
215 else 237 else
216 tmp_inode->i_fop = &cifs_file_ops; 238 tmp_inode->i_fop = &cifs_file_ops;
217 239
218 tmp_inode->i_data.a_ops = &cifs_addr_ops;
219 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 240 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
220 (cifs_sb->tcon->ses->server->maxBuf < 241 (cifs_sb->tcon->ses->server->maxBuf <
221 4096 + MAX_CIFS_HDR_SIZE)) 242 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
222 tmp_inode->i_data.a_ops->readpages = NULL; 243 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
244 else
245 tmp_inode->i_data.a_ops = &cifs_addr_ops;
246
223 if(isNewInode) 247 if(isNewInode)
224 return; /* No sense invalidating pages for new inode 248 return; /* No sense invalidating pages for new inode
225 since have not started caching readahead file 249 since have not started caching readahead file
@@ -338,11 +362,12 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
338 else 362 else
339 tmp_inode->i_fop = &cifs_file_ops; 363 tmp_inode->i_fop = &cifs_file_ops;
340 364
341 tmp_inode->i_data.a_ops = &cifs_addr_ops;
342 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 365 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
343 (cifs_sb->tcon->ses->server->maxBuf < 366 (cifs_sb->tcon->ses->server->maxBuf <
344 4096 + MAX_CIFS_HDR_SIZE)) 367 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
345 tmp_inode->i_data.a_ops->readpages = NULL; 368 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
369 else
370 tmp_inode->i_data.a_ops = &cifs_addr_ops;
346 371
347 if(isNewInode) 372 if(isNewInode)
348 return; /* No sense invalidating pages for new inode since we 373 return; /* No sense invalidating pages for new inode since we
@@ -415,7 +440,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
415ffirst_retry: 440ffirst_retry:
416 /* test for Unix extensions */ 441 /* test for Unix extensions */
417 if (pTcon->ses->capabilities & CAP_UNIX) { 442 if (pTcon->ses->capabilities & CAP_UNIX) {
418 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 443 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
444 } else if ((pTcon->ses->capabilities &
445 (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
446 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
419 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 447 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
420 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; 448 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
421 } else /* not srvinos - BB fixme add check for backlevel? */ { 449 } else /* not srvinos - BB fixme add check for backlevel? */ {
@@ -451,12 +479,19 @@ static int cifs_unicode_bytelen(char *str)
451 return len << 1; 479 return len << 1;
452} 480}
453 481
454static char *nxt_dir_entry(char *old_entry, char *end_of_smb) 482static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
455{ 483{
456 char * new_entry; 484 char * new_entry;
457 FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; 485 FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
458 486
459 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); 487 if(level == SMB_FIND_FILE_INFO_STANDARD) {
488 FIND_FILE_STANDARD_INFO * pfData;
489 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
490
491 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
492 pfData->FileNameLength;
493 } else
494 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
460 cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); 495 cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
461 /* validate that new_entry is not past end of SMB */ 496 /* validate that new_entry is not past end of SMB */
462 if(new_entry >= end_of_smb) { 497 if(new_entry >= end_of_smb) {
@@ -464,7 +499,10 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
464 ("search entry %p began after end of SMB %p old entry %p", 499 ("search entry %p began after end of SMB %p old entry %p",
465 new_entry, end_of_smb, old_entry)); 500 new_entry, end_of_smb, old_entry));
466 return NULL; 501 return NULL;
467 } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) { 502 } else if(((level == SMB_FIND_FILE_INFO_STANDARD) &&
503 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
504 ((level != SMB_FIND_FILE_INFO_STANDARD) &&
505 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
468 cERROR(1,("search entry %p extends after end of SMB %p", 506 cERROR(1,("search entry %p extends after end of SMB %p",
469 new_entry, end_of_smb)); 507 new_entry, end_of_smb));
470 return NULL; 508 return NULL;
@@ -482,7 +520,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
482 char * filename = NULL; 520 char * filename = NULL;
483 int len = 0; 521 int len = 0;
484 522
485 if(cfile->srch_inf.info_level == 0x202) { 523 if(cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
486 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; 524 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
487 filename = &pFindData->FileName[0]; 525 filename = &pFindData->FileName[0];
488 if(cfile->srch_inf.unicode) { 526 if(cfile->srch_inf.unicode) {
@@ -491,26 +529,34 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
491 /* BB should we make this strnlen of PATH_MAX? */ 529 /* BB should we make this strnlen of PATH_MAX? */
492 len = strnlen(filename, 5); 530 len = strnlen(filename, 5);
493 } 531 }
494 } else if(cfile->srch_inf.info_level == 0x101) { 532 } else if(cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
495 FILE_DIRECTORY_INFO * pFindData = 533 FILE_DIRECTORY_INFO * pFindData =
496 (FILE_DIRECTORY_INFO *)current_entry; 534 (FILE_DIRECTORY_INFO *)current_entry;
497 filename = &pFindData->FileName[0]; 535 filename = &pFindData->FileName[0];
498 len = le32_to_cpu(pFindData->FileNameLength); 536 len = le32_to_cpu(pFindData->FileNameLength);
499 } else if(cfile->srch_inf.info_level == 0x102) { 537 } else if(cfile->srch_inf.info_level ==
538 SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
500 FILE_FULL_DIRECTORY_INFO * pFindData = 539 FILE_FULL_DIRECTORY_INFO * pFindData =
501 (FILE_FULL_DIRECTORY_INFO *)current_entry; 540 (FILE_FULL_DIRECTORY_INFO *)current_entry;
502 filename = &pFindData->FileName[0]; 541 filename = &pFindData->FileName[0];
503 len = le32_to_cpu(pFindData->FileNameLength); 542 len = le32_to_cpu(pFindData->FileNameLength);
504 } else if(cfile->srch_inf.info_level == 0x105) { 543 } else if(cfile->srch_inf.info_level ==
544 SMB_FIND_FILE_ID_FULL_DIR_INFO) {
505 SEARCH_ID_FULL_DIR_INFO * pFindData = 545 SEARCH_ID_FULL_DIR_INFO * pFindData =
506 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 546 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
507 filename = &pFindData->FileName[0]; 547 filename = &pFindData->FileName[0];
508 len = le32_to_cpu(pFindData->FileNameLength); 548 len = le32_to_cpu(pFindData->FileNameLength);
509 } else if(cfile->srch_inf.info_level == 0x104) { 549 } else if(cfile->srch_inf.info_level ==
550 SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
510 FILE_BOTH_DIRECTORY_INFO * pFindData = 551 FILE_BOTH_DIRECTORY_INFO * pFindData =
511 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 552 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
512 filename = &pFindData->FileName[0]; 553 filename = &pFindData->FileName[0];
513 len = le32_to_cpu(pFindData->FileNameLength); 554 len = le32_to_cpu(pFindData->FileNameLength);
555 } else if(cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
556 FIND_FILE_STANDARD_INFO * pFindData =
557 (FIND_FILE_STANDARD_INFO *)current_entry;
558 filename = &pFindData->FileName[0];
559 len = le32_to_cpu(pFindData->FileNameLength);
514 } else { 560 } else {
515 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level)); 561 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
516 } 562 }
@@ -597,7 +643,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
597 . and .. for the root of a drive and for those we need 643 . and .. for the root of a drive and for those we need
598 to start two entries earlier */ 644 to start two entries earlier */
599 645
600/* dump_cifs_file_struct(file, "In fce ");*/ 646#ifdef CONFIG_CIFS_DEBUG2
647 dump_cifs_file_struct(file, "In fce ");
648#endif
601 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 649 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
602 is_dir_changed(file)) || 650 is_dir_changed(file)) ||
603 (index_to_find < first_entry_in_buffer)) { 651 (index_to_find < first_entry_in_buffer)) {
@@ -644,10 +692,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
644 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry 692 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
645 - cifsFile->srch_inf.entries_in_buffer; 693 - cifsFile->srch_inf.entries_in_buffer;
646 pos_in_buf = index_to_find - first_entry_in_buffer; 694 pos_in_buf = index_to_find - first_entry_in_buffer;
647 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 695 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
696
648 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 697 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
649 /* go entry by entry figuring out which is first */ 698 /* go entry by entry figuring out which is first */
650 current_entry = nxt_dir_entry(current_entry,end_of_smb); 699 current_entry = nxt_dir_entry(current_entry,end_of_smb,
700 cifsFile->srch_inf.info_level);
651 } 701 }
652 if((current_entry == NULL) && (i < pos_in_buf)) { 702 if((current_entry == NULL) && (i < pos_in_buf)) {
653 /* BB fixme - check if we should flag this error */ 703 /* BB fixme - check if we should flag this error */
@@ -674,7 +724,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
674/* inode num, inode type and filename returned */ 724/* inode num, inode type and filename returned */
675static int cifs_get_name_from_search_buf(struct qstr *pqst, 725static int cifs_get_name_from_search_buf(struct qstr *pqst,
676 char *current_entry, __u16 level, unsigned int unicode, 726 char *current_entry, __u16 level, unsigned int unicode,
677 struct cifs_sb_info * cifs_sb, ino_t *pinum) 727 struct cifs_sb_info * cifs_sb, int max_len, ino_t *pinum)
678{ 728{
679 int rc = 0; 729 int rc = 0;
680 unsigned int len = 0; 730 unsigned int len = 0;
@@ -718,10 +768,22 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
718 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 768 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
719 filename = &pFindData->FileName[0]; 769 filename = &pFindData->FileName[0];
720 len = le32_to_cpu(pFindData->FileNameLength); 770 len = le32_to_cpu(pFindData->FileNameLength);
771 } else if(level == SMB_FIND_FILE_INFO_STANDARD) {
772 FIND_FILE_STANDARD_INFO * pFindData =
773 (FIND_FILE_STANDARD_INFO *)current_entry;
774 filename = &pFindData->FileName[0];
775 /* one byte length, no name conversion */
776 len = (unsigned int)pFindData->FileNameLength;
721 } else { 777 } else {
722 cFYI(1,("Unknown findfirst level %d",level)); 778 cFYI(1,("Unknown findfirst level %d",level));
723 return -EINVAL; 779 return -EINVAL;
724 } 780 }
781
782 if(len > max_len) {
783 cERROR(1,("bad search response length %d past smb end", len));
784 return -EINVAL;
785 }
786
725 if(unicode) { 787 if(unicode) {
726 /* BB fixme - test with long names */ 788 /* BB fixme - test with long names */
727 /* Note converted filename can be longer than in unicode */ 789 /* Note converted filename can be longer than in unicode */
@@ -741,7 +803,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
741} 803}
742 804
743static int cifs_filldir(char *pfindEntry, struct file *file, 805static int cifs_filldir(char *pfindEntry, struct file *file,
744 filldir_t filldir, void *direntry, char *scratch_buf) 806 filldir_t filldir, void *direntry, char *scratch_buf, int max_len)
745{ 807{
746 int rc = 0; 808 int rc = 0;
747 struct qstr qstring; 809 struct qstr qstring;
@@ -777,6 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
777 rc = cifs_get_name_from_search_buf(&qstring,pfindEntry, 839 rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
778 pCifsF->srch_inf.info_level, 840 pCifsF->srch_inf.info_level,
779 pCifsF->srch_inf.unicode,cifs_sb, 841 pCifsF->srch_inf.unicode,cifs_sb,
842 max_len,
780 &inum /* returned */); 843 &inum /* returned */);
781 844
782 if(rc) 845 if(rc)
@@ -798,13 +861,16 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
798 /* we pass in rc below, indicating whether it is a new inode, 861 /* we pass in rc below, indicating whether it is a new inode,
799 so we can figure out whether to invalidate the inode cached 862 so we can figure out whether to invalidate the inode cached
800 data if the file has changed */ 863 data if the file has changed */
801 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { 864 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
802 unix_fill_in_inode(tmp_inode, 865 unix_fill_in_inode(tmp_inode,
803 (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc); 866 (FILE_UNIX_INFO *)pfindEntry,
804 } else { 867 &obj_type, rc);
805 fill_in_inode(tmp_inode, 868 else if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
806 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 869 fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
807 } 870 pfindEntry, &obj_type, rc);
871 else
872 fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
873
808 874
809 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos, 875 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
810 tmp_inode->i_ino,obj_type); 876 tmp_inode->i_ino,obj_type);
@@ -864,6 +930,12 @@ static int cifs_save_resume_key(const char *current_entry,
864 filename = &pFindData->FileName[0]; 930 filename = &pFindData->FileName[0];
865 len = le32_to_cpu(pFindData->FileNameLength); 931 len = le32_to_cpu(pFindData->FileNameLength);
866 cifsFile->srch_inf.resume_key = pFindData->FileIndex; 932 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
933 } else if(level == SMB_FIND_FILE_INFO_STANDARD) {
934 FIND_FILE_STANDARD_INFO * pFindData =
935 (FIND_FILE_STANDARD_INFO *)current_entry;
936 filename = &pFindData->FileName[0];
937 /* one byte length, no name conversion */
938 len = (unsigned int)pFindData->FileNameLength;
867 } else { 939 } else {
868 cFYI(1,("Unknown findfirst level %d",level)); 940 cFYI(1,("Unknown findfirst level %d",level));
869 return -EINVAL; 941 return -EINVAL;
@@ -884,6 +956,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
884 int num_to_fill = 0; 956 int num_to_fill = 0;
885 char * tmp_buf = NULL; 957 char * tmp_buf = NULL;
886 char * end_of_smb; 958 char * end_of_smb;
959 int max_len;
887 960
888 xid = GetXid(); 961 xid = GetXid();
889 962
@@ -909,7 +982,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
909 case 1: 982 case 1:
910 if (filldir(direntry, "..", 2, file->f_pos, 983 if (filldir(direntry, "..", 2, file->f_pos,
911 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { 984 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
912 cERROR(1, ("Filldir for parent dir failed ")); 985 cERROR(1, ("Filldir for parent dir failed"));
913 rc = -ENOMEM; 986 rc = -ENOMEM;
914 break; 987 break;
915 } 988 }
@@ -959,10 +1032,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
959 goto rddir2_exit; 1032 goto rddir2_exit;
960 } 1033 }
961 cFYI(1,("loop through %d times filling dir for net buf %p", 1034 cFYI(1,("loop through %d times filling dir for net buf %p",
962 num_to_fill,cifsFile->srch_inf.ntwrk_buf_start)); 1035 num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
963 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 1036 max_len = smbCalcSize((struct smb_hdr *)
964 smbCalcSize((struct smb_hdr *) 1037 cifsFile->srch_inf.ntwrk_buf_start);
965 cifsFile->srch_inf.ntwrk_buf_start); 1038 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
1039
966 /* To be safe - for UCS to UTF-8 with strings loaded 1040 /* To be safe - for UCS to UTF-8 with strings loaded
967 with the rare long characters alloc more to account for 1041 with the rare long characters alloc more to account for
968 such multibyte target UTF-8 characters. cifs_unicode.c, 1042 such multibyte target UTF-8 characters. cifs_unicode.c,
@@ -977,17 +1051,19 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
977 } 1051 }
978 /* if buggy server returns . and .. late do 1052 /* if buggy server returns . and .. late do
979 we want to check for that here? */ 1053 we want to check for that here? */
980 rc = cifs_filldir(current_entry, file, 1054 rc = cifs_filldir(current_entry, file,
981 filldir, direntry,tmp_buf); 1055 filldir, direntry, tmp_buf, max_len);
982 file->f_pos++; 1056 file->f_pos++;
983 if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) { 1057 if(file->f_pos ==
1058 cifsFile->srch_inf.index_of_last_entry) {
984 cFYI(1,("last entry in buf at pos %lld %s", 1059 cFYI(1,("last entry in buf at pos %lld %s",
985 file->f_pos,tmp_buf)); /* BB removeme BB */ 1060 file->f_pos,tmp_buf));
986 cifs_save_resume_key(current_entry,cifsFile); 1061 cifs_save_resume_key(current_entry,cifsFile);
987 break; 1062 break;
988 } else 1063 } else
989 current_entry = nxt_dir_entry(current_entry, 1064 current_entry =
990 end_of_smb); 1065 nxt_dir_entry(current_entry, end_of_smb,
1066 cifsFile->srch_inf.info_level);
991 } 1067 }
992 kfree(tmp_buf); 1068 kfree(tmp_buf);
993 break; 1069 break;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
new file mode 100644
index 000000000000..c6fd01f55e90
--- /dev/null
+++ b/fs/cifs/sess.c
@@ -0,0 +1,528 @@
1/*
2 * fs/cifs/sess.c
3 *
4 * SMB/CIFS session setup handling routines
5 *
6 * Copyright (c) International Business Machines Corp., 2006
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include "cifspdu.h"
25#include "cifsglob.h"
26#include "cifsproto.h"
27#include "cifs_unicode.h"
28#include "cifs_debug.h"
29#include "ntlmssp.h"
30#include "nterr.h"
31#include <linux/utsname.h>
32
33extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
34 unsigned char *p24);
35
36#ifdef CONFIG_CIFS_EXPERIMENTAL
37
38static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
39{
40 __u32 capabilities = 0;
41
42 /* init fields common to all four types of SessSetup */
43 /* note that header is initialized to zero in header_assemble */
44 pSMB->req.AndXCommand = 0xFF;
45 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
46 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
47
48 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
49
50 /* BB verify whether signing required on neg or just on auth frame
51 (and NTLM case) */
52
53 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
54 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
55
56 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
57 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
58
59 if (ses->capabilities & CAP_UNICODE) {
60 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
61 capabilities |= CAP_UNICODE;
62 }
63 if (ses->capabilities & CAP_STATUS32) {
64 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
65 capabilities |= CAP_STATUS32;
66 }
67 if (ses->capabilities & CAP_DFS) {
68 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
69 capabilities |= CAP_DFS;
70 }
71 if (ses->capabilities & CAP_UNIX) {
72 capabilities |= CAP_UNIX;
73 }
74
75 /* BB check whether to init vcnum BB */
76 return capabilities;
77}
78
79static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
80 const struct nls_table * nls_cp)
81{
82 char * bcc_ptr = *pbcc_area;
83 int bytes_ret = 0;
84
85 /* BB FIXME add check that strings total less
86 than 335 or will need to send them as arrays */
87
88 /* align unicode strings, must be word aligned */
89 if ((long) bcc_ptr % 2) {
90 *bcc_ptr = 0;
91 bcc_ptr++;
92 }
93 /* copy user */
94 if(ses->userName == NULL) {
95 /* BB what about null user mounts - check that we do this BB */
96 } else { /* 300 should be long enough for any conceivable user name */
97 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
98 300, nls_cp);
99 }
100 bcc_ptr += 2 * bytes_ret;
101 bcc_ptr += 2; /* account for null termination */
102 /* copy domain */
103 if(ses->domainName == NULL)
104 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
105 "CIFS_LINUX_DOM", 32, nls_cp);
106 else
107 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
108 256, nls_cp);
109 bcc_ptr += 2 * bytes_ret;
110 bcc_ptr += 2; /* account for null terminator */
111
112 /* Copy OS version */
113 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
114 nls_cp);
115 bcc_ptr += 2 * bytes_ret;
116 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
117 32, nls_cp);
118 bcc_ptr += 2 * bytes_ret;
119 bcc_ptr += 2; /* trailing null */
120
121 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
122 32, nls_cp);
123 bcc_ptr += 2 * bytes_ret;
124 bcc_ptr += 2; /* trailing null */
125
126 *pbcc_area = bcc_ptr;
127}
128
129static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
130 const struct nls_table * nls_cp)
131{
132 char * bcc_ptr = *pbcc_area;
133
134 /* copy user */
135 /* BB what about null user mounts - check that we do this BB */
136 /* copy user */
137 if(ses->userName == NULL) {
138 /* BB what about null user mounts - check that we do this BB */
139 } else { /* 300 should be long enough for any conceivable user name */
140 strncpy(bcc_ptr, ses->userName, 300);
141 }
142 /* BB improve check for overflow */
143 bcc_ptr += strnlen(ses->userName, 200);
144 *bcc_ptr = 0;
145 bcc_ptr++; /* account for null termination */
146
147 /* copy domain */
148
149 if(ses->domainName == NULL) {
150 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
151 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
152 } else {
153 strncpy(bcc_ptr, ses->domainName, 256);
154 bcc_ptr += strnlen(ses->domainName, 256);
155 }
156 *bcc_ptr = 0;
157 bcc_ptr++;
158
159 /* BB check for overflow here */
160
161 strcpy(bcc_ptr, "Linux version ");
162 bcc_ptr += strlen("Linux version ");
163 strcpy(bcc_ptr, system_utsname.release);
164 bcc_ptr += strlen(system_utsname.release) + 1;
165
166 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
167 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
168
169 *pbcc_area = bcc_ptr;
170}
171
172static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
173 const struct nls_table * nls_cp)
174{
175 int rc = 0;
176 int words_left, len;
177 char * data = *pbcc_area;
178
179
180
181 cFYI(1,("bleft %d",bleft));
182
183
184 /* word align, if bytes remaining is not even */
185 if(bleft % 2) {
186 bleft--;
187 data++;
188 }
189 words_left = bleft / 2;
190
191 /* save off server operating system */
192 len = UniStrnlen((wchar_t *) data, words_left);
193
194/* We look for obvious messed up bcc or strings in response so we do not go off
195 the end since (at least) WIN2K and Windows XP have a major bug in not null
196 terminating last Unicode string in response */
197 if(len >= words_left)
198 return rc;
199
200 if(ses->serverOS)
201 kfree(ses->serverOS);
202 /* UTF-8 string will not grow more than four times as big as UCS-16 */
203 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
204 if(ses->serverOS != NULL) {
205 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
206 nls_cp);
207 }
208 data += 2 * (len + 1);
209 words_left -= len + 1;
210
211 /* save off server network operating system */
212 len = UniStrnlen((wchar_t *) data, words_left);
213
214 if(len >= words_left)
215 return rc;
216
217 if(ses->serverNOS)
218 kfree(ses->serverNOS);
219 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
220 if(ses->serverNOS != NULL) {
221 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
222 nls_cp);
223 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
224 cFYI(1,("NT4 server"));
225 ses->flags |= CIFS_SES_NT4;
226 }
227 }
228 data += 2 * (len + 1);
229 words_left -= len + 1;
230
231 /* save off server domain */
232 len = UniStrnlen((wchar_t *) data, words_left);
233
234 if(len > words_left)
235 return rc;
236
237 if(ses->serverDomain)
238 kfree(ses->serverDomain);
239 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
240 if(ses->serverDomain != NULL) {
241 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
242 nls_cp);
243 ses->serverDomain[2*len] = 0;
244 ses->serverDomain[(2*len) + 1] = 0;
245 }
246 data += 2 * (len + 1);
247 words_left -= len + 1;
248
249 cFYI(1,("words left: %d",words_left));
250
251 return rc;
252}
253
254static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
255 const struct nls_table * nls_cp)
256{
257 int rc = 0;
258 int len;
259 char * bcc_ptr = *pbcc_area;
260
261 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
262
263 len = strnlen(bcc_ptr, bleft);
264 if(len >= bleft)
265 return rc;
266
267 if(ses->serverOS)
268 kfree(ses->serverOS);
269
270 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
271 if(ses->serverOS)
272 strncpy(ses->serverOS, bcc_ptr, len);
273
274 bcc_ptr += len + 1;
275 bleft -= len + 1;
276
277 len = strnlen(bcc_ptr, bleft);
278 if(len >= bleft)
279 return rc;
280
281 if(ses->serverNOS)
282 kfree(ses->serverNOS);
283
284 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
285 if(ses->serverNOS)
286 strncpy(ses->serverNOS, bcc_ptr, len);
287
288 bcc_ptr += len + 1;
289 bleft -= len + 1;
290
291 len = strnlen(bcc_ptr, bleft);
292 if(len > bleft)
293 return rc;
294
295 if(ses->serverDomain)
296 kfree(ses->serverDomain);
297
298 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
299 if(ses->serverOS)
300 strncpy(ses->serverOS, bcc_ptr, len);
301
302 bcc_ptr += len + 1;
303 bleft -= len + 1;
304
305 cFYI(1,("ascii: bytes left %d",bleft));
306
307 return rc;
308}
309
310int
311CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
312 const struct nls_table *nls_cp)
313{
314 int rc = 0;
315 int wct;
316 struct smb_hdr *smb_buf;
317 char *bcc_ptr;
318 SESSION_SETUP_ANDX *pSMB;
319 __u32 capabilities;
320 int count;
321 int resp_buf_type = 0;
322 struct kvec iov[1];
323 enum securityEnum type;
324 __u16 action;
325 int bytes_remaining;
326
327 cFYI(1,("new sess setup"));
328 if(ses == NULL)
329 return -EINVAL;
330
331 type = ses->server->secType;
332 if(type == LANMAN) {
333#ifndef CONFIG_CIFS_WEAK_PW_HASH
334 /* LANMAN and plaintext are less secure and off by default.
335 So we make this explicitly be turned on in kconfig (in the
336 build) and turned on at runtime (changed from the default)
337 in proc/fs/cifs or via mount parm. Unfortunately this is
338 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
339 return -EOPNOTSUPP;
340#endif
341 wct = 10; /* lanman 2 style sessionsetup */
342 } else if((type == NTLM) || (type == NTLMv2)) {
343 /* For NTLMv2 failures eventually may need to retry NTLM */
344 wct = 13; /* old style NTLM sessionsetup */
345 } else /* same size for negotiate or auth, NTLMSSP or extended security */
346 wct = 12;
347
348 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
349 (void **)&smb_buf);
350 if(rc)
351 return rc;
352
353 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
354
355 capabilities = cifs_ssetup_hdr(ses, pSMB);
356 bcc_ptr = pByteArea(smb_buf);
357
358 if(type == LANMAN) {
359#ifdef CONFIG_CIFS_WEAK_PW_HASH
360 char lnm_session_key[CIFS_SESS_KEY_SIZE];
361
362 /* no capabilities flags in old lanman negotiation */
363
364 pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
365 /* BB calculate hash with password */
366 /* and copy into bcc */
367
368 calc_lanman_hash(ses, lnm_session_key);
369
370#ifdef CONFIG_CIFS_DEBUG2
371 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
372 CIFS_SESS_KEY_SIZE);
373#endif
374 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
375 bcc_ptr += CIFS_SESS_KEY_SIZE;
376
377 /* can not sign if LANMAN negotiated so no need
378 to calculate signing key? but what if server
379 changed to do higher than lanman dialect and
380 we reconnected would we ever calc signing_key? */
381
382 cERROR(1,("Negotiating LANMAN setting up strings"));
383 /* Unicode not allowed for LANMAN dialects */
384 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
385#endif
386 } else if (type == NTLM) {
387 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
388
389 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
390 pSMB->req_no_secext.CaseInsensitivePasswordLength =
391 cpu_to_le16(CIFS_SESS_KEY_SIZE);
392 pSMB->req_no_secext.CaseSensitivePasswordLength =
393 cpu_to_le16(CIFS_SESS_KEY_SIZE);
394
395 /* calculate session key */
396 SMBNTencrypt(ses->password, ses->server->cryptKey,
397 ntlm_session_key);
398
399 if(first_time) /* should this be moved into common code
400 with similar ntlmv2 path? */
401 cifs_calculate_mac_key( ses->server->mac_signing_key,
402 ntlm_session_key, ses->password);
403 /* copy session key */
404
405 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
406 bcc_ptr += CIFS_SESS_KEY_SIZE;
407 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
408 bcc_ptr += CIFS_SESS_KEY_SIZE;
409 if(ses->capabilities & CAP_UNICODE)
410 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
411 else
412 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
413 } else if (type == NTLMv2) {
414 char * v2_sess_key =
415 kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
416
417 /* BB FIXME change all users of v2_sess_key to
418 struct ntlmv2_resp */
419
420 if(v2_sess_key == NULL) {
421 cifs_small_buf_release(smb_buf);
422 return -ENOMEM;
423 }
424
425 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
426
427 /* LM2 password would be here if we supported it */
428 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
429 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
430
431 pSMB->req_no_secext.CaseSensitivePasswordLength =
432 cpu_to_le16(sizeof(struct ntlmv2_resp));
433
434 /* calculate session key */
435 setup_ntlmv2_rsp(ses, v2_sess_key);
436 if(first_time) /* should this be moved into common code
437 with similar ntlmv2 path? */
438 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
439 response BB FIXME, v2_sess_key); */
440
441 /* copy session key */
442
443 /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
444 bcc_ptr += LM2_SESS_KEY_SIZE; */
445 memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
446 bcc_ptr += sizeof(struct ntlmv2_resp);
447 kfree(v2_sess_key);
448 if(ses->capabilities & CAP_UNICODE)
449 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
450 else
451 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
452 } else /* NTLMSSP or SPNEGO */ {
453 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
454 capabilities |= CAP_EXTENDED_SECURITY;
455 pSMB->req.Capabilities = cpu_to_le32(capabilities);
456 /* BB set password lengths */
457 }
458
459 count = (long) bcc_ptr - (long) pByteArea(smb_buf);
460 smb_buf->smb_buf_length += count;
461
462 /* if we switch to small buffers, count will need to be fewer
463 than 383 (strings less than 335 bytes) */
464
465 BCC_LE(smb_buf) = cpu_to_le16(count);
466
467
468 /* BB FIXME check for other non ntlm code paths */
469
470 /* BB check is this too big for a small smb? */
471
472 iov[0].iov_base = (char *)pSMB;
473 iov[0].iov_len = smb_buf->smb_buf_length + 4;
474
475 rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
476 /* SMB request buf freed in SendReceive2 */
477
478 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
479 if(rc)
480 goto ssetup_exit;
481
482 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
483 smb_buf = (struct smb_hdr *)iov[0].iov_base;
484
485 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
486 rc = -EIO;
487 cERROR(1,("bad word count %d", smb_buf->WordCount));
488 goto ssetup_exit;
489 }
490 action = le16_to_cpu(pSMB->resp.Action);
491 if (action & GUEST_LOGIN)
492 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
493 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
494 cFYI(1, ("UID = %d ", ses->Suid));
495 /* response can have either 3 or 4 word count - Samba sends 3 */
496 /* and lanman response is 3 */
497 bytes_remaining = BCC(smb_buf);
498 bcc_ptr = pByteArea(smb_buf);
499
500 if(smb_buf->WordCount == 4) {
501 __u16 blob_len;
502 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
503 bcc_ptr += blob_len;
504 if(blob_len > bytes_remaining) {
505 cERROR(1,("bad security blob length %d", blob_len));
506 rc = -EINVAL;
507 goto ssetup_exit;
508 }
509 bytes_remaining -= blob_len;
510 }
511
512 /* BB check if Unicode and decode strings */
513 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
514 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
515 ses, nls_cp);
516 else
517 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
518
519ssetup_exit:
520 if(resp_buf_type == CIFS_SMALL_BUFFER) {
521 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
522 cifs_small_buf_release(iov[0].iov_base);
523 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
524 cifs_buf_release(iov[0].iov_base);
525
526 return rc;
527}
528#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 6103bcdfb16d..f518c5e45035 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -30,6 +30,7 @@
30#include <linux/random.h> 30#include <linux/random.h>
31#include "cifs_unicode.h" 31#include "cifs_unicode.h"
32#include "cifspdu.h" 32#include "cifspdu.h"
33#include "cifsglob.h"
33#include "md5.h" 34#include "md5.h"
34#include "cifs_debug.h" 35#include "cifs_debug.h"
35#include "cifsencrypt.h" 36#include "cifsencrypt.h"
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 3da80409466c..17ba329e2b3d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -654,8 +654,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
654 654
655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
656 up(&ses->server->tcpSem); 656 up(&ses->server->tcpSem);
657 cERROR(1, 657 cERROR(1, ("Illegal length, greater than maximum frame, %d",
658 ("Illegal length, greater than maximum frame, %d ",
659 in_buf->smb_buf_length)); 658 in_buf->smb_buf_length));
660 DeleteMidQEntry(midQ); 659 DeleteMidQEntry(midQ);
661 /* If not lock req, update # of requests on wire to server */ 660 /* If not lock req, update # of requests on wire to server */