aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-27 21:31:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-27 21:31:57 -0400
commitf17a2686b11453680e9662ef8bdc8d948d0dce18 (patch)
tree8dc0dda0afe880fbd263825e2e07fe1d814f732e /fs/cifs
parent01f7e67367f75257ea5e8e5a21eddba9fa660f17 (diff)
parentf40c562855294bf4e7268274d7461dc32c1e6b25 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (25 commits) [CIFS] Fix authentication choice so we do not force NTLMv2 unless the [CIFS] Fix alignment of unicode strings in previous patch [CIFS] Fix allocation of buffers for new session setup routine to allow [CIFS] Remove calls to to take f_owner.lock [CIFS] remove some redundant null pointer checks [CIFS] Fix compile warning when CONFIG_CIFS_EXPERIMENTAL is off [CIFS] Enable sec flags on mount for cifs (part one) [CIFS] Fix suspend/resume problem which causes EIO on subsequent access to [CIFS] fix minor compile warning when config_cifs_weak_security is off [CIFS] NTLMv2 support part 5 [CIFS] Add support for readdir to legacy servers [CIFS] NTLMv2 support part 4 [CIFS] NTLMv2 support part 3 [CIFS] NTLMv2 support part 2 [CIFS] Fix mask so can set new cifs security flags properly CIFS] Support for older servers which require plaintext passwords - part 2 [CIFS] Support for older servers which require plaintext passwords [CIFS] Fix mapping of old SMB return code Invalid Net Name so it is [CIFS] Missing brace [CIFS] Do not overwrite aops ...
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES17
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README39
-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.c140
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/cifs/cifsfs.h3
-rw-r--r--fs/cifs/cifsglob.h71
-rw-r--r--fs/cifs/cifspdu.h98
-rw-r--r--fs/cifs/cifsproto.h14
-rw-r--r--fs/cifs/cifssmb.c287
-rw-r--r--fs/cifs/connect.c498
-rw-r--r--fs/cifs/dir.c15
-rw-r--r--fs/cifs/fcntl.c4
-rw-r--r--fs/cifs/file.c52
-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.c538
-rw-r--r--fs/cifs/smbencrypt.c1
-rw-r--r--fs/cifs/transport.c3
27 files changed, 1503 insertions, 821 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 7271bb0257f6..a61d17ed1827 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,9 +1,24 @@
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). Fix to allow
9NTLMv2 authentication support (now can use stronger password hashing
10on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004).
11Allow override of global cifs security flags on mount via "sec=" option(s).
12
1Version 1.43 13Version 1.43
2------------ 14------------
3POSIX locking to servers which support CIFS POSIX Extensions 15POSIX locking to servers which support CIFS POSIX Extensions
4(disabled by default controlled by proc/fs/cifs/Experimental). 16(disabled by default controlled by proc/fs/cifs/Experimental).
5Handle conversion of long share names (especially Asian languages) 17Handle conversion of long share names (especially Asian languages)
6to Unicode during mount. 18to Unicode during mount. Fix memory leak in sess struct on reconnect.
19Fix rare oops after acpi suspend. Fix O_TRUNC opens to overwrite on
20cifs open which helps rare case when setpathinfo fails or server does
21not support it.
7 22
8Version 1.42 23Version 1.42
9------------ 24------------
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..7986d0d97ace 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -443,7 +443,10 @@ A partial list of the supported mount options follows:
443 SFU does). In the future the bottom 9 bits of the mode 443 SFU does). In the future the bottom 9 bits of the mode
444 mode also will be emulated using queries of the security 444 mode also will be emulated using queries of the security
445 descriptor (ACL). 445 descriptor (ACL).
446sec Security mode. Allowed values are: 446 sign Must use packet signing (helps avoid unwanted data modification
447 by intermediate systems in the route). Note that signing
448 does not work with lanman or plaintext authentication.
449 sec Security mode. Allowed values are:
447 none attempt to connection as a null user (no name) 450 none attempt to connection as a null user (no name)
448 krb5 Use Kerberos version 5 authentication 451 krb5 Use Kerberos version 5 authentication
449 krb5i Use Kerberos authentication and packet signing 452 krb5i Use Kerberos authentication and packet signing
@@ -453,6 +456,8 @@ sec Security mode. Allowed values are:
453 server requires signing also can be the default) 456 server requires signing also can be the default)
454 ntlmv2 Use NTLMv2 password hashing 457 ntlmv2 Use NTLMv2 password hashing
455 ntlmv2i Use NTLMv2 password hashing with packet signing 458 ntlmv2i Use NTLMv2 password hashing with packet signing
459 lanman (if configured in kernel config) use older
460 lanman hash
456 461
457The mount.cifs mount helper also accepts a few mount options before -o 462The mount.cifs mount helper also accepts a few mount options before -o
458including: 463including:
@@ -485,14 +490,34 @@ PacketSigningEnabled If set to one, cifs packet signing is enabled
485 it. If set to two, cifs packet signing is 490 it. If set to two, cifs packet signing is
486 required even if the server considers packet 491 required even if the server considers packet
487 signing optional. (default 1) 492 signing optional. (default 1)
493SecurityFlags Flags which control security negotiation and
494 also packet signing. Authentication (may/must)
495 flags (e.g. for NTLM and/or NTLMv2) may be combined with
496 the signing flags. Specifying two different password
497 hashing mechanisms (as "must use") on the other hand
498 does not make much sense. Default flags are
499 0x07007
500 (NTLM, NTLMv2 and packet signing allowed). Maximum
501 allowable flags if you want to allow mounts to servers
502 using weaker password hashes is 0x37037 (lanman,
503 plaintext, ntlm, ntlmv2, signing allowed):
504
505 may use packet signing 0x00001
506 must use packet signing 0x01001
507 may use NTLM (most common password hash) 0x00002
508 must use NTLM 0x02002
509 may use NTLMv2 0x00004
510 must use NTLMv2 0x04004
511 may use Kerberos security (not implemented yet) 0x00008
512 must use Kerberos (not implemented yet) 0x08008
513 may use lanman (weak) password hash 0x00010
514 must use lanman password hash 0x10010
515 may use plaintext passwords 0x00020
516 must use plaintext passwords 0x20020
517 (reserved for future packet encryption) 0x00040
518
488cifsFYI If set to one, additional debug information is 519cifsFYI If set to one, additional debug information is
489 logged to the system error log. (default 0) 520 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 521traceSMB If set to one, debug information is logged to the
497 system error log with the start of smb requests 522 system error log with the start of smb requests
498 and responses (default 0) 523 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..a89efaf78a26 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,11 +208,12 @@ 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
211int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info) 215int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
216 const struct nls_table * nls_info)
212{ 217{
213 char temp_hash[16]; 218 char temp_hash[16];
214 struct HMACMD5Context ctx; 219 struct HMACMD5Context ctx;
@@ -225,6 +230,8 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
225 user_name_len = strlen(ses->userName); 230 user_name_len = strlen(ses->userName);
226 if(user_name_len > MAX_USERNAME_SIZE) 231 if(user_name_len > MAX_USERNAME_SIZE)
227 return -EINVAL; 232 return -EINVAL;
233 if(ses->domainName == NULL)
234 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
228 dom_name_len = strlen(ses->domainName); 235 dom_name_len = strlen(ses->domainName);
229 if(dom_name_len > MAX_USERNAME_SIZE) 236 if(dom_name_len > MAX_USERNAME_SIZE)
230 return -EINVAL; 237 return -EINVAL;
@@ -259,16 +266,131 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
259 kfree(unicode_buf); 266 kfree(unicode_buf);
260 return 0; 267 return 0;
261} 268}
262void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) 269
270#ifdef CONFIG_CIFS_WEAK_PW_HASH
271void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
272{
273 int i;
274 char password_with_pad[CIFS_ENCPWD_SIZE];
275
276 if(ses->server == NULL)
277 return;
278
279 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
280 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
281
282 if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
283 if(extended_security & CIFSSEC_MAY_PLNTXT) {
284 memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
285 return;
286 }
287
288 /* calculate old style session key */
289 /* calling toupper is less broken than repeatedly
290 calling nls_toupper would be since that will never
291 work for UTF8, but neither handles multibyte code pages
292 but the only alternative would be converting to UCS-16 (Unicode)
293 (using a routine something like UniStrupr) then
294 uppercasing and then converting back from Unicode - which
295 would only worth doing it if we knew it were utf8. Basically
296 utf8 and other multibyte codepages each need their own strupper
297 function since a byte at a time will ont work. */
298
299 for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
300 password_with_pad[i] = toupper(password_with_pad[i]);
301 }
302
303 SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
304 /* clear password before we return/free memory */
305 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
306}
307#endif /* CIFS_WEAK_PW_HASH */
308
309static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
310 const struct nls_table * nls_cp)
311{
312 int rc = 0;
313 int len;
314 char nt_hash[16];
315 struct HMACMD5Context * pctxt;
316 wchar_t * user;
317 wchar_t * domain;
318
319 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
320
321 if(pctxt == NULL)
322 return -ENOMEM;
323
324 /* calculate md4 hash of password */
325 E_md4hash(ses->password, nt_hash);
326
327 /* convert Domainname to unicode and uppercase */
328 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
329
330 /* convert ses->userName to unicode and uppercase */
331 len = strlen(ses->userName);
332 user = kmalloc(2 + (len * 2), GFP_KERNEL);
333 if(user == NULL)
334 goto calc_exit_2;
335 len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
336 UniStrupr(user);
337 hmac_md5_update((char *)user, 2*len, pctxt);
338
339 /* convert ses->domainName to unicode and uppercase */
340 if(ses->domainName) {
341 len = strlen(ses->domainName);
342
343 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
344 if(domain == NULL)
345 goto calc_exit_1;
346 len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
347 UniStrupr(domain);
348
349 hmac_md5_update((char *)domain, 2*len, pctxt);
350
351 kfree(domain);
352 }
353calc_exit_1:
354 kfree(user);
355calc_exit_2:
356 /* BB FIXME what about bytes 24 through 40 of the signing key?
357 compare with the NTLM example */
358 hmac_md5_final(ses->server->mac_signing_key, pctxt);
359
360 return rc;
361}
362
363void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
364 const struct nls_table * nls_cp)
365{
366 int rc;
367 struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
368
369 buf->blob_signature = cpu_to_le32(0x00000101);
370 buf->reserved = 0;
371 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
372 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
373 buf->reserved2 = 0;
374 buf->names[0].type = 0;
375 buf->names[0].length = 0;
376
377 /* calculate buf->ntlmv2_hash */
378 rc = calc_ntlmv2_hash(ses, nls_cp);
379 if(rc)
380 cERROR(1,("could not get v2 hash rc %d",rc));
381 CalcNTLMv2_response(ses, resp_buf);
382}
383
384void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
263{ 385{
264 struct HMACMD5Context context; 386 struct HMACMD5Context context;
387 /* rest of v2 struct already generated */
265 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 388 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
266 /* gen_blob(v2_session_response + 16); */
267 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context); 389 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
268 390
269 hmac_md5_update(ses->server->cryptKey,8,&context); 391 hmac_md5_update(v2_session_response+8,
270/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 392 sizeof(struct ntlmv2_resp) - 8, &context);
271 393
272 hmac_md5_final(v2_session_response,&context); 394 hmac_md5_final(v2_session_response,&context);
273 cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */ 395/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
274} 396}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8b4de6eaabd0..c28ede599946 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;
@@ -908,7 +908,7 @@ static int cifs_dnotify_thread(void * dummyarg)
908 struct cifsSesInfo *ses; 908 struct cifsSesInfo *ses;
909 909
910 do { 910 do {
911 if(try_to_freeze()) 911 if (try_to_freeze())
912 continue; 912 continue;
913 set_current_state(TASK_INTERRUPTIBLE); 913 set_current_state(TASK_INTERRUPTIBLE);
914 schedule_timeout(15*HZ); 914 schedule_timeout(15*HZ);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d56c0577c710..a6384d83fdef 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..6d7cf5f3bc0b 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,10 +180,13 @@ 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;
189 unsigned overrideSecFlg; /* if non-zero override global sec flags */
186 __u16 ipc_tid; /* special tid for connection to IPC share */ 190 __u16 ipc_tid; /* special tid for connection to IPC share */
187 __u16 flags; 191 __u16 flags;
188 char *serverOS; /* name of operating system underlying server */ 192 char *serverOS; /* name of operating system underlying server */
@@ -194,7 +198,7 @@ struct cifsSesInfo {
194 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for 198 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
195 TCP names - will ipv6 and sctp addresses fit? */ 199 TCP names - will ipv6 and sctp addresses fit? */
196 char userName[MAX_USERNAME_SIZE + 1]; 200 char userName[MAX_USERNAME_SIZE + 1];
197 char domainName[MAX_USERNAME_SIZE + 1]; 201 char * domainName;
198 char * password; 202 char * password;
199}; 203};
200/* session flags */ 204/* session flags */
@@ -209,12 +213,12 @@ struct cifsTconInfo {
209 struct list_head openFileList; 213 struct list_head openFileList;
210 struct semaphore tconSem; 214 struct semaphore tconSem;
211 struct cifsSesInfo *ses; /* pointer to session associated with */ 215 struct cifsSesInfo *ses; /* pointer to session associated with */
212 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */ 216 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
213 char *nativeFileSystem; 217 char *nativeFileSystem;
214 __u16 tid; /* The 2 byte tree id */ 218 __u16 tid; /* The 2 byte tree id */
215 __u16 Flags; /* optional support bits */ 219 __u16 Flags; /* optional support bits */
216 enum statusEnum tidStatus; 220 enum statusEnum tidStatus;
217 atomic_t useCount; /* how many mounts (explicit or implicit) to this share */ 221 atomic_t useCount; /* how many explicit/implicit mounts to share */
218#ifdef CONFIG_CIFS_STATS 222#ifdef CONFIG_CIFS_STATS
219 atomic_t num_smbs_sent; 223 atomic_t num_smbs_sent;
220 atomic_t num_writes; 224 atomic_t num_writes;
@@ -254,7 +258,7 @@ struct cifsTconInfo {
254 spinlock_t stat_lock; 258 spinlock_t stat_lock;
255#endif /* CONFIG_CIFS_STATS */ 259#endif /* CONFIG_CIFS_STATS */
256 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 260 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
257 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ 261 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
258 FILE_SYSTEM_UNIX_INFO fsUnixInfo; 262 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
259 unsigned retry:1; 263 unsigned retry:1;
260 unsigned nocase:1; 264 unsigned nocase:1;
@@ -305,7 +309,6 @@ struct cifsFileInfo {
305 atomic_t wrtPending; /* handle in use - defer close */ 309 atomic_t wrtPending; /* handle in use - defer close */
306 struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 310 struct semaphore fh_sem; /* prevents reopen race after dead ses*/
307 char * search_resume_name; /* BB removeme BB */ 311 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; 312 struct cifs_search_info srch_inf;
310}; 313};
311 314
@@ -391,9 +394,9 @@ struct mid_q_entry {
391 struct smb_hdr *resp_buf; /* response buffer */ 394 struct smb_hdr *resp_buf; /* response buffer */
392 int midState; /* wish this were enum but can not pass to wait_event */ 395 int midState; /* wish this were enum but can not pass to wait_event */
393 __u8 command; /* smb command code */ 396 __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 */ 397 unsigned largeBuf:1; /* if valid response, is pointer to large buf */
396 unsigned multiResp:1; /* multiple trans2 responses for one request */ 398 unsigned multiRsp:1; /* multiple trans2 responses for one request */
399 unsigned multiEnd:1; /* both received */
397}; 400};
398 401
399struct oplock_q_entry { 402struct oplock_q_entry {
@@ -430,15 +433,35 @@ struct dir_notify_req {
430#define CIFS_LARGE_BUFFER 2 433#define CIFS_LARGE_BUFFER 2
431#define CIFS_IOVEC 4 /* array of response buffers */ 434#define CIFS_IOVEC 4 /* array of response buffers */
432 435
433/* Type of session setup needed */ 436/* Security Flags: indicate type of session setup needed */
434#define CIFS_PLAINTEXT 0 437#define CIFSSEC_MAY_SIGN 0x00001
435#define CIFS_LANMAN 1 438#define CIFSSEC_MAY_NTLM 0x00002
436#define CIFS_NTLM 2 439#define CIFSSEC_MAY_NTLMV2 0x00004
437#define CIFS_NTLMSSP_NEG 3 440#define CIFSSEC_MAY_KRB5 0x00008
438#define CIFS_NTLMSSP_AUTH 4 441#ifdef CONFIG_CIFS_WEAK_PW_HASH
439#define CIFS_SPNEGO_INIT 5 442#define CIFSSEC_MAY_LANMAN 0x00010
440#define CIFS_SPNEGO_TARG 6 443#define CIFSSEC_MAY_PLNTXT 0x00020
441 444#endif /* weak passwords */
445#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
446
447#define CIFSSEC_MUST_SIGN 0x01001
448/* note that only one of the following can be set so the
449result of setting MUST flags more than once will be to
450require use of the stronger protocol */
451#define CIFSSEC_MUST_NTLM 0x02002
452#define CIFSSEC_MUST_NTLMV2 0x04004
453#define CIFSSEC_MUST_KRB5 0x08008
454#ifdef CONFIG_CIFS_WEAK_PW_HASH
455#define CIFSSEC_MUST_LANMAN 0x10010
456#define CIFSSEC_MUST_PLNTXT 0x20020
457#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
458#else
459#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
460#endif /* WEAK_PW_HASH */
461#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
462
463#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
464#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
442/* 465/*
443 ***************************************************************** 466 *****************************************************************
444 * All constants go here 467 * All constants go here
@@ -500,16 +523,16 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
500GLOBAL_EXTERN struct list_head GlobalOplock_Q; 523GLOBAL_EXTERN struct list_head GlobalOplock_Q;
501 524
502GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ 525GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
503GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */ 526GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */
504 527
505/* 528/*
506 * Global transaction id (XID) information 529 * Global transaction id (XID) information
507 */ 530 */
508GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ 531GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
509GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ 532GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
510GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ 533GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
511GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */ 534GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */
512 /* on midQ entries */ 535 /* on midQ entries */
513GLOBAL_EXTERN char Local_System_Name[15]; 536GLOBAL_EXTERN char Local_System_Name[15];
514 537
515/* 538/*
@@ -531,7 +554,7 @@ GLOBAL_EXTERN atomic_t smBufAllocCount;
531GLOBAL_EXTERN atomic_t midCount; 554GLOBAL_EXTERN atomic_t midCount;
532 555
533/* Misc globals */ 556/* Misc globals */
534GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions 557GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
535 to be established on existing mount if we 558 to be established on existing mount if we
536 have the uid/password or Kerberos credential 559 have the uid/password or Kerberos credential
537 or equivalent for current user */ 560 or equivalent for current user */
@@ -540,8 +563,8 @@ GLOBAL_EXTERN unsigned int experimEnabled;
540GLOBAL_EXTERN unsigned int lookupCacheEnabled; 563GLOBAL_EXTERN unsigned int lookupCacheEnabled;
541GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent 564GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
542 with more secure ntlmssp2 challenge/resp */ 565 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 */ 566GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
567GLOBAL_EXTERN unsigned int secFlags;
545GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ 568GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
546GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ 569GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
547GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ 570GLOBAL_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..a5ddc62d6fe6 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -64,14 +64,12 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb);
64extern void header_assemble(struct smb_hdr *, char /* command */ , 64extern void header_assemble(struct smb_hdr *, char /* command */ ,
65 const struct cifsTconInfo *, int /* length of 65 const struct cifsTconInfo *, int /* length of
66 fixed section (word count) in two byte units */); 66 fixed section (word count) in two byte units */);
67#ifdef CONFIG_CIFS_EXPERIMENTAL
68extern int small_smb_init_no_tc(const int smb_cmd, const int wct, 67extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
69 struct cifsSesInfo *ses, 68 struct cifsSesInfo *ses,
70 void ** request_buf); 69 void ** request_buf);
71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, 70extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
72 const int stage, int * pNTLMv2_flg, 71 const int stage,
73 const struct nls_table *nls_cp); 72 const struct nls_table *nls_cp);
74#endif
75extern __u16 GetNextMid(struct TCP_Server_Info *server); 73extern __u16 GetNextMid(struct TCP_Server_Info *server);
76extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 74extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
77 struct cifsTconInfo *); 75 struct cifsTconInfo *);
@@ -285,8 +283,14 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
285extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 283extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
286 __u32 expected_sequence_number); 284 __u32 expected_sequence_number);
287extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 285extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
288extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); 286extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); 287 const struct nls_table *);
288extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
289extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
290 const struct nls_table *);
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..19678c575dfc 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 */
@@ -188,7 +209,6 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
188 return rc; 209 return rc;
189} 210}
190 211
191#ifdef CONFIG_CIFS_EXPERIMENTAL
192int 212int
193small_smb_init_no_tc(const int smb_command, const int wct, 213small_smb_init_no_tc(const int smb_command, const int wct,
194 struct cifsSesInfo *ses, void **request_buf) 214 struct cifsSesInfo *ses, void **request_buf)
@@ -214,7 +234,6 @@ small_smb_init_no_tc(const int smb_command, const int wct,
214 234
215 return rc; 235 return rc;
216} 236}
217#endif /* CONFIG_CIFS_EXPERIMENTAL */
218 237
219/* If the return code is zero, this function must fill in request_buf pointer */ 238/* If the return code is zero, this function must fill in request_buf pointer */
220static int 239static int
@@ -322,7 +341,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
322 /* potential retries of smb operations it turns out we can determine */ 341 /* potential retries of smb operations it turns out we can determine */
323 /* from the mid flags when the request buffer can be resent without */ 342 /* from the mid flags when the request buffer can be resent without */
324 /* having to use a second distinct buffer for the response */ 343 /* having to use a second distinct buffer for the response */
325 *response_buf = *request_buf; 344 if(response_buf)
345 *response_buf = *request_buf;
326 346
327 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 347 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
328 wct /*wct */ ); 348 wct /*wct */ );
@@ -373,8 +393,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
373 NEGOTIATE_RSP *pSMBr; 393 NEGOTIATE_RSP *pSMBr;
374 int rc = 0; 394 int rc = 0;
375 int bytes_returned; 395 int bytes_returned;
396 int i;
376 struct TCP_Server_Info * server; 397 struct TCP_Server_Info * server;
377 u16 count; 398 u16 count;
399 unsigned int secFlags;
378 400
379 if(ses->server) 401 if(ses->server)
380 server = ses->server; 402 server = ses->server;
@@ -386,101 +408,200 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
386 (void **) &pSMB, (void **) &pSMBr); 408 (void **) &pSMB, (void **) &pSMBr);
387 if (rc) 409 if (rc)
388 return rc; 410 return rc;
411
412 /* if any of auth flags (ie not sign or seal) are overriden use them */
413 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
414 secFlags = ses->overrideSecFlg;
415 else /* if override flags set only sign/seal OR them with global auth */
416 secFlags = extended_security | ses->overrideSecFlg;
417
418 cFYI(1,("secFlags 0x%x",secFlags));
419
389 pSMB->hdr.Mid = GetNextMid(server); 420 pSMB->hdr.Mid = GetNextMid(server);
390 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 421 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
391 if (extended_security) 422 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
392 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 423 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
393 424
394 count = strlen(protocols[0].name) + 1; 425 count = 0;
395 strncpy(pSMB->DialectsArray, protocols[0].name, 30); 426 for(i=0;i<CIFS_NUM_PROT;i++) {
396 /* null guaranteed to be at end of source and target buffers anyway */ 427 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
397 428 count += strlen(protocols[i].name) + 1;
429 /* null at end of source and target buffers anyway */
430 }
398 pSMB->hdr.smb_buf_length += count; 431 pSMB->hdr.smb_buf_length += count;
399 pSMB->ByteCount = cpu_to_le16(count); 432 pSMB->ByteCount = cpu_to_le16(count);
400 433
401 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, 434 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
402 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
403 if (rc == 0) { 436 if (rc != 0)
404 server->secMode = pSMBr->SecurityMode; 437 goto neg_err_exit;
405 if((server->secMode & SECMODE_USER) == 0) 438
406 cFYI(1,("share mode security")); 439 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
407 server->secType = NTLM; /* BB override default for 440 /* Check wct = 1 error case */
408 NTLMv2 or kerberos v5 */ 441 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
409 /* one byte - no need to convert this or EncryptionKeyLen 442 /* core returns wct = 1, but we do not ask for core - otherwise
410 from little endian */ 443 small wct just comes when dialect index is -1 indicating we
411 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 444 could not negotiate a common dialect */
412 /* probably no need to store and check maxvcs */ 445 rc = -EOPNOTSUPP;
413 server->maxBuf = 446 goto neg_err_exit;
414 min(le32_to_cpu(pSMBr->MaxBufferSize), 447#ifdef CONFIG_CIFS_WEAK_PW_HASH
448 } else if((pSMBr->hdr.WordCount == 13)
449 && (pSMBr->DialectIndex == LANMAN_PROT)) {
450 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
451
452 if((secFlags & CIFSSEC_MAY_LANMAN) ||
453 (secFlags & CIFSSEC_MAY_PLNTXT))
454 server->secType = LANMAN;
455 else {
456 cERROR(1, ("mount failed weak security disabled"
457 " in /proc/fs/cifs/SecurityFlags"));
458 rc = -EOPNOTSUPP;
459 goto neg_err_exit;
460 }
461 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
462 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
463 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
464 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
465 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
466 /* even though we do not use raw we might as well set this
467 accurately, in case we ever find a need for it */
468 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
469 server->maxRw = 0xFF00;
470 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
471 } else {
472 server->maxRw = 0;/* we do not need to use raw anyway */
473 server->capabilities = CAP_MPX_MODE;
474 }
475 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
476
477 /* BB get server time for time conversions and add
478 code to use it and timezone since this is not UTC */
479
480 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
481 memcpy(server->cryptKey, rsp->EncryptionKey,
482 CIFS_CRYPTO_KEY_SIZE);
483 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
484 rc = -EIO; /* need cryptkey unless plain text */
485 goto neg_err_exit;
486 }
487
488 cFYI(1,("LANMAN negotiated"));
489 /* we will not end up setting signing flags - as no signing
490 was in LANMAN and server did not return the flags on */
491 goto signing_check;
492#else /* weak security disabled */
493 } else if(pSMBr->hdr.WordCount == 13) {
494 cERROR(1,("mount failed, cifs module not built "
495 "with CIFS_WEAK_PW_HASH support"));
496 rc = -EOPNOTSUPP;
497#endif /* WEAK_PW_HASH */
498 goto neg_err_exit;
499 } else if(pSMBr->hdr.WordCount != 17) {
500 /* unknown wct */
501 rc = -EOPNOTSUPP;
502 goto neg_err_exit;
503 }
504 /* else wct == 17 NTLM */
505 server->secMode = pSMBr->SecurityMode;
506 if((server->secMode & SECMODE_USER) == 0)
507 cFYI(1,("share mode security"));
508
509 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
510#ifdef CONFIG_CIFS_WEAK_PW_HASH
511 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
512#endif /* CIFS_WEAK_PW_HASH */
513 cERROR(1,("Server requests plain text password"
514 " but client support disabled"));
515
516 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
517 server->secType = NTLMv2;
518 else if(secFlags & CIFSSEC_MAY_NTLM)
519 server->secType = NTLM;
520 else if(secFlags & CIFSSEC_MAY_NTLMV2)
521 server->secType = NTLMv2;
522 /* else krb5 ... any others ... */
523
524 /* one byte, so no need to convert this or EncryptionKeyLen from
525 little endian */
526 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
527 /* probably no need to store and check maxvcs */
528 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
415 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 529 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
416 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 530 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
417 cFYI(0, ("Max buf = %d", ses->server->maxBuf)); 531 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
418 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 532 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
419 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 533 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
420 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); 534 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
421 /* BB with UTC do we ever need to be using srvr timezone? */ 535 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
422 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 536 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
423 memcpy(server->cryptKey, pSMBr->u.EncryptionKey, 537 CIFS_CRYPTO_KEY_SIZE);
424 CIFS_CRYPTO_KEY_SIZE); 538 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
425 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) 539 && (pSMBr->EncryptionKeyLength == 0)) {
426 && (pSMBr->EncryptionKeyLength == 0)) { 540 /* decode security blob */
427 /* decode security blob */ 541 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
428 } else 542 rc = -EIO; /* no crypt key only if plain text pwd */
429 rc = -EIO; 543 goto neg_err_exit;
544 }
430 545
431 /* BB might be helpful to save off the domain of server here */ 546 /* BB might be helpful to save off the domain of server here */
432 547
433 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 548 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
434 (server->capabilities & CAP_EXTENDED_SECURITY)) { 549 (server->capabilities & CAP_EXTENDED_SECURITY)) {
435 count = pSMBr->ByteCount; 550 count = pSMBr->ByteCount;
436 if (count < 16) 551 if (count < 16)
437 rc = -EIO; 552 rc = -EIO;
438 else if (count == 16) { 553 else if (count == 16) {
439 server->secType = RawNTLMSSP; 554 server->secType = RawNTLMSSP;
440 if (server->socketUseCount.counter > 1) { 555 if (server->socketUseCount.counter > 1) {
441 if (memcmp 556 if (memcmp(server->server_GUID,
442 (server->server_GUID, 557 pSMBr->u.extended_response.
443 pSMBr->u.extended_response. 558 GUID, 16) != 0) {
444 GUID, 16) != 0) { 559 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, 560 memcpy(server->server_GUID,
454 pSMBr->u.extended_response. 561 pSMBr->u.extended_response.GUID,
455 GUID, 16); 562 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 } 563 }
564 } else
565 memcpy(server->server_GUID,
566 pSMBr->u.extended_response.GUID, 16);
567 } else {
568 rc = decode_negTokenInit(pSMBr->u.extended_response.
569 SecurityBlob,
570 count - 16,
571 &server->secType);
572 if(rc == 1) {
573 /* BB Need to fill struct for sessetup here */
574 rc = -EOPNOTSUPP;
575 } else {
576 rc = -EINVAL;
468 } 577 }
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 } 578 }
480 579 } else
580 server->capabilities &= ~CAP_EXTENDED_SECURITY;
581
582#ifdef CONFIG_CIFS_WEAK_PW_HASH
583signing_check:
584#endif
585 if(sign_CIFS_PDUs == FALSE) {
586 if(server->secMode & SECMODE_SIGN_REQUIRED)
587 cERROR(1,("Server requires "
588 "/proc/fs/cifs/PacketSigningEnabled to be on"));
589 server->secMode &=
590 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
591 } else if(sign_CIFS_PDUs == 1) {
592 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
593 server->secMode &=
594 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
595 } else if(sign_CIFS_PDUs == 2) {
596 if((server->secMode &
597 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
598 cERROR(1,("signing required but server lacks support"));
599 }
481 } 600 }
482 601neg_err_exit:
483 cifs_buf_release(pSMB); 602 cifs_buf_release(pSMB);
603
604 cFYI(1,("negprot rc %d",rc));
484 return rc; 605 return rc;
485} 606}
486 607
@@ -2239,7 +2360,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2239 } 2360 }
2240 symlinkinfo[buflen] = 0; /* just in case so the caller 2361 symlinkinfo[buflen] = 0; /* just in case so the caller
2241 does not go off the end of the buffer */ 2362 does not go off the end of the buffer */
2242 cFYI(1,("readlink result - %s ",symlinkinfo)); 2363 cFYI(1,("readlink result - %s",symlinkinfo));
2243 } 2364 }
2244 } 2365 }
2245qreparse_out: 2366qreparse_out:
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bae1479318d1..876eb9ef85fe 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
@@ -70,6 +68,7 @@ struct smb_vol {
70 gid_t linux_gid; 68 gid_t linux_gid;
71 mode_t file_mode; 69 mode_t file_mode;
72 mode_t dir_mode; 70 mode_t dir_mode;
71 unsigned secFlg;
73 unsigned rw:1; 72 unsigned rw:1;
74 unsigned retry:1; 73 unsigned retry:1;
75 unsigned intr:1; 74 unsigned intr:1;
@@ -83,12 +82,7 @@ struct smb_vol {
83 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
84 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
85 unsigned sfu_emul:1; 84 unsigned sfu_emul:1;
86 unsigned krb5:1;
87 unsigned ntlm:1;
88 unsigned ntlmv2:1;
89 unsigned nullauth:1; /* attempt to authenticate with null user */ 85 unsigned nullauth:1; /* attempt to authenticate with null user */
90 unsigned sign:1;
91 unsigned seal:1; /* encrypt */
92 unsigned nocase; /* request case insensitive filenames */ 86 unsigned nocase; /* request case insensitive filenames */
93 unsigned nobrl; /* disable sending byte range locks to srv */ 87 unsigned nobrl; /* disable sending byte range locks to srv */
94 unsigned int rsize; 88 unsigned int rsize;
@@ -369,21 +363,21 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
369 continue; 363 continue;
370 if (bigbuf == NULL) { 364 if (bigbuf == NULL) {
371 bigbuf = cifs_buf_get(); 365 bigbuf = cifs_buf_get();
372 if(bigbuf == NULL) { 366 if (!bigbuf) {
373 cERROR(1,("No memory for large SMB response")); 367 cERROR(1, ("No memory for large SMB response"));
374 msleep(3000); 368 msleep(3000);
375 /* retry will check if exiting */ 369 /* retry will check if exiting */
376 continue; 370 continue;
377 } 371 }
378 } else if(isLargeBuf) { 372 } else if (isLargeBuf) {
379 /* we are reusing a dirtry large buf, clear its start */ 373 /* we are reusing a dirty large buf, clear its start */
380 memset(bigbuf, 0, sizeof (struct smb_hdr)); 374 memset(bigbuf, 0, sizeof (struct smb_hdr));
381 } 375 }
382 376
383 if (smallbuf == NULL) { 377 if (smallbuf == NULL) {
384 smallbuf = cifs_small_buf_get(); 378 smallbuf = cifs_small_buf_get();
385 if(smallbuf == NULL) { 379 if (!smallbuf) {
386 cERROR(1,("No memory for SMB response")); 380 cERROR(1, ("No memory for SMB response"));
387 msleep(1000); 381 msleep(1000);
388 /* retry will check if exiting */ 382 /* retry will check if exiting */
389 continue; 383 continue;
@@ -403,12 +397,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
403 kernel_recvmsg(csocket, &smb_msg, 397 kernel_recvmsg(csocket, &smb_msg,
404 &iov, 1, 4, 0 /* BB see socket.h flags */); 398 &iov, 1, 4, 0 /* BB see socket.h flags */);
405 399
406 if(server->tcpStatus == CifsExiting) { 400 if (server->tcpStatus == CifsExiting) {
407 break; 401 break;
408 } else if (server->tcpStatus == CifsNeedReconnect) { 402 } else if (server->tcpStatus == CifsNeedReconnect) {
409 cFYI(1,("Reconnect after server stopped responding")); 403 cFYI(1, ("Reconnect after server stopped responding"));
410 cifs_reconnect(server); 404 cifs_reconnect(server);
411 cFYI(1,("call to reconnect done")); 405 cFYI(1, ("call to reconnect done"));
412 csocket = server->ssocket; 406 csocket = server->ssocket;
413 continue; 407 continue;
414 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { 408 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
@@ -417,15 +411,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
417 tcpStatus CifsNeedReconnect if server hung */ 411 tcpStatus CifsNeedReconnect if server hung */
418 continue; 412 continue;
419 } else if (length <= 0) { 413 } else if (length <= 0) {
420 if(server->tcpStatus == CifsNew) { 414 if (server->tcpStatus == CifsNew) {
421 cFYI(1,("tcp session abend after SMBnegprot")); 415 cFYI(1, ("tcp session abend after SMBnegprot"));
422 /* some servers kill the TCP session rather than 416 /* some servers kill the TCP session rather than
423 returning an SMB negprot error, in which 417 returning an SMB negprot error, in which
424 case reconnecting here is not going to help, 418 case reconnecting here is not going to help,
425 and so simply return error to mount */ 419 and so simply return error to mount */
426 break; 420 break;
427 } 421 }
428 if(length == -EINTR) { 422 if (!try_to_freeze() && (length == -EINTR)) {
429 cFYI(1,("cifsd thread killed")); 423 cFYI(1,("cifsd thread killed"));
430 break; 424 break;
431 } 425 }
@@ -585,9 +579,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
585 /* merge response - fix up 1st*/ 579 /* merge response - fix up 1st*/
586 if(coalesce_t2(smb_buffer, 580 if(coalesce_t2(smb_buffer,
587 mid_entry->resp_buf)) { 581 mid_entry->resp_buf)) {
582 mid_entry->multiRsp = 1;
588 break; 583 break;
589 } else { 584 } else {
590 /* all parts received */ 585 /* all parts received */
586 mid_entry->multiEnd = 1;
591 goto multi_t2_fnd; 587 goto multi_t2_fnd;
592 } 588 }
593 } else { 589 } else {
@@ -632,9 +628,14 @@ multi_t2_fnd:
632 wake_up_process(task_to_wake); 628 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) 629 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) { 630 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd!")); 631 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer, 632 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr)); 633 sizeof(struct smb_hdr));
634#ifdef CONFIG_CIFS_DEBUG2
635 cifs_dump_detail(smb_buffer);
636 cifs_dump_mids(server);
637#endif /* CIFS_DEBUG2 */
638
638 } 639 }
639 } /* end while !EXITING */ 640 } /* end while !EXITING */
640 641
@@ -784,7 +785,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
784 785
785 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 786 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
786 vol->rw = TRUE; 787 vol->rw = TRUE;
787 vol->ntlm = TRUE;
788 /* default is always to request posix paths. */ 788 /* default is always to request posix paths. */
789 vol->posix_paths = 1; 789 vol->posix_paths = 1;
790 790
@@ -915,30 +915,35 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
915 cERROR(1,("no security value specified")); 915 cERROR(1,("no security value specified"));
916 continue; 916 continue;
917 } else if (strnicmp(value, "krb5i", 5) == 0) { 917 } else if (strnicmp(value, "krb5i", 5) == 0) {
918 vol->sign = 1; 918 vol->secFlg |= CIFSSEC_MAY_KRB5 |
919 vol->krb5 = 1; 919 CIFSSEC_MUST_SIGN;
920 } else if (strnicmp(value, "krb5p", 5) == 0) { 920 } else if (strnicmp(value, "krb5p", 5) == 0) {
921 /* vol->seal = 1; 921 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
922 vol->krb5 = 1; */ 922 CIFSSEC_MAY_KRB5; */
923 cERROR(1,("Krb5 cifs privacy not supported")); 923 cERROR(1,("Krb5 cifs privacy not supported"));
924 return 1; 924 return 1;
925 } else if (strnicmp(value, "krb5", 4) == 0) { 925 } else if (strnicmp(value, "krb5", 4) == 0) {
926 vol->krb5 = 1; 926 vol->secFlg |= CIFSSEC_MAY_KRB5;
927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
928 vol->ntlmv2 = 1; 928 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
929 vol->sign = 1; 929 CIFSSEC_MUST_SIGN;
930 } else if (strnicmp(value, "ntlmv2", 6) == 0) { 930 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
931 vol->ntlmv2 = 1; 931 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
932 } else if (strnicmp(value, "ntlmi", 5) == 0) { 932 } else if (strnicmp(value, "ntlmi", 5) == 0) {
933 vol->ntlm = 1; 933 vol->secFlg |= CIFSSEC_MAY_NTLM |
934 vol->sign = 1; 934 CIFSSEC_MUST_SIGN;
935 } else if (strnicmp(value, "ntlm", 4) == 0) { 935 } else if (strnicmp(value, "ntlm", 4) == 0) {
936 /* ntlm is default so can be turned off too */ 936 /* ntlm is default so can be turned off too */
937 vol->ntlm = 1; 937 vol->secFlg |= CIFSSEC_MAY_NTLM;
938 } else if (strnicmp(value, "nontlm", 6) == 0) { 938 } else if (strnicmp(value, "nontlm", 6) == 0) {
939 vol->ntlm = 0; 939 /* BB is there a better way to do this? */
940 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
941#ifdef CONFIG_CIFS_WEAK_PW_HASH
942 } else if (strnicmp(value, "lanman", 6) == 0) {
943 vol->secFlg |= CIFSSEC_MAY_LANMAN;
944#endif
940 } else if (strnicmp(value, "none", 4) == 0) { 945 } else if (strnicmp(value, "none", 4) == 0) {
941 vol->nullauth = 1; 946 vol->nullauth = 1;
942 } else { 947 } else {
943 cERROR(1,("bad security option: %s", value)); 948 cERROR(1,("bad security option: %s", value));
944 return 1; 949 return 1;
@@ -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 {
@@ -1168,6 +1173,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1168 vol->no_psx_acl = 0; 1173 vol->no_psx_acl = 0;
1169 } else if (strnicmp(data, "noacl",5) == 0) { 1174 } else if (strnicmp(data, "noacl",5) == 0) {
1170 vol->no_psx_acl = 1; 1175 vol->no_psx_acl = 1;
1176 } else if (strnicmp(data, "sign",4) == 0) {
1177 vol->secFlg |= CIFSSEC_MUST_SIGN;
1178/* } else if (strnicmp(data, "seal",4) == 0) {
1179 vol->secFlg |= CIFSSEC_MUST_SEAL; */
1171 } else if (strnicmp(data, "direct",6) == 0) { 1180 } else if (strnicmp(data, "direct",6) == 0) {
1172 vol->direct_io = 1; 1181 vol->direct_io = 1;
1173 } else if (strnicmp(data, "forcedirectio",13) == 0) { 1182 } else if (strnicmp(data, "forcedirectio",13) == 0) {
@@ -1762,11 +1771,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1762 if (volume_info.username) 1771 if (volume_info.username)
1763 strncpy(pSesInfo->userName, 1772 strncpy(pSesInfo->userName,
1764 volume_info.username,MAX_USERNAME_SIZE); 1773 volume_info.username,MAX_USERNAME_SIZE);
1765 if (volume_info.domainname) 1774 if (volume_info.domainname) {
1766 strncpy(pSesInfo->domainName, 1775 int len = strlen(volume_info.domainname);
1767 volume_info.domainname,MAX_USERNAME_SIZE); 1776 pSesInfo->domainName =
1777 kmalloc(len + 1, GFP_KERNEL);
1778 if(pSesInfo->domainName)
1779 strcpy(pSesInfo->domainName,
1780 volume_info.domainname);
1781 }
1768 pSesInfo->linux_uid = volume_info.linux_uid; 1782 pSesInfo->linux_uid = volume_info.linux_uid;
1783 pSesInfo->overrideSecFlg = volume_info.secFlg;
1769 down(&pSesInfo->sesSem); 1784 down(&pSesInfo->sesSem);
1785 /* BB FIXME need to pass vol->secFlgs BB */
1770 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1786 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1771 up(&pSesInfo->sesSem); 1787 up(&pSesInfo->sesSem);
1772 if(!rc) 1788 if(!rc)
@@ -1980,7 +1996,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1980 1996
1981static int 1997static int
1982CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, 1998CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1983 char session_key[CIFS_SESSION_KEY_SIZE], 1999 char session_key[CIFS_SESS_KEY_SIZE],
1984 const struct nls_table *nls_codepage) 2000 const struct nls_table *nls_codepage)
1985{ 2001{
1986 struct smb_hdr *smb_buffer; 2002 struct smb_hdr *smb_buffer;
@@ -2038,15 +2054,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2038 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 2054 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2039 2055
2040 pSMB->req_no_secext.CaseInsensitivePasswordLength = 2056 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2041 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2057 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2042 2058
2043 pSMB->req_no_secext.CaseSensitivePasswordLength = 2059 pSMB->req_no_secext.CaseSensitivePasswordLength =
2044 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2060 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2045 bcc_ptr = pByteArea(smb_buffer); 2061 bcc_ptr = pByteArea(smb_buffer);
2046 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2062 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2047 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2063 bcc_ptr += CIFS_SESS_KEY_SIZE;
2048 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2064 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2049 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2065 bcc_ptr += CIFS_SESS_KEY_SIZE;
2050 2066
2051 if (ses->capabilities & CAP_UNICODE) { 2067 if (ses->capabilities & CAP_UNICODE) {
2052 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ 2068 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
@@ -2054,7 +2070,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2054 bcc_ptr++; 2070 bcc_ptr++;
2055 } 2071 }
2056 if(user == NULL) 2072 if(user == NULL)
2057 bytes_returned = 0; /* skill null user */ 2073 bytes_returned = 0; /* skip null user */
2058 else 2074 else
2059 bytes_returned = 2075 bytes_returned =
2060 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, 2076 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
@@ -2162,8 +2178,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2162 if (remaining_words > 0) { 2178 if (remaining_words > 0) {
2163 len = UniStrnlen((wchar_t *)bcc_ptr, 2179 len = UniStrnlen((wchar_t *)bcc_ptr,
2164 remaining_words-1); 2180 remaining_words-1);
2165 if(ses->serverNOS) 2181 kfree(ses->serverNOS);
2166 kfree(ses->serverNOS);
2167 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL); 2182 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2168 if(ses->serverNOS == NULL) 2183 if(ses->serverNOS == NULL)
2169 goto sesssetup_nomem; 2184 goto sesssetup_nomem;
@@ -2203,12 +2218,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2203 /* if these kcallocs fail not much we 2218 /* if these kcallocs fail not much we
2204 can do, but better to not fail the 2219 can do, but better to not fail the
2205 sesssetup itself */ 2220 sesssetup itself */
2206 if(ses->serverDomain) 2221 kfree(ses->serverDomain);
2207 kfree(ses->serverDomain);
2208 ses->serverDomain = 2222 ses->serverDomain =
2209 kzalloc(2, GFP_KERNEL); 2223 kzalloc(2, GFP_KERNEL);
2210 if(ses->serverNOS) 2224 kfree(ses->serverNOS);
2211 kfree(ses->serverNOS);
2212 ses->serverNOS = 2225 ses->serverNOS =
2213 kzalloc(2, GFP_KERNEL); 2226 kzalloc(2, GFP_KERNEL);
2214 } 2227 }
@@ -2217,8 +2230,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2217 if (((long) bcc_ptr + len) - (long) 2230 if (((long) bcc_ptr + len) - (long)
2218 pByteArea(smb_buffer_response) 2231 pByteArea(smb_buffer_response)
2219 <= BCC(smb_buffer_response)) { 2232 <= BCC(smb_buffer_response)) {
2220 if(ses->serverOS) 2233 kfree(ses->serverOS);
2221 kfree(ses->serverOS);
2222 ses->serverOS = kzalloc(len + 1,GFP_KERNEL); 2234 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2223 if(ses->serverOS == NULL) 2235 if(ses->serverOS == NULL)
2224 goto sesssetup_nomem; 2236 goto sesssetup_nomem;
@@ -2229,8 +2241,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2229 bcc_ptr++; 2241 bcc_ptr++;
2230 2242
2231 len = strnlen(bcc_ptr, 1024); 2243 len = strnlen(bcc_ptr, 1024);
2232 if(ses->serverNOS) 2244 kfree(ses->serverNOS);
2233 kfree(ses->serverNOS);
2234 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); 2245 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2235 if(ses->serverNOS == NULL) 2246 if(ses->serverNOS == NULL)
2236 goto sesssetup_nomem; 2247 goto sesssetup_nomem;
@@ -2274,292 +2285,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings,
2274} 2285}
2275 2286
2276static int 2287static int
2277CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2278 char *SecurityBlob,int SecurityBlobLength,
2279 const struct nls_table *nls_codepage)
2280{
2281 struct smb_hdr *smb_buffer;
2282 struct smb_hdr *smb_buffer_response;
2283 SESSION_SETUP_ANDX *pSMB;
2284 SESSION_SETUP_ANDX *pSMBr;
2285 char *bcc_ptr;
2286 char *user;
2287 char *domain;
2288 int rc = 0;
2289 int remaining_words = 0;
2290 int bytes_returned = 0;
2291 int len;
2292 __u32 capabilities;
2293 __u16 count;
2294
2295 cFYI(1, ("In spnego sesssetup "));
2296 if(ses == NULL)
2297 return -EINVAL;
2298 user = ses->userName;
2299 domain = ses->domainName;
2300
2301 smb_buffer = cifs_buf_get();
2302 if (smb_buffer == NULL) {
2303 return -ENOMEM;
2304 }
2305 smb_buffer_response = smb_buffer;
2306 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2307
2308 /* send SMBsessionSetup here */
2309 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2310 NULL /* no tCon exists yet */ , 12 /* wct */ );
2311
2312 smb_buffer->Mid = GetNextMid(ses->server);
2313 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2314 pSMB->req.AndXCommand = 0xFF;
2315 if(ses->server->maxBuf > 64*1024)
2316 ses->server->maxBuf = (64*1023);
2317 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2318 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2319
2320 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2321 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2322
2323 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2324 CAP_EXTENDED_SECURITY;
2325 if (ses->capabilities & CAP_UNICODE) {
2326 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2327 capabilities |= CAP_UNICODE;
2328 }
2329 if (ses->capabilities & CAP_STATUS32) {
2330 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2331 capabilities |= CAP_STATUS32;
2332 }
2333 if (ses->capabilities & CAP_DFS) {
2334 smb_buffer->Flags2 |= SMBFLG2_DFS;
2335 capabilities |= CAP_DFS;
2336 }
2337 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2338
2339 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2340 bcc_ptr = pByteArea(smb_buffer);
2341 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2342 bcc_ptr += SecurityBlobLength;
2343
2344 if (ses->capabilities & CAP_UNICODE) {
2345 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2346 *bcc_ptr = 0;
2347 bcc_ptr++;
2348 }
2349 bytes_returned =
2350 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2351 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2352 bcc_ptr += 2; /* trailing null */
2353 if (domain == NULL)
2354 bytes_returned =
2355 cifs_strtoUCS((__le16 *) bcc_ptr,
2356 "CIFS_LINUX_DOM", 32, nls_codepage);
2357 else
2358 bytes_returned =
2359 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2360 nls_codepage);
2361 bcc_ptr += 2 * bytes_returned;
2362 bcc_ptr += 2;
2363 bytes_returned =
2364 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2365 32, nls_codepage);
2366 bcc_ptr += 2 * bytes_returned;
2367 bytes_returned =
2368 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2369 nls_codepage);
2370 bcc_ptr += 2 * bytes_returned;
2371 bcc_ptr += 2;
2372 bytes_returned =
2373 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2374 64, nls_codepage);
2375 bcc_ptr += 2 * bytes_returned;
2376 bcc_ptr += 2;
2377 } else {
2378 strncpy(bcc_ptr, user, 200);
2379 bcc_ptr += strnlen(user, 200);
2380 *bcc_ptr = 0;
2381 bcc_ptr++;
2382 if (domain == NULL) {
2383 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2384 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2385 } else {
2386 strncpy(bcc_ptr, domain, 64);
2387 bcc_ptr += strnlen(domain, 64);
2388 *bcc_ptr = 0;
2389 bcc_ptr++;
2390 }
2391 strcpy(bcc_ptr, "Linux version ");
2392 bcc_ptr += strlen("Linux version ");
2393 strcpy(bcc_ptr, system_utsname.release);
2394 bcc_ptr += strlen(system_utsname.release) + 1;
2395 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2396 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2397 }
2398 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2399 smb_buffer->smb_buf_length += count;
2400 pSMB->req.ByteCount = cpu_to_le16(count);
2401
2402 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2403 &bytes_returned, 1);
2404 if (rc) {
2405/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2406 } else if ((smb_buffer_response->WordCount == 3)
2407 || (smb_buffer_response->WordCount == 4)) {
2408 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2409 __u16 blob_len =
2410 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2411 if (action & GUEST_LOGIN)
2412 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2413 if (ses) {
2414 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2415 cFYI(1, ("UID = %d ", ses->Suid));
2416 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2417
2418 /* BB Fix below to make endian neutral !! */
2419
2420 if ((pSMBr->resp.hdr.WordCount == 3)
2421 || ((pSMBr->resp.hdr.WordCount == 4)
2422 && (blob_len <
2423 pSMBr->resp.ByteCount))) {
2424 if (pSMBr->resp.hdr.WordCount == 4) {
2425 bcc_ptr +=
2426 blob_len;
2427 cFYI(1,
2428 ("Security Blob Length %d ",
2429 blob_len));
2430 }
2431
2432 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2433 if ((long) (bcc_ptr) % 2) {
2434 remaining_words =
2435 (BCC(smb_buffer_response)
2436 - 1) / 2;
2437 bcc_ptr++; /* Unicode strings must be word aligned */
2438 } else {
2439 remaining_words =
2440 BCC
2441 (smb_buffer_response) / 2;
2442 }
2443 len =
2444 UniStrnlen((wchar_t *) bcc_ptr,
2445 remaining_words - 1);
2446/* We look for obvious messed up bcc or strings in response so we do not go off
2447 the end since (at least) WIN2K and Windows XP have a major bug in not null
2448 terminating last Unicode string in response */
2449 if(ses->serverOS)
2450 kfree(ses->serverOS);
2451 ses->serverOS =
2452 kzalloc(2 * (len + 1), GFP_KERNEL);
2453 cifs_strfromUCS_le(ses->serverOS,
2454 (__le16 *)
2455 bcc_ptr, len,
2456 nls_codepage);
2457 bcc_ptr += 2 * (len + 1);
2458 remaining_words -= len + 1;
2459 ses->serverOS[2 * len] = 0;
2460 ses->serverOS[1 + (2 * len)] = 0;
2461 if (remaining_words > 0) {
2462 len = UniStrnlen((wchar_t *)bcc_ptr,
2463 remaining_words
2464 - 1);
2465 if(ses->serverNOS)
2466 kfree(ses->serverNOS);
2467 ses->serverNOS =
2468 kzalloc(2 * (len + 1),
2469 GFP_KERNEL);
2470 cifs_strfromUCS_le(ses->serverNOS,
2471 (__le16 *)bcc_ptr,
2472 len,
2473 nls_codepage);
2474 bcc_ptr += 2 * (len + 1);
2475 ses->serverNOS[2 * len] = 0;
2476 ses->serverNOS[1 + (2 * len)] = 0;
2477 remaining_words -= len + 1;
2478 if (remaining_words > 0) {
2479 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2480 /* last string not null terminated (e.g.Windows XP/2000) */
2481 if(ses->serverDomain)
2482 kfree(ses->serverDomain);
2483 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2484 cifs_strfromUCS_le(ses->serverDomain,
2485 (__le16 *)bcc_ptr,
2486 len, nls_codepage);
2487 bcc_ptr += 2*(len+1);
2488 ses->serverDomain[2*len] = 0;
2489 ses->serverDomain[1+(2*len)] = 0;
2490 } /* else no more room so create dummy domain string */
2491 else {
2492 if(ses->serverDomain)
2493 kfree(ses->serverDomain);
2494 ses->serverDomain =
2495 kzalloc(2,GFP_KERNEL);
2496 }
2497 } else {/* no room use dummy domain&NOS */
2498 if(ses->serverDomain)
2499 kfree(ses->serverDomain);
2500 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2501 if(ses->serverNOS)
2502 kfree(ses->serverNOS);
2503 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2504 }
2505 } else { /* ASCII */
2506
2507 len = strnlen(bcc_ptr, 1024);
2508 if (((long) bcc_ptr + len) - (long)
2509 pByteArea(smb_buffer_response)
2510 <= BCC(smb_buffer_response)) {
2511 if(ses->serverOS)
2512 kfree(ses->serverOS);
2513 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2514 strncpy(ses->serverOS, bcc_ptr, len);
2515
2516 bcc_ptr += len;
2517 bcc_ptr[0] = 0; /* null terminate the string */
2518 bcc_ptr++;
2519
2520 len = strnlen(bcc_ptr, 1024);
2521 if(ses->serverNOS)
2522 kfree(ses->serverNOS);
2523 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2524 strncpy(ses->serverNOS, bcc_ptr, len);
2525 bcc_ptr += len;
2526 bcc_ptr[0] = 0;
2527 bcc_ptr++;
2528
2529 len = strnlen(bcc_ptr, 1024);
2530 if(ses->serverDomain)
2531 kfree(ses->serverDomain);
2532 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2533 strncpy(ses->serverDomain, bcc_ptr, len);
2534 bcc_ptr += len;
2535 bcc_ptr[0] = 0;
2536 bcc_ptr++;
2537 } else
2538 cFYI(1,
2539 ("Variable field of length %d extends beyond end of smb ",
2540 len));
2541 }
2542 } else {
2543 cERROR(1,
2544 (" Security Blob Length extends beyond end of SMB"));
2545 }
2546 } else {
2547 cERROR(1, ("No session structure passed in."));
2548 }
2549 } else {
2550 cERROR(1,
2551 (" Invalid Word count %d: ",
2552 smb_buffer_response->WordCount));
2553 rc = -EIO;
2554 }
2555
2556 if (smb_buffer)
2557 cifs_buf_release(smb_buffer);
2558
2559 return rc;
2560}
2561
2562static int
2563CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, 2288CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2564 struct cifsSesInfo *ses, int * pNTLMv2_flag, 2289 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2565 const struct nls_table *nls_codepage) 2290 const struct nls_table *nls_codepage)
@@ -2635,8 +2360,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2635 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2360 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2636 if(sign_CIFS_PDUs) 2361 if(sign_CIFS_PDUs)
2637 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2362 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2638 if(ntlmv2_support) 2363/* if(ntlmv2_support)
2639 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; 2364 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2640 /* setup pointers to domain name and workstation name */ 2365 /* setup pointers to domain name and workstation name */
2641 bcc_ptr += SecurityBlobLength; 2366 bcc_ptr += SecurityBlobLength;
2642 2367
@@ -2783,8 +2508,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2783 bcc_ptr, 2508 bcc_ptr,
2784 remaining_words 2509 remaining_words
2785 - 1); 2510 - 1);
2786 if(ses->serverNOS) 2511 kfree(ses->serverNOS);
2787 kfree(ses->serverNOS);
2788 ses->serverNOS = 2512 ses->serverNOS =
2789 kzalloc(2 * (len + 1), 2513 kzalloc(2 * (len + 1),
2790 GFP_KERNEL); 2514 GFP_KERNEL);
@@ -2802,8 +2526,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2802 if (remaining_words > 0) { 2526 if (remaining_words > 0) {
2803 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2527 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2804 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2528 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2805 if(ses->serverDomain) 2529 kfree(ses->serverDomain);
2806 kfree(ses->serverDomain);
2807 ses->serverDomain = 2530 ses->serverDomain =
2808 kzalloc(2 * 2531 kzalloc(2 *
2809 (len + 2532 (len +
@@ -2822,19 +2545,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2822 = 0; 2545 = 0;
2823 } /* else no more room so create dummy domain string */ 2546 } /* else no more room so create dummy domain string */
2824 else { 2547 else {
2825 if(ses->serverDomain) 2548 kfree(ses->serverDomain);
2826 kfree(ses->serverDomain);
2827 ses->serverDomain = 2549 ses->serverDomain =
2828 kzalloc(2, 2550 kzalloc(2,
2829 GFP_KERNEL); 2551 GFP_KERNEL);
2830 } 2552 }
2831 } else { /* no room so create dummy domain and NOS string */ 2553 } else { /* no room so create dummy domain and NOS string */
2832 if(ses->serverDomain); 2554 kfree(ses->serverDomain);
2833 kfree(ses->serverDomain);
2834 ses->serverDomain = 2555 ses->serverDomain =
2835 kzalloc(2, GFP_KERNEL); 2556 kzalloc(2, GFP_KERNEL);
2836 if(ses->serverNOS) 2557 kfree(ses->serverNOS);
2837 kfree(ses->serverNOS);
2838 ses->serverNOS = 2558 ses->serverNOS =
2839 kzalloc(2, GFP_KERNEL); 2559 kzalloc(2, GFP_KERNEL);
2840 } 2560 }
@@ -2856,8 +2576,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2856 bcc_ptr++; 2576 bcc_ptr++;
2857 2577
2858 len = strnlen(bcc_ptr, 1024); 2578 len = strnlen(bcc_ptr, 1024);
2859 if(ses->serverNOS) 2579 kfree(ses->serverNOS);
2860 kfree(ses->serverNOS);
2861 ses->serverNOS = 2580 ses->serverNOS =
2862 kzalloc(len + 1, 2581 kzalloc(len + 1,
2863 GFP_KERNEL); 2582 GFP_KERNEL);
@@ -2867,8 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2867 bcc_ptr++; 2586 bcc_ptr++;
2868 2587
2869 len = strnlen(bcc_ptr, 1024); 2588 len = strnlen(bcc_ptr, 1024);
2870 if(ses->serverDomain) 2589 kfree(ses->serverDomain);
2871 kfree(ses->serverDomain);
2872 ses->serverDomain = 2590 ses->serverDomain =
2873 kzalloc(len + 1, 2591 kzalloc(len + 1,
2874 GFP_KERNEL); 2592 GFP_KERNEL);
@@ -2994,14 +2712,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2994 SecurityBlob->LmChallengeResponse.Buffer = 0; 2712 SecurityBlob->LmChallengeResponse.Buffer = 0;
2995 2713
2996 SecurityBlob->NtChallengeResponse.Length = 2714 SecurityBlob->NtChallengeResponse.Length =
2997 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2715 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2998 SecurityBlob->NtChallengeResponse.MaximumLength = 2716 SecurityBlob->NtChallengeResponse.MaximumLength =
2999 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2717 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3000 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); 2718 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3001 SecurityBlob->NtChallengeResponse.Buffer = 2719 SecurityBlob->NtChallengeResponse.Buffer =
3002 cpu_to_le32(SecurityBlobLength); 2720 cpu_to_le32(SecurityBlobLength);
3003 SecurityBlobLength += CIFS_SESSION_KEY_SIZE; 2721 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3004 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2722 bcc_ptr += CIFS_SESS_KEY_SIZE;
3005 2723
3006 if (ses->capabilities & CAP_UNICODE) { 2724 if (ses->capabilities & CAP_UNICODE) {
3007 if (domain == NULL) { 2725 if (domain == NULL) {
@@ -3190,8 +2908,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3190 bcc_ptr, 2908 bcc_ptr,
3191 remaining_words 2909 remaining_words
3192 - 1); 2910 - 1);
3193 if(ses->serverNOS) 2911 kfree(ses->serverNOS);
3194 kfree(ses->serverNOS);
3195 ses->serverNOS = 2912 ses->serverNOS =
3196 kzalloc(2 * (len + 1), 2913 kzalloc(2 * (len + 1),
3197 GFP_KERNEL); 2914 GFP_KERNEL);
@@ -3244,8 +2961,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3244 if(ses->serverDomain) 2961 if(ses->serverDomain)
3245 kfree(ses->serverDomain); 2962 kfree(ses->serverDomain);
3246 ses->serverDomain = kzalloc(2, GFP_KERNEL); 2963 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3247 if(ses->serverNOS) 2964 kfree(ses->serverNOS);
3248 kfree(ses->serverNOS);
3249 ses->serverNOS = kzalloc(2, GFP_KERNEL); 2965 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3250 } 2966 }
3251 } else { /* ASCII */ 2967 } else { /* ASCII */
@@ -3263,8 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3263 bcc_ptr++; 2979 bcc_ptr++;
3264 2980
3265 len = strnlen(bcc_ptr, 1024); 2981 len = strnlen(bcc_ptr, 1024);
3266 if(ses->serverNOS) 2982 kfree(ses->serverNOS);
3267 kfree(ses->serverNOS);
3268 ses->serverNOS = kzalloc(len+1,GFP_KERNEL); 2983 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3269 strncpy(ses->serverNOS, bcc_ptr, len); 2984 strncpy(ses->serverNOS, bcc_ptr, len);
3270 bcc_ptr += len; 2985 bcc_ptr += len;
@@ -3340,22 +3055,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3340 bcc_ptr = &pSMB->Password[0]; 3055 bcc_ptr = &pSMB->Password[0];
3341 if((ses->server->secMode) & SECMODE_USER) { 3056 if((ses->server->secMode) & SECMODE_USER) {
3342 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ 3057 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3058 *bcc_ptr = 0; /* password is null byte */
3343 bcc_ptr++; /* skip password */ 3059 bcc_ptr++; /* skip password */
3060 /* already aligned so no need to do it below */
3344 } else { 3061 } else {
3345 pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); 3062 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3346 /* BB FIXME add code to fail this if NTLMv2 or Kerberos 3063 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3347 specified as required (when that support is added to 3064 specified as required (when that support is added to
3348 the vfs in the future) as only NTLM or the much 3065 the vfs in the future) as only NTLM or the much
3349 weaker LANMAN (which we do not send) is accepted 3066 weaker LANMAN (which we do not send by default) is accepted
3350 by Samba (not sure whether other servers allow 3067 by Samba (not sure whether other servers allow
3351 NTLMv2 password here) */ 3068 NTLMv2 password here) */
3069#ifdef CONFIG_CIFS_WEAK_PW_HASH
3070 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3071 (ses->server->secType == LANMAN))
3072 calc_lanman_hash(ses, bcc_ptr);
3073 else
3074#endif /* CIFS_WEAK_PW_HASH */
3352 SMBNTencrypt(ses->password, 3075 SMBNTencrypt(ses->password,
3353 ses->server->cryptKey, 3076 ses->server->cryptKey,
3354 bcc_ptr); 3077 bcc_ptr);
3355 3078
3356 bcc_ptr += CIFS_SESSION_KEY_SIZE; 3079 bcc_ptr += CIFS_SESS_KEY_SIZE;
3357 *bcc_ptr = 0; 3080 if(ses->capabilities & CAP_UNICODE) {
3358 bcc_ptr++; /* align */ 3081 /* must align unicode strings */
3082 *bcc_ptr = 0; /* null byte password */
3083 bcc_ptr++;
3084 }
3359 } 3085 }
3360 3086
3361 if(ses->server->secMode & 3087 if(ses->server->secMode &
@@ -3429,7 +3155,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3429 } 3155 }
3430 /* else do not bother copying these informational fields */ 3156 /* else do not bother copying these informational fields */
3431 } 3157 }
3432 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); 3158 if(smb_buffer_response->WordCount == 3)
3159 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3160 else
3161 tcon->Flags = 0;
3433 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); 3162 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3434 } else if ((rc == 0) && tcon == NULL) { 3163 } else if ((rc == 0) && tcon == NULL) {
3435 /* all we need to save for IPC$ connection */ 3164 /* all we need to save for IPC$ connection */
@@ -3494,7 +3223,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3494 struct nls_table * nls_info) 3223 struct nls_table * nls_info)
3495{ 3224{
3496 int rc = 0; 3225 int rc = 0;
3497 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 3226 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3498 int ntlmv2_flag = FALSE; 3227 int ntlmv2_flag = FALSE;
3499 int first_time = 0; 3228 int first_time = 0;
3500 3229
@@ -3526,20 +3255,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3526 pSesInfo->server->secMode, 3255 pSesInfo->server->secMode,
3527 pSesInfo->server->capabilities, 3256 pSesInfo->server->capabilities,
3528 pSesInfo->server->timeZone)); 3257 pSesInfo->server->timeZone));
3529#ifdef CONFIG_CIFS_EXPERIMENTAL 3258 if(experimEnabled < 2)
3530 if(experimEnabled > 1) 3259 rc = CIFS_SessSetup(xid, pSesInfo,
3531 rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, 3260 first_time, nls_info);
3532 &ntlmv2_flag, nls_info); 3261 else if (extended_security
3533 else
3534#endif
3535 if (extended_security
3536 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3262 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3537 && (pSesInfo->server->secType == NTLMSSP)) { 3263 && (pSesInfo->server->secType == NTLMSSP)) {
3538 cFYI(1, ("New style sesssetup")); 3264 rc = -EOPNOTSUPP;
3539 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3540 NULL /* security blob */,
3541 0 /* blob length */,
3542 nls_info);
3543 } else if (extended_security 3265 } else if (extended_security
3544 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3266 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3545 && (pSesInfo->server->secType == RawNTLMSSP)) { 3267 && (pSesInfo->server->secType == RawNTLMSSP)) {
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 b4a18c1cab0a..e9c1573f6aa7 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -110,7 +110,6 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
110 &pCifsInode->openFileList); 110 &pCifsInode->openFileList);
111 } 111 }
112 write_unlock(&GlobalSMBSeslock); 112 write_unlock(&GlobalSMBSeslock);
113 write_unlock(&file->f_owner.lock);
114 if (pCifsInode->clientCanCacheRead) { 113 if (pCifsInode->clientCanCacheRead) {
115 /* we have the inode open somewhere else 114 /* we have the inode open somewhere else
116 no need to discard cache data */ 115 no need to discard cache data */
@@ -201,7 +200,7 @@ int cifs_open(struct inode *inode, struct file *file)
201 } else { 200 } else {
202 if (file->f_flags & O_EXCL) 201 if (file->f_flags & O_EXCL)
203 cERROR(1, ("could not find file instance for " 202 cERROR(1, ("could not find file instance for "
204 "new file %p ", file)); 203 "new file %p", file));
205 } 204 }
206 } 205 }
207 206
@@ -260,10 +259,15 @@ int cifs_open(struct inode *inode, struct file *file)
260 rc = -ENOMEM; 259 rc = -ENOMEM;
261 goto out; 260 goto out;
262 } 261 }
263 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 262
264 CREATE_NOT_DIR, &netfid, &oplock, buf, 263 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
264 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
265 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
265 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 266 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
266 & CIFS_MOUNT_MAP_SPECIAL_CHR); 267 & CIFS_MOUNT_MAP_SPECIAL_CHR);
268 else
269 rc = -EIO; /* no NT SMB support fall into legacy open below */
270
267 if (rc == -EIO) { 271 if (rc == -EIO) {
268 /* Old server, try legacy style OpenX */ 272 /* Old server, try legacy style OpenX */
269 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 273 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -272,7 +276,7 @@ int cifs_open(struct inode *inode, struct file *file)
272 & CIFS_MOUNT_MAP_SPECIAL_CHR); 276 & CIFS_MOUNT_MAP_SPECIAL_CHR);
273 } 277 }
274 if (rc) { 278 if (rc) {
275 cFYI(1, ("cifs_open returned 0x%x ", rc)); 279 cFYI(1, ("cifs_open returned 0x%x", rc));
276 goto out; 280 goto out;
277 } 281 }
278 file->private_data = 282 file->private_data =
@@ -282,7 +286,6 @@ int cifs_open(struct inode *inode, struct file *file)
282 goto out; 286 goto out;
283 } 287 }
284 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 288 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
285 write_lock(&file->f_owner.lock);
286 write_lock(&GlobalSMBSeslock); 289 write_lock(&GlobalSMBSeslock);
287 list_add(&pCifsFile->tlist, &pTcon->openFileList); 290 list_add(&pCifsFile->tlist, &pTcon->openFileList);
288 291
@@ -293,7 +296,6 @@ int cifs_open(struct inode *inode, struct file *file)
293 &oplock, buf, full_path, xid); 296 &oplock, buf, full_path, xid);
294 } else { 297 } else {
295 write_unlock(&GlobalSMBSeslock); 298 write_unlock(&GlobalSMBSeslock);
296 write_unlock(&file->f_owner.lock);
297 } 299 }
298 300
299 if (oplock & CIFS_CREATE_ACTION) { 301 if (oplock & CIFS_CREATE_ACTION) {
@@ -409,8 +411,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
409 CIFS_MOUNT_MAP_SPECIAL_CHR); 411 CIFS_MOUNT_MAP_SPECIAL_CHR);
410 if (rc) { 412 if (rc) {
411 up(&pCifsFile->fh_sem); 413 up(&pCifsFile->fh_sem);
412 cFYI(1, ("cifs_open returned 0x%x ", rc)); 414 cFYI(1, ("cifs_open returned 0x%x", rc));
413 cFYI(1, ("oplock: %d ", oplock)); 415 cFYI(1, ("oplock: %d", oplock));
414 } else { 416 } else {
415 pCifsFile->netfid = netfid; 417 pCifsFile->netfid = netfid;
416 pCifsFile->invalidHandle = FALSE; 418 pCifsFile->invalidHandle = FALSE;
@@ -472,7 +474,6 @@ int cifs_close(struct inode *inode, struct file *file)
472 pTcon = cifs_sb->tcon; 474 pTcon = cifs_sb->tcon;
473 if (pSMBFile) { 475 if (pSMBFile) {
474 pSMBFile->closePend = TRUE; 476 pSMBFile->closePend = TRUE;
475 write_lock(&file->f_owner.lock);
476 if (pTcon) { 477 if (pTcon) {
477 /* no sense reconnecting to close a file that is 478 /* no sense reconnecting to close a file that is
478 already closed */ 479 already closed */
@@ -487,23 +488,18 @@ int cifs_close(struct inode *inode, struct file *file)
487 the struct would be in each open file, 488 the struct would be in each open file,
488 but this should give enough time to 489 but this should give enough time to
489 clear the socket */ 490 clear the socket */
490 write_unlock(&file->f_owner.lock);
491 cERROR(1,("close with pending writes")); 491 cERROR(1,("close with pending writes"));
492 msleep(timeout); 492 msleep(timeout);
493 write_lock(&file->f_owner.lock);
494 timeout *= 4; 493 timeout *= 4;
495 } 494 }
496 write_unlock(&file->f_owner.lock);
497 rc = CIFSSMBClose(xid, pTcon, 495 rc = CIFSSMBClose(xid, pTcon,
498 pSMBFile->netfid); 496 pSMBFile->netfid);
499 write_lock(&file->f_owner.lock);
500 } 497 }
501 } 498 }
502 write_lock(&GlobalSMBSeslock); 499 write_lock(&GlobalSMBSeslock);
503 list_del(&pSMBFile->flist); 500 list_del(&pSMBFile->flist);
504 list_del(&pSMBFile->tlist); 501 list_del(&pSMBFile->tlist);
505 write_unlock(&GlobalSMBSeslock); 502 write_unlock(&GlobalSMBSeslock);
506 write_unlock(&file->f_owner.lock);
507 kfree(pSMBFile->search_resume_name); 503 kfree(pSMBFile->search_resume_name);
508 kfree(file->private_data); 504 kfree(file->private_data);
509 file->private_data = NULL; 505 file->private_data = NULL;
@@ -531,7 +527,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
531 (struct cifsFileInfo *)file->private_data; 527 (struct cifsFileInfo *)file->private_data;
532 char *ptmp; 528 char *ptmp;
533 529
534 cFYI(1, ("Closedir inode = 0x%p with ", inode)); 530 cFYI(1, ("Closedir inode = 0x%p", inode));
535 531
536 xid = GetXid(); 532 xid = GetXid();
537 533
@@ -605,7 +601,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
605 } 601 }
606 if (pfLock->fl_flags & FL_ACCESS) 602 if (pfLock->fl_flags & FL_ACCESS)
607 cFYI(1, ("Process suspended by mandatory locking - " 603 cFYI(1, ("Process suspended by mandatory locking - "
608 "not implemented yet ")); 604 "not implemented yet"));
609 if (pfLock->fl_flags & FL_LEASE) 605 if (pfLock->fl_flags & FL_LEASE)
610 cFYI(1, ("Lease on file - not implemented yet")); 606 cFYI(1, ("Lease on file - not implemented yet"));
611 if (pfLock->fl_flags & 607 if (pfLock->fl_flags &
@@ -1375,7 +1371,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1375 1371
1376 xid = GetXid(); 1372 xid = GetXid();
1377 1373
1378 cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 1374 cFYI(1, ("Sync file - name: %s datasync: 0x%x",
1379 dentry->d_name.name, datasync)); 1375 dentry->d_name.name, datasync));
1380 1376
1381 rc = filemap_fdatawrite(inode->i_mapping); 1377 rc = filemap_fdatawrite(inode->i_mapping);
@@ -1404,7 +1400,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1404/* fill in rpages then 1400/* fill in rpages then
1405 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ 1401 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1406 1402
1407/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); 1403/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
1408 1404
1409#if 0 1405#if 0
1410 if (rc < 0) 1406 if (rc < 0)
@@ -1836,7 +1832,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
1836 if (rc < 0) 1832 if (rc < 0)
1837 goto io_error; 1833 goto io_error;
1838 else 1834 else
1839 cFYI(1, ("Bytes read %d ",rc)); 1835 cFYI(1, ("Bytes read %d",rc));
1840 1836
1841 file->f_dentry->d_inode->i_atime = 1837 file->f_dentry->d_inode->i_atime =
1842 current_fs_time(file->f_dentry->d_inode->i_sb); 1838 current_fs_time(file->f_dentry->d_inode->i_sb);
@@ -1957,3 +1953,19 @@ struct address_space_operations cifs_addr_ops = {
1957 /* .sync_page = cifs_sync_page, */ 1953 /* .sync_page = cifs_sync_page, */
1958 /* .direct_IO = */ 1954 /* .direct_IO = */
1959}; 1955};
1956
1957/*
1958 * cifs_readpages requires the server to support a buffer large enough to
1959 * contain the header plus one complete page of data. Otherwise, we need
1960 * to leave cifs_readpages out of the address space operations.
1961 */
1962struct address_space_operations cifs_addr_ops_smallbuf = {
1963 .readpage = cifs_readpage,
1964 .writepage = cifs_writepage,
1965 .writepages = cifs_writepages,
1966 .prepare_write = cifs_prepare_write,
1967 .commit_write = cifs_commit_write,
1968 .set_page_dirty = __set_page_dirty_nobuffers,
1969 /* .sync_page = cifs_sync_page, */
1970 /* .direct_IO = */
1971};
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..7202d534ef0b
--- /dev/null
+++ b/fs/cifs/sess.c
@@ -0,0 +1,538 @@
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
36static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
37{
38 __u32 capabilities = 0;
39
40 /* init fields common to all four types of SessSetup */
41 /* note that header is initialized to zero in header_assemble */
42 pSMB->req.AndXCommand = 0xFF;
43 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
44 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
45
46 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
47
48 /* BB verify whether signing required on neg or just on auth frame
49 (and NTLM case) */
50
51 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
52 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
53
54 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
55 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
56
57 if (ses->capabilities & CAP_UNICODE) {
58 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
59 capabilities |= CAP_UNICODE;
60 }
61 if (ses->capabilities & CAP_STATUS32) {
62 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
63 capabilities |= CAP_STATUS32;
64 }
65 if (ses->capabilities & CAP_DFS) {
66 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
67 capabilities |= CAP_DFS;
68 }
69 if (ses->capabilities & CAP_UNIX) {
70 capabilities |= CAP_UNIX;
71 }
72
73 /* BB check whether to init vcnum BB */
74 return capabilities;
75}
76
77static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
78 const struct nls_table * nls_cp)
79{
80 char * bcc_ptr = *pbcc_area;
81 int bytes_ret = 0;
82
83 /* BB FIXME add check that strings total less
84 than 335 or will need to send them as arrays */
85
86 /* unicode strings, must be word aligned before the call */
87/* if ((long) bcc_ptr % 2) {
88 *bcc_ptr = 0;
89 bcc_ptr++;
90 } */
91 /* copy user */
92 if(ses->userName == NULL) {
93 /* BB what about null user mounts - check that we do this BB */
94 } else { /* 300 should be long enough for any conceivable user name */
95 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
96 300, nls_cp);
97 }
98 bcc_ptr += 2 * bytes_ret;
99 bcc_ptr += 2; /* account for null termination */
100 /* copy domain */
101 if(ses->domainName == NULL)
102 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
103 "CIFS_LINUX_DOM", 32, nls_cp);
104 else
105 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
106 256, nls_cp);
107 bcc_ptr += 2 * bytes_ret;
108 bcc_ptr += 2; /* account for null terminator */
109
110 /* Copy OS version */
111 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
112 nls_cp);
113 bcc_ptr += 2 * bytes_ret;
114 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
115 32, nls_cp);
116 bcc_ptr += 2 * bytes_ret;
117 bcc_ptr += 2; /* trailing null */
118
119 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
120 32, nls_cp);
121 bcc_ptr += 2 * bytes_ret;
122 bcc_ptr += 2; /* trailing null */
123
124 *pbcc_area = bcc_ptr;
125}
126
127static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
128 const struct nls_table * nls_cp)
129{
130 char * bcc_ptr = *pbcc_area;
131
132 /* copy user */
133 /* BB what about null user mounts - check that we do this BB */
134 /* copy user */
135 if(ses->userName == NULL) {
136 /* BB what about null user mounts - check that we do this BB */
137 } else { /* 300 should be long enough for any conceivable user name */
138 strncpy(bcc_ptr, ses->userName, 300);
139 }
140 /* BB improve check for overflow */
141 bcc_ptr += strnlen(ses->userName, 300);
142 *bcc_ptr = 0;
143 bcc_ptr++; /* account for null termination */
144
145 /* copy domain */
146
147 if(ses->domainName == NULL) {
148 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
149 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
150 } else {
151 strncpy(bcc_ptr, ses->domainName, 256);
152 bcc_ptr += strnlen(ses->domainName, 256);
153 }
154 *bcc_ptr = 0;
155 bcc_ptr++;
156
157 /* BB check for overflow here */
158
159 strcpy(bcc_ptr, "Linux version ");
160 bcc_ptr += strlen("Linux version ");
161 strcpy(bcc_ptr, system_utsname.release);
162 bcc_ptr += strlen(system_utsname.release) + 1;
163
164 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
165 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
166
167 *pbcc_area = bcc_ptr;
168}
169
170static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
171 const struct nls_table * nls_cp)
172{
173 int rc = 0;
174 int words_left, len;
175 char * data = *pbcc_area;
176
177
178
179 cFYI(1,("bleft %d",bleft));
180
181
182 /* word align, if bytes remaining is not even */
183 if(bleft % 2) {
184 bleft--;
185 data++;
186 }
187 words_left = bleft / 2;
188
189 /* save off server operating system */
190 len = UniStrnlen((wchar_t *) data, words_left);
191
192/* We look for obvious messed up bcc or strings in response so we do not go off
193 the end since (at least) WIN2K and Windows XP have a major bug in not null
194 terminating last Unicode string in response */
195 if(len >= words_left)
196 return rc;
197
198 if(ses->serverOS)
199 kfree(ses->serverOS);
200 /* UTF-8 string will not grow more than four times as big as UCS-16 */
201 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
202 if(ses->serverOS != NULL) {
203 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
204 nls_cp);
205 }
206 data += 2 * (len + 1);
207 words_left -= len + 1;
208
209 /* save off server network operating system */
210 len = UniStrnlen((wchar_t *) data, words_left);
211
212 if(len >= words_left)
213 return rc;
214
215 if(ses->serverNOS)
216 kfree(ses->serverNOS);
217 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
218 if(ses->serverNOS != NULL) {
219 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
220 nls_cp);
221 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
222 cFYI(1,("NT4 server"));
223 ses->flags |= CIFS_SES_NT4;
224 }
225 }
226 data += 2 * (len + 1);
227 words_left -= len + 1;
228
229 /* save off server domain */
230 len = UniStrnlen((wchar_t *) data, words_left);
231
232 if(len > words_left)
233 return rc;
234
235 if(ses->serverDomain)
236 kfree(ses->serverDomain);
237 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
238 if(ses->serverDomain != NULL) {
239 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
240 nls_cp);
241 ses->serverDomain[2*len] = 0;
242 ses->serverDomain[(2*len) + 1] = 0;
243 }
244 data += 2 * (len + 1);
245 words_left -= len + 1;
246
247 cFYI(1,("words left: %d",words_left));
248
249 return rc;
250}
251
252static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
253 const struct nls_table * nls_cp)
254{
255 int rc = 0;
256 int len;
257 char * bcc_ptr = *pbcc_area;
258
259 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
260
261 len = strnlen(bcc_ptr, bleft);
262 if(len >= bleft)
263 return rc;
264
265 if(ses->serverOS)
266 kfree(ses->serverOS);
267
268 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
269 if(ses->serverOS)
270 strncpy(ses->serverOS, bcc_ptr, len);
271
272 bcc_ptr += len + 1;
273 bleft -= len + 1;
274
275 len = strnlen(bcc_ptr, bleft);
276 if(len >= bleft)
277 return rc;
278
279 if(ses->serverNOS)
280 kfree(ses->serverNOS);
281
282 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
283 if(ses->serverNOS)
284 strncpy(ses->serverNOS, bcc_ptr, len);
285
286 bcc_ptr += len + 1;
287 bleft -= len + 1;
288
289 len = strnlen(bcc_ptr, bleft);
290 if(len > bleft)
291 return rc;
292
293 if(ses->serverDomain)
294 kfree(ses->serverDomain);
295
296 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
297 if(ses->serverOS)
298 strncpy(ses->serverOS, bcc_ptr, len);
299
300 bcc_ptr += len + 1;
301 bleft -= len + 1;
302
303 cFYI(1,("ascii: bytes left %d",bleft));
304
305 return rc;
306}
307
308int
309CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
310 const struct nls_table *nls_cp)
311{
312 int rc = 0;
313 int wct;
314 struct smb_hdr *smb_buf;
315 char *bcc_ptr;
316 char *str_area;
317 SESSION_SETUP_ANDX *pSMB;
318 __u32 capabilities;
319 int count;
320 int resp_buf_type = 0;
321 struct kvec iov[2];
322 enum securityEnum type;
323 __u16 action;
324 int bytes_remaining;
325
326 if(ses == NULL)
327 return -EINVAL;
328
329 type = ses->server->secType;
330
331 cFYI(1,("sess setup type %d",type));
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
357 /* we will send the SMB in two pieces,
358 a fixed length beginning part, and a
359 second part which will include the strings
360 and rest of bcc area, in order to avoid having
361 to do a large buffer 17K allocation */
362 iov[0].iov_base = (char *)pSMB;
363 iov[0].iov_len = smb_buf->smb_buf_length + 4;
364
365 /* 2000 big enough to fit max user, domain, NOS name etc. */
366 str_area = kmalloc(2000, GFP_KERNEL);
367 bcc_ptr = str_area;
368
369 if(type == LANMAN) {
370#ifdef CONFIG_CIFS_WEAK_PW_HASH
371 char lnm_session_key[CIFS_SESS_KEY_SIZE];
372
373 /* no capabilities flags in old lanman negotiation */
374
375 pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
376 /* BB calculate hash with password */
377 /* and copy into bcc */
378
379 calc_lanman_hash(ses, lnm_session_key);
380
381/* #ifdef CONFIG_CIFS_DEBUG2
382 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
383 CIFS_SESS_KEY_SIZE);
384#endif */
385 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
386 bcc_ptr += CIFS_SESS_KEY_SIZE;
387
388 /* can not sign if LANMAN negotiated so no need
389 to calculate signing key? but what if server
390 changed to do higher than lanman dialect and
391 we reconnected would we ever calc signing_key? */
392
393 cFYI(1,("Negotiating LANMAN setting up strings"));
394 /* Unicode not allowed for LANMAN dialects */
395 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
396#endif
397 } else if (type == NTLM) {
398 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
399
400 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
401 pSMB->req_no_secext.CaseInsensitivePasswordLength =
402 cpu_to_le16(CIFS_SESS_KEY_SIZE);
403 pSMB->req_no_secext.CaseSensitivePasswordLength =
404 cpu_to_le16(CIFS_SESS_KEY_SIZE);
405
406 /* calculate session key */
407 SMBNTencrypt(ses->password, ses->server->cryptKey,
408 ntlm_session_key);
409
410 if(first_time) /* should this be moved into common code
411 with similar ntlmv2 path? */
412 cifs_calculate_mac_key(ses->server->mac_signing_key,
413 ntlm_session_key, ses->password);
414 /* copy session key */
415
416 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
417 bcc_ptr += CIFS_SESS_KEY_SIZE;
418 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
419 bcc_ptr += CIFS_SESS_KEY_SIZE;
420 if(ses->capabilities & CAP_UNICODE) {
421 /* unicode strings must be word aligned */
422 if (iov[0].iov_len % 2) {
423 *bcc_ptr = 0;
424 bcc_ptr++;
425 }
426 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
427 } else
428 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
429 } else if (type == NTLMv2) {
430 char * v2_sess_key =
431 kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
432
433 /* BB FIXME change all users of v2_sess_key to
434 struct ntlmv2_resp */
435
436 if(v2_sess_key == NULL) {
437 cifs_small_buf_release(smb_buf);
438 return -ENOMEM;
439 }
440
441 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
442
443 /* LM2 password would be here if we supported it */
444 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
445 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
446
447 pSMB->req_no_secext.CaseSensitivePasswordLength =
448 cpu_to_le16(sizeof(struct ntlmv2_resp));
449
450 /* calculate session key */
451 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
452 if(first_time) /* should this be moved into common code
453 with similar ntlmv2 path? */
454 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
455 response BB FIXME, v2_sess_key); */
456
457 /* copy session key */
458
459 /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
460 bcc_ptr += LM2_SESS_KEY_SIZE; */
461 memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
462 bcc_ptr += sizeof(struct ntlmv2_resp);
463 kfree(v2_sess_key);
464 if(ses->capabilities & CAP_UNICODE) {
465 if(iov[0].iov_len % 2) {
466 *bcc_ptr = 0;
467 } bcc_ptr++;
468 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
469 } else
470 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
471 } else /* NTLMSSP or SPNEGO */ {
472 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
473 capabilities |= CAP_EXTENDED_SECURITY;
474 pSMB->req.Capabilities = cpu_to_le32(capabilities);
475 /* BB set password lengths */
476 }
477
478 count = (long) bcc_ptr - (long) str_area;
479 smb_buf->smb_buf_length += count;
480
481 BCC_LE(smb_buf) = cpu_to_le16(count);
482
483 iov[1].iov_base = str_area;
484 iov[1].iov_len = count;
485 rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
486 /* SMB request buf freed in SendReceive2 */
487
488 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
489 if(rc)
490 goto ssetup_exit;
491
492 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
493 smb_buf = (struct smb_hdr *)iov[0].iov_base;
494
495 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
496 rc = -EIO;
497 cERROR(1,("bad word count %d", smb_buf->WordCount));
498 goto ssetup_exit;
499 }
500 action = le16_to_cpu(pSMB->resp.Action);
501 if (action & GUEST_LOGIN)
502 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
503 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
504 cFYI(1, ("UID = %d ", ses->Suid));
505 /* response can have either 3 or 4 word count - Samba sends 3 */
506 /* and lanman response is 3 */
507 bytes_remaining = BCC(smb_buf);
508 bcc_ptr = pByteArea(smb_buf);
509
510 if(smb_buf->WordCount == 4) {
511 __u16 blob_len;
512 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
513 bcc_ptr += blob_len;
514 if(blob_len > bytes_remaining) {
515 cERROR(1,("bad security blob length %d", blob_len));
516 rc = -EINVAL;
517 goto ssetup_exit;
518 }
519 bytes_remaining -= blob_len;
520 }
521
522 /* BB check if Unicode and decode strings */
523 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
524 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
525 ses, nls_cp);
526 else
527 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
528
529ssetup_exit:
530 kfree(str_area);
531 if(resp_buf_type == CIFS_SMALL_BUFFER) {
532 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
533 cifs_small_buf_release(iov[0].iov_base);
534 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
535 cifs_buf_release(iov[0].iov_base);
536
537 return rc;
538}
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 */