diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 40 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 16 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/README | 34 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 134 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.c | 1 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 140 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 70 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 98 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 14 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 273 | ||||
-rw-r--r-- | fs/cifs/connect.c | 448 | ||||
-rw-r--r-- | fs/cifs/dir.c | 15 | ||||
-rw-r--r-- | fs/cifs/fcntl.c | 4 | ||||
-rw-r--r-- | fs/cifs/file.c | 43 | ||||
-rw-r--r-- | fs/cifs/inode.c | 39 | ||||
-rw-r--r-- | fs/cifs/link.c | 7 | ||||
-rw-r--r-- | fs/cifs/misc.c | 10 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 4 | ||||
-rw-r--r-- | fs/cifs/ntlmssp.c | 143 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 184 | ||||
-rw-r--r-- | fs/cifs/sess.c | 525 | ||||
-rw-r--r-- | fs/cifs/smbencrypt.c | 1 | ||||
-rw-r--r-- | fs/cifs/transport.c | 3 |
28 files changed, 1491 insertions, 780 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 2aa4624cc018..467f7ae5f092 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -1713,7 +1713,7 @@ config CIFS_STATS | |||
1713 | mounted by the cifs client to be displayed in /proc/fs/cifs/Stats | 1713 | mounted by the cifs client to be displayed in /proc/fs/cifs/Stats |
1714 | 1714 | ||
1715 | config CIFS_STATS2 | 1715 | config CIFS_STATS2 |
1716 | bool "CIFS extended statistics" | 1716 | bool "Extended statistics" |
1717 | depends on CIFS_STATS | 1717 | depends on CIFS_STATS |
1718 | help | 1718 | help |
1719 | Enabling this option will allow more detailed statistics on SMB | 1719 | Enabling this option will allow more detailed statistics on SMB |
@@ -1726,6 +1726,32 @@ config CIFS_STATS2 | |||
1726 | Unless you are a developer or are doing network performance analysis | 1726 | Unless you are a developer or are doing network performance analysis |
1727 | or tuning, say N. | 1727 | or tuning, say N. |
1728 | 1728 | ||
1729 | config CIFS_WEAK_PW_HASH | ||
1730 | bool "Support legacy servers which use weaker LANMAN security" | ||
1731 | depends on CIFS | ||
1732 | help | ||
1733 | Modern CIFS servers including Samba and most Windows versions | ||
1734 | (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos) | ||
1735 | security mechanisms. These hash the password more securely | ||
1736 | than the mechanisms used in the older LANMAN version of the | ||
1737 | SMB protocol needed to establish sessions with old SMB servers. | ||
1738 | |||
1739 | Enabling this option allows the cifs module to mount to older | ||
1740 | LANMAN based servers such as OS/2 and Windows 95, but such | ||
1741 | mounts may be less secure than mounts using NTLM or more recent | ||
1742 | security mechanisms if you are on a public network. Unless you | ||
1743 | have a need to access old SMB servers (and are on a private | ||
1744 | network) you probably want to say N. Even if this support | ||
1745 | is enabled in the kernel build, they will not be used | ||
1746 | automatically. At runtime LANMAN mounts are disabled but | ||
1747 | can be set to required (or optional) either in | ||
1748 | /proc/fs/cifs (see fs/cifs/README for more detail) or via an | ||
1749 | option on the mount command. This support is disabled by | ||
1750 | default in order to reduce the possibility of a downgrade | ||
1751 | attack. | ||
1752 | |||
1753 | If unsure, say N. | ||
1754 | |||
1729 | config CIFS_XATTR | 1755 | config CIFS_XATTR |
1730 | bool "CIFS extended attributes" | 1756 | bool "CIFS extended attributes" |
1731 | depends on CIFS | 1757 | depends on CIFS |
@@ -1754,6 +1780,16 @@ config CIFS_POSIX | |||
1754 | (such as Samba 3.10 and later) which can negotiate | 1780 | (such as Samba 3.10 and later) which can negotiate |
1755 | CIFS POSIX ACL support. If unsure, say N. | 1781 | CIFS POSIX ACL support. If unsure, say N. |
1756 | 1782 | ||
1783 | config CIFS_DEBUG2 | ||
1784 | bool "Enable additional CIFS debugging routines" | ||
1785 | help | ||
1786 | Enabling this option adds a few more debugging routines | ||
1787 | to the cifs code which slightly increases the size of | ||
1788 | the cifs module and can cause additional logging of debug | ||
1789 | messages in some error paths, slowing performance. This | ||
1790 | option can be turned off unless you are debugging | ||
1791 | cifs problems. If unsure, say N. | ||
1792 | |||
1757 | config CIFS_EXPERIMENTAL | 1793 | config CIFS_EXPERIMENTAL |
1758 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 1794 | bool "CIFS Experimental Features (EXPERIMENTAL)" |
1759 | depends on CIFS && EXPERIMENTAL | 1795 | depends on CIFS && EXPERIMENTAL |
@@ -1769,7 +1805,7 @@ config CIFS_EXPERIMENTAL | |||
1769 | If unsure, say N. | 1805 | If unsure, say N. |
1770 | 1806 | ||
1771 | config CIFS_UPCALL | 1807 | config CIFS_UPCALL |
1772 | bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" | 1808 | bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" |
1773 | depends on CIFS_EXPERIMENTAL | 1809 | depends on CIFS_EXPERIMENTAL |
1774 | select CONNECTOR | 1810 | select CONNECTOR |
1775 | help | 1811 | help |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 7271bb0257f6..79a202b8f66a 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,9 +1,23 @@ | |||
1 | Version 1.44 | ||
2 | ------------ | ||
3 | Rewritten sessionsetup support, including support for legacy SMB | ||
4 | session setup needed for OS/2 and older servers such as Windows 95 and 98. | ||
5 | Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst | ||
6 | so we can do search (ls etc.) to OS/2. Do not send NTCreateX | ||
7 | or recent levels of FindFirst unless server says it supports NT SMBs | ||
8 | (instead use legacy equivalents from LANMAN dialect). Fix to allow | ||
9 | NTLMv2 authentication support (now can use stronger password hashing | ||
10 | on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004) | ||
11 | |||
1 | Version 1.43 | 12 | Version 1.43 |
2 | ------------ | 13 | ------------ |
3 | POSIX locking to servers which support CIFS POSIX Extensions | 14 | POSIX locking to servers which support CIFS POSIX Extensions |
4 | (disabled by default controlled by proc/fs/cifs/Experimental). | 15 | (disabled by default controlled by proc/fs/cifs/Experimental). |
5 | Handle conversion of long share names (especially Asian languages) | 16 | Handle conversion of long share names (especially Asian languages) |
6 | to Unicode during mount. | 17 | to Unicode during mount. Fix memory leak in sess struct on reconnect. |
18 | Fix rare oops after acpi suspend. Fix O_TRUNC opens to overwrite on | ||
19 | cifs open which helps rare case when setpathinfo fails or server does | ||
20 | not support it. | ||
7 | 21 | ||
8 | Version 1.42 | 22 | Version 1.42 |
9 | ------------ | 23 | ------------ |
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 | # |
4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
5 | 5 | ||
6 | cifs-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 | 6 | cifs-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..46c2cfa5acf3 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -453,6 +453,8 @@ sec Security mode. Allowed values are: | |||
453 | server requires signing also can be the default) | 453 | server requires signing also can be the default) |
454 | ntlmv2 Use NTLMv2 password hashing | 454 | ntlmv2 Use NTLMv2 password hashing |
455 | ntlmv2i Use NTLMv2 password hashing with packet signing | 455 | ntlmv2i Use NTLMv2 password hashing with packet signing |
456 | lanman (if configured in kernel config) use older | ||
457 | lanman hash | ||
456 | 458 | ||
457 | The mount.cifs mount helper also accepts a few mount options before -o | 459 | The mount.cifs mount helper also accepts a few mount options before -o |
458 | including: | 460 | including: |
@@ -485,14 +487,34 @@ PacketSigningEnabled If set to one, cifs packet signing is enabled | |||
485 | it. If set to two, cifs packet signing is | 487 | it. If set to two, cifs packet signing is |
486 | required even if the server considers packet | 488 | required even if the server considers packet |
487 | signing optional. (default 1) | 489 | signing optional. (default 1) |
490 | SecurityFlags Flags which control security negotiation and | ||
491 | also packet signing. Authentication (may/must) | ||
492 | flags (e.g. for NTLM and/or NTLMv2) may be combined with | ||
493 | the signing flags. Specifying two different password | ||
494 | hashing mechanisms (as "must use") on the other hand | ||
495 | does not make much sense. Default flags are | ||
496 | 0x07007 | ||
497 | (NTLM, NTLMv2 and packet signing allowed). Maximum | ||
498 | allowable flags if you want to allow mounts to servers | ||
499 | using weaker password hashes is 0x37037 (lanman, | ||
500 | plaintext, ntlm, ntlmv2, signing allowed): | ||
501 | |||
502 | may use packet signing 0x00001 | ||
503 | must use packet signing 0x01001 | ||
504 | may use NTLM (most common password hash) 0x00002 | ||
505 | must use NTLM 0x02002 | ||
506 | may use NTLMv2 0x00004 | ||
507 | must use NTLMv2 0x04004 | ||
508 | may use Kerberos security (not implemented yet) 0x00008 | ||
509 | must use Kerberos (not implemented yet) 0x08008 | ||
510 | may use lanman (weak) password hash 0x00010 | ||
511 | must use lanman password hash 0x10010 | ||
512 | may use plaintext passwords 0x00020 | ||
513 | must use plaintext passwords 0x20020 | ||
514 | (reserved for future packet encryption) 0x00040 | ||
515 | |||
488 | cifsFYI If set to one, additional debug information is | 516 | cifsFYI If set to one, additional debug information is |
489 | logged to the system error log. (default 0) | 517 | logged to the system error log. (default 0) |
490 | ExtendedSecurity If set to one, SPNEGO session establishment | ||
491 | is allowed which enables more advanced | ||
492 | secure CIFS session establishment (default 0) | ||
493 | NTLMV2Enabled 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) | ||
496 | traceSMB If set to one, debug information is logged to the | 518 | traceSMB If set to one, debug information is logged to the |
497 | system error log with the start of smb requests | 519 | system error log with the start of smb requests |
498 | and responses (default 0) | 520 | 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 | ||
61 | void 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 | |||
70 | void 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 |
61 | static int | 112 | static int |
62 | cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, | 113 | cifs_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; | |||
395 | static write_proc_t traceSMB_write; | 445 | static write_proc_t traceSMB_write; |
396 | static read_proc_t multiuser_mount_read; | 446 | static read_proc_t multiuser_mount_read; |
397 | static write_proc_t multiuser_mount_write; | 447 | static write_proc_t multiuser_mount_write; |
398 | static read_proc_t extended_security_read; | 448 | static read_proc_t security_flags_read; |
399 | static write_proc_t extended_security_write; | 449 | static write_proc_t security_flags_write; |
400 | static read_proc_t ntlmv2_enabled_read; | 450 | /* static read_proc_t ntlmv2_enabled_read; |
401 | static write_proc_t ntlmv2_enabled_write; | 451 | static write_proc_t ntlmv2_enabled_write; |
402 | static read_proc_t packet_signing_enabled_read; | 452 | static read_proc_t packet_signing_enabled_read; |
403 | static write_proc_t packet_signing_enabled_write; | 453 | static write_proc_t packet_signing_enabled_write;*/ |
404 | static read_proc_t experimEnabled_read; | 454 | static read_proc_t experimEnabled_read; |
405 | static write_proc_t experimEnabled_write; | 455 | static write_proc_t experimEnabled_write; |
406 | static read_proc_t linuxExtensionsEnabled_read; | 456 | static 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 | ||
485 | void | 535 | void |
@@ -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 | ||
784 | static int | 834 | static int |
785 | extended_security_read(char *page, char **start, off_t off, | 835 | security_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 | } |
805 | static int | 855 | static int |
806 | extended_security_write(struct file *file, const char __user *buffer, | 856 | security_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 | ||
823 | static int | 901 | /* static int |
824 | ntlmv2_enabled_read(char *page, char **start, off_t off, | 902 | ntlmv2_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 | ||
26 | void cifs_dump_mem(char *label, void *data, int length); | 26 | void cifs_dump_mem(char *label, void *data, int length); |
27 | #ifdef CONFIG_CIFS_DEBUG2 | ||
28 | void cifs_dump_detail(struct smb_hdr *); | ||
29 | void cifs_dump_mids(struct TCP_Server_Info *); | ||
30 | #endif | ||
27 | extern int traceSMB; /* flag which enables the function below */ | 31 | extern int traceSMB; /* flag which enables the function below */ |
28 | void dump_smb(struct smb_hdr *, int); | 32 | void 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 | ||
36 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | 38 | extern void mdfour(unsigned char *out, unsigned char *in, int n); |
37 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); | 39 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); |
40 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | ||
41 | unsigned char *p24); | ||
38 | 42 | ||
39 | static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, | 43 | static 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 | ||
211 | int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info) | 215 | int 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 | } |
262 | void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) | 269 | |
270 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
271 | void 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 | |||
309 | static 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 | } | ||
353 | calc_exit_1: | ||
354 | kfree(user); | ||
355 | calc_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 | |||
363 | void 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 | |||
384 | void 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 7520f4687158..f2e285457bee 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -56,8 +56,8 @@ unsigned int experimEnabled = 0; | |||
56 | unsigned int linuxExtEnabled = 1; | 56 | unsigned int linuxExtEnabled = 1; |
57 | unsigned int lookupCacheEnabled = 1; | 57 | unsigned int lookupCacheEnabled = 1; |
58 | unsigned int multiuser_mount = 0; | 58 | unsigned int multiuser_mount = 0; |
59 | unsigned int extended_security = 0; | 59 | unsigned int extended_security = CIFSSEC_DEF; |
60 | unsigned int ntlmv2_support = 0; | 60 | /* unsigned int ntlmv2_support = 0; */ |
61 | unsigned int sign_CIFS_PDUs = 1; | 61 | unsigned int sign_CIFS_PDUs = 1; |
62 | extern struct task_struct * oplockThread; /* remove sparse warning */ | 62 | extern struct task_struct * oplockThread; /* remove sparse warning */ |
63 | struct task_struct * oplockThread = NULL; | 63 | struct task_struct * oplockThread = NULL; |
@@ -906,7 +906,7 @@ static int cifs_dnotify_thread(void * dummyarg) | |||
906 | struct cifsSesInfo *ses; | 906 | struct cifsSesInfo *ses; |
907 | 907 | ||
908 | do { | 908 | do { |
909 | if(try_to_freeze()) | 909 | if (try_to_freeze()) |
910 | continue; | 910 | continue; |
911 | set_current_state(TASK_INTERRUPTIBLE); | 911 | set_current_state(TASK_INTERRUPTIBLE); |
912 | schedule_timeout(15*HZ); | 912 | 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 | ||
35 | extern struct address_space_operations cifs_addr_ops; | 35 | extern struct address_space_operations cifs_addr_ops; |
36 | extern struct address_space_operations cifs_addr_ops_smallbuf; | ||
36 | 37 | ||
37 | /* Functions related to super block operations */ | 38 | /* Functions related to super block operations */ |
38 | extern struct super_operations cifs_super_ops; | 39 | extern struct super_operations cifs_super_ops; |
@@ -99,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
99 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 100 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
100 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 101 | extern int cifs_ioctl (struct inode * inode, struct file * filep, |
101 | unsigned int command, unsigned long arg); | 102 | unsigned int command, unsigned long arg); |
102 | #define CIFS_VERSION "1.43" | 103 | #define CIFS_VERSION "1.44" |
103 | #endif /* _CIFSFS_H */ | 104 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 006eb33bff5f..87453a6bcaf8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -88,7 +88,8 @@ enum statusEnum { | |||
88 | }; | 88 | }; |
89 | 89 | ||
90 | enum securityEnum { | 90 | enum securityEnum { |
91 | NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */ | 91 | LANMAN = 0, /* Legacy LANMAN auth */ |
92 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ | ||
92 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ | 93 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ |
93 | RawNTLMSSP, /* NTLMSSP without SPNEGO */ | 94 | RawNTLMSSP, /* NTLMSSP without SPNEGO */ |
94 | NTLMSSP, /* NTLMSSP via SPNEGO */ | 95 | NTLMSSP, /* NTLMSSP via SPNEGO */ |
@@ -157,7 +158,7 @@ struct TCP_Server_Info { | |||
157 | /* 16th byte of RFC1001 workstation name is always null */ | 158 | /* 16th byte of RFC1001 workstation name is always null */ |
158 | char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | 159 | char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; |
159 | __u32 sequence_number; /* needed for CIFS PDU signature */ | 160 | __u32 sequence_number; /* needed for CIFS PDU signature */ |
160 | char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; | 161 | char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; |
161 | }; | 162 | }; |
162 | 163 | ||
163 | /* | 164 | /* |
@@ -179,7 +180,9 @@ struct cifsUidInfo { | |||
179 | struct cifsSesInfo { | 180 | struct cifsSesInfo { |
180 | struct list_head cifsSessionList; | 181 | struct list_head cifsSessionList; |
181 | struct semaphore sesSem; | 182 | struct semaphore sesSem; |
183 | #if 0 | ||
182 | struct cifsUidInfo *uidInfo; /* pointer to user info */ | 184 | struct cifsUidInfo *uidInfo; /* pointer to user info */ |
185 | #endif | ||
183 | struct TCP_Server_Info *server; /* pointer to server info */ | 186 | struct TCP_Server_Info *server; /* pointer to server info */ |
184 | atomic_t inUse; /* # of mounts (tree connections) on this ses */ | 187 | atomic_t inUse; /* # of mounts (tree connections) on this ses */ |
185 | enum statusEnum status; | 188 | enum statusEnum status; |
@@ -194,7 +197,7 @@ struct cifsSesInfo { | |||
194 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for | 197 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for |
195 | TCP names - will ipv6 and sctp addresses fit? */ | 198 | TCP names - will ipv6 and sctp addresses fit? */ |
196 | char userName[MAX_USERNAME_SIZE + 1]; | 199 | char userName[MAX_USERNAME_SIZE + 1]; |
197 | char domainName[MAX_USERNAME_SIZE + 1]; | 200 | char * domainName; |
198 | char * password; | 201 | char * password; |
199 | }; | 202 | }; |
200 | /* session flags */ | 203 | /* session flags */ |
@@ -209,12 +212,12 @@ struct cifsTconInfo { | |||
209 | struct list_head openFileList; | 212 | struct list_head openFileList; |
210 | struct semaphore tconSem; | 213 | struct semaphore tconSem; |
211 | struct cifsSesInfo *ses; /* pointer to session associated with */ | 214 | struct cifsSesInfo *ses; /* pointer to session associated with */ |
212 | char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */ | 215 | char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */ |
213 | char *nativeFileSystem; | 216 | char *nativeFileSystem; |
214 | __u16 tid; /* The 2 byte tree id */ | 217 | __u16 tid; /* The 2 byte tree id */ |
215 | __u16 Flags; /* optional support bits */ | 218 | __u16 Flags; /* optional support bits */ |
216 | enum statusEnum tidStatus; | 219 | enum statusEnum tidStatus; |
217 | atomic_t useCount; /* how many mounts (explicit or implicit) to this share */ | 220 | atomic_t useCount; /* how many explicit/implicit mounts to share */ |
218 | #ifdef CONFIG_CIFS_STATS | 221 | #ifdef CONFIG_CIFS_STATS |
219 | atomic_t num_smbs_sent; | 222 | atomic_t num_smbs_sent; |
220 | atomic_t num_writes; | 223 | atomic_t num_writes; |
@@ -254,7 +257,7 @@ struct cifsTconInfo { | |||
254 | spinlock_t stat_lock; | 257 | spinlock_t stat_lock; |
255 | #endif /* CONFIG_CIFS_STATS */ | 258 | #endif /* CONFIG_CIFS_STATS */ |
256 | FILE_SYSTEM_DEVICE_INFO fsDevInfo; | 259 | FILE_SYSTEM_DEVICE_INFO fsDevInfo; |
257 | FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ | 260 | FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ |
258 | FILE_SYSTEM_UNIX_INFO fsUnixInfo; | 261 | FILE_SYSTEM_UNIX_INFO fsUnixInfo; |
259 | unsigned retry:1; | 262 | unsigned retry:1; |
260 | unsigned nocase:1; | 263 | unsigned nocase:1; |
@@ -305,7 +308,6 @@ struct cifsFileInfo { | |||
305 | atomic_t wrtPending; /* handle in use - defer close */ | 308 | atomic_t wrtPending; /* handle in use - defer close */ |
306 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ | 309 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ |
307 | char * search_resume_name; /* BB removeme BB */ | 310 | char * search_resume_name; /* BB removeme BB */ |
308 | unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */ | ||
309 | struct cifs_search_info srch_inf; | 311 | struct cifs_search_info srch_inf; |
310 | }; | 312 | }; |
311 | 313 | ||
@@ -391,9 +393,9 @@ struct mid_q_entry { | |||
391 | struct smb_hdr *resp_buf; /* response buffer */ | 393 | struct smb_hdr *resp_buf; /* response buffer */ |
392 | int midState; /* wish this were enum but can not pass to wait_event */ | 394 | int midState; /* wish this were enum but can not pass to wait_event */ |
393 | __u8 command; /* smb command code */ | 395 | __u8 command; /* smb command code */ |
394 | unsigned multiPart:1; /* multiple responses to one SMB request */ | ||
395 | unsigned largeBuf:1; /* if valid response, is pointer to large buf */ | 396 | unsigned largeBuf:1; /* if valid response, is pointer to large buf */ |
396 | unsigned multiResp:1; /* multiple trans2 responses for one request */ | 397 | unsigned multiRsp:1; /* multiple trans2 responses for one request */ |
398 | unsigned multiEnd:1; /* both received */ | ||
397 | }; | 399 | }; |
398 | 400 | ||
399 | struct oplock_q_entry { | 401 | struct oplock_q_entry { |
@@ -430,15 +432,35 @@ struct dir_notify_req { | |||
430 | #define CIFS_LARGE_BUFFER 2 | 432 | #define CIFS_LARGE_BUFFER 2 |
431 | #define CIFS_IOVEC 4 /* array of response buffers */ | 433 | #define CIFS_IOVEC 4 /* array of response buffers */ |
432 | 434 | ||
433 | /* Type of session setup needed */ | 435 | /* Security Flags: indicate type of session setup needed */ |
434 | #define CIFS_PLAINTEXT 0 | 436 | #define CIFSSEC_MAY_SIGN 0x00001 |
435 | #define CIFS_LANMAN 1 | 437 | #define CIFSSEC_MAY_NTLM 0x00002 |
436 | #define CIFS_NTLM 2 | 438 | #define CIFSSEC_MAY_NTLMV2 0x00004 |
437 | #define CIFS_NTLMSSP_NEG 3 | 439 | #define CIFSSEC_MAY_KRB5 0x00008 |
438 | #define CIFS_NTLMSSP_AUTH 4 | 440 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
439 | #define CIFS_SPNEGO_INIT 5 | 441 | #define CIFSSEC_MAY_LANMAN 0x00010 |
440 | #define CIFS_SPNEGO_TARG 6 | 442 | #define CIFSSEC_MAY_PLNTXT 0x00020 |
441 | 443 | #endif /* weak passwords */ | |
444 | #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ | ||
445 | |||
446 | #define CIFSSEC_MUST_SIGN 0x01001 | ||
447 | /* note that only one of the following can be set so the | ||
448 | result of setting MUST flags more than once will be to | ||
449 | require use of the stronger protocol */ | ||
450 | #define CIFSSEC_MUST_NTLM 0x02002 | ||
451 | #define CIFSSEC_MUST_NTLMV2 0x04004 | ||
452 | #define CIFSSEC_MUST_KRB5 0x08008 | ||
453 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
454 | #define CIFSSEC_MUST_LANMAN 0x10010 | ||
455 | #define CIFSSEC_MUST_PLNTXT 0x20020 | ||
456 | #define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ | ||
457 | #else | ||
458 | #define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */ | ||
459 | #endif /* WEAK_PW_HASH */ | ||
460 | #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ | ||
461 | |||
462 | #define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | ||
463 | #define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2 | ||
442 | /* | 464 | /* |
443 | ***************************************************************** | 465 | ***************************************************************** |
444 | * All constants go here | 466 | * All constants go here |
@@ -500,16 +522,16 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ | |||
500 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; | 522 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; |
501 | 523 | ||
502 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ | 524 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ |
503 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */ | 525 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */ |
504 | 526 | ||
505 | /* | 527 | /* |
506 | * Global transaction id (XID) information | 528 | * Global transaction id (XID) information |
507 | */ | 529 | */ |
508 | GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ | 530 | GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ |
509 | GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ | 531 | GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ |
510 | GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ | 532 | GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ |
511 | GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */ | 533 | GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */ |
512 | /* on midQ entries */ | 534 | /* on midQ entries */ |
513 | GLOBAL_EXTERN char Local_System_Name[15]; | 535 | GLOBAL_EXTERN char Local_System_Name[15]; |
514 | 536 | ||
515 | /* | 537 | /* |
@@ -531,7 +553,7 @@ GLOBAL_EXTERN atomic_t smBufAllocCount; | |||
531 | GLOBAL_EXTERN atomic_t midCount; | 553 | GLOBAL_EXTERN atomic_t midCount; |
532 | 554 | ||
533 | /* Misc globals */ | 555 | /* Misc globals */ |
534 | GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions | 556 | GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions |
535 | to be established on existing mount if we | 557 | to be established on existing mount if we |
536 | have the uid/password or Kerberos credential | 558 | have the uid/password or Kerberos credential |
537 | or equivalent for current user */ | 559 | or equivalent for current user */ |
@@ -540,8 +562,8 @@ GLOBAL_EXTERN unsigned int experimEnabled; | |||
540 | GLOBAL_EXTERN unsigned int lookupCacheEnabled; | 562 | GLOBAL_EXTERN unsigned int lookupCacheEnabled; |
541 | GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent | 563 | GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent |
542 | with more secure ntlmssp2 challenge/resp */ | 564 | with more secure ntlmssp2 challenge/resp */ |
543 | GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */ | ||
544 | GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ | 565 | GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ |
566 | GLOBAL_EXTERN unsigned int secFlags; | ||
545 | GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ | 567 | GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ |
546 | GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ | 568 | GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ |
547 | GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ | 569 | GLOBAL_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 | |||
411 | typedef 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 | |||
403 | typedef struct negotiate_rsp { | 432 | typedef 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 | |||
577 | struct ntlmssp2_name { | ||
578 | __le16 type; | ||
579 | __le16 length; | ||
580 | /* char name[length]; */ | ||
581 | } __attribute__((packed)); | ||
582 | |||
583 | struct 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 | ||
575 | typedef struct smb_com_tconx_rsp { | 624 | typedef 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 { | |||
1844 | typedef struct { | 1898 | typedef 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 | ||
1849 | typedef struct { | 1903 | typedef 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 | ||
1948 | struct file_allocation_info { | 2002 | struct 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 | ||
1952 | struct file_end_of_file_info { | 2007 | struct 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 | ||
2059 | typedef struct { | 2114 | typedef 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 | ||
2074 | typedef struct { | 2129 | typedef 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 | ||
2091 | typedef struct { | 2146 | typedef 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 | |||
2164 | typedef 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 | ||
2110 | struct win_dev { | 2180 | struct win_dev { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 310ea2f0e0bf..7ed06bfa1921 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -68,10 +68,10 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , | |||
68 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, | 68 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, |
69 | struct cifsSesInfo *ses, | 69 | struct cifsSesInfo *ses, |
70 | void ** request_buf); | 70 | void ** request_buf); |
71 | #endif | ||
71 | extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | 72 | extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, |
72 | const int stage, int * pNTLMv2_flg, | 73 | const int stage, |
73 | const struct nls_table *nls_cp); | 74 | const struct nls_table *nls_cp); |
74 | #endif | ||
75 | extern __u16 GetNextMid(struct TCP_Server_Info *server); | 75 | extern __u16 GetNextMid(struct TCP_Server_Info *server); |
76 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, | 76 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, |
77 | struct cifsTconInfo *); | 77 | struct cifsTconInfo *); |
@@ -285,8 +285,14 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, | |||
285 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, | 285 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, |
286 | __u32 expected_sequence_number); | 286 | __u32 expected_sequence_number); |
287 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); | 287 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); |
288 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); | 288 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, |
289 | extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); | 289 | const struct nls_table *); |
290 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); | ||
291 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | ||
292 | const struct nls_table *); | ||
293 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
294 | extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key); | ||
295 | #endif /* CIFS_WEAK_PW_HASH */ | ||
290 | extern int CIFSSMBCopy(int xid, | 296 | extern int CIFSSMBCopy(int xid, |
291 | struct cifsTconInfo *source_tcon, | 297 | struct cifsTconInfo *source_tcon, |
292 | const char *fromName, | 298 | const char *fromName, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 925881e00ff2..271a037a386f 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -44,8 +44,11 @@ static struct { | |||
44 | int index; | 44 | int index; |
45 | char *name; | 45 | char *name; |
46 | } protocols[] = { | 46 | } protocols[] = { |
47 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
48 | {LANMAN_PROT, "\2LM1.2X002"}, | ||
49 | #endif /* weak password hashing for legacy clients */ | ||
47 | {CIFS_PROT, "\2NT LM 0.12"}, | 50 | {CIFS_PROT, "\2NT LM 0.12"}, |
48 | {CIFS_PROT, "\2POSIX 2"}, | 51 | {POSIX_PROT, "\2POSIX 2"}, |
49 | {BAD_PROT, "\2"} | 52 | {BAD_PROT, "\2"} |
50 | }; | 53 | }; |
51 | #else | 54 | #else |
@@ -53,11 +56,29 @@ static struct { | |||
53 | int index; | 56 | int index; |
54 | char *name; | 57 | char *name; |
55 | } protocols[] = { | 58 | } protocols[] = { |
59 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
60 | {LANMAN_PROT, "\2LM1.2X002"}, | ||
61 | #endif /* weak password hashing for legacy clients */ | ||
56 | {CIFS_PROT, "\2NT LM 0.12"}, | 62 | {CIFS_PROT, "\2NT LM 0.12"}, |
57 | {BAD_PROT, "\2"} | 63 | {BAD_PROT, "\2"} |
58 | }; | 64 | }; |
59 | #endif | 65 | #endif |
60 | 66 | ||
67 | /* define the number of elements in the cifs dialect array */ | ||
68 | #ifdef CONFIG_CIFS_POSIX | ||
69 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
70 | #define CIFS_NUM_PROT 3 | ||
71 | #else | ||
72 | #define CIFS_NUM_PROT 2 | ||
73 | #endif /* CIFS_WEAK_PW_HASH */ | ||
74 | #else /* not posix */ | ||
75 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
76 | #define CIFS_NUM_PROT 2 | ||
77 | #else | ||
78 | #define CIFS_NUM_PROT 1 | ||
79 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ | ||
80 | #endif /* CIFS_POSIX */ | ||
81 | |||
61 | 82 | ||
62 | /* Mark as invalid, all open files on tree connections since they | 83 | /* Mark as invalid, all open files on tree connections since they |
63 | were closed when session to server was lost */ | 84 | were closed when session to server was lost */ |
@@ -322,7 +343,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
322 | /* potential retries of smb operations it turns out we can determine */ | 343 | /* potential retries of smb operations it turns out we can determine */ |
323 | /* from the mid flags when the request buffer can be resent without */ | 344 | /* from the mid flags when the request buffer can be resent without */ |
324 | /* having to use a second distinct buffer for the response */ | 345 | /* having to use a second distinct buffer for the response */ |
325 | *response_buf = *request_buf; | 346 | if(response_buf) |
347 | *response_buf = *request_buf; | ||
326 | 348 | ||
327 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, | 349 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, |
328 | wct /*wct */ ); | 350 | wct /*wct */ ); |
@@ -373,6 +395,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
373 | NEGOTIATE_RSP *pSMBr; | 395 | NEGOTIATE_RSP *pSMBr; |
374 | int rc = 0; | 396 | int rc = 0; |
375 | int bytes_returned; | 397 | int bytes_returned; |
398 | int i; | ||
376 | struct TCP_Server_Info * server; | 399 | struct TCP_Server_Info * server; |
377 | u16 count; | 400 | u16 count; |
378 | 401 | ||
@@ -388,99 +411,187 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
388 | return rc; | 411 | return rc; |
389 | pSMB->hdr.Mid = GetNextMid(server); | 412 | pSMB->hdr.Mid = GetNextMid(server); |
390 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; | 413 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; |
391 | if (extended_security) | 414 | if((extended_security & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) |
392 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 415 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
393 | 416 | ||
394 | count = strlen(protocols[0].name) + 1; | 417 | count = 0; |
395 | strncpy(pSMB->DialectsArray, protocols[0].name, 30); | 418 | for(i=0;i<CIFS_NUM_PROT;i++) { |
396 | /* null guaranteed to be at end of source and target buffers anyway */ | 419 | strncpy(pSMB->DialectsArray+count, protocols[i].name, 16); |
397 | 420 | count += strlen(protocols[i].name) + 1; | |
421 | /* null at end of source and target buffers anyway */ | ||
422 | } | ||
398 | pSMB->hdr.smb_buf_length += count; | 423 | pSMB->hdr.smb_buf_length += count; |
399 | pSMB->ByteCount = cpu_to_le16(count); | 424 | pSMB->ByteCount = cpu_to_le16(count); |
400 | 425 | ||
401 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 426 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
402 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 427 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
403 | if (rc == 0) { | 428 | if (rc != 0) |
404 | server->secMode = pSMBr->SecurityMode; | 429 | goto neg_err_exit; |
405 | if((server->secMode & SECMODE_USER) == 0) | 430 | |
406 | cFYI(1,("share mode security")); | 431 | cFYI(1,("Dialect: %d", pSMBr->DialectIndex)); |
407 | server->secType = NTLM; /* BB override default for | 432 | /* Check wct = 1 error case */ |
408 | NTLMv2 or kerberos v5 */ | 433 | if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) { |
409 | /* one byte - no need to convert this or EncryptionKeyLen | 434 | /* core returns wct = 1, but we do not ask for core - otherwise |
410 | from little endian */ | 435 | small wct just comes when dialect index is -1 indicating we |
411 | server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); | 436 | could not negotiate a common dialect */ |
412 | /* probably no need to store and check maxvcs */ | 437 | rc = -EOPNOTSUPP; |
413 | server->maxBuf = | 438 | goto neg_err_exit; |
414 | min(le32_to_cpu(pSMBr->MaxBufferSize), | 439 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
440 | } else if((pSMBr->hdr.WordCount == 13) | ||
441 | && (pSMBr->DialectIndex == LANMAN_PROT)) { | ||
442 | struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; | ||
443 | |||
444 | if((extended_security & CIFSSEC_MAY_LANMAN) || | ||
445 | (extended_security & CIFSSEC_MAY_PLNTXT)) | ||
446 | server->secType = LANMAN; | ||
447 | else { | ||
448 | cERROR(1, ("mount failed weak security disabled" | ||
449 | " in /proc/fs/cifs/SecurityFlags")); | ||
450 | rc = -EOPNOTSUPP; | ||
451 | goto neg_err_exit; | ||
452 | } | ||
453 | server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode); | ||
454 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); | ||
455 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), | ||
456 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | ||
457 | GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); | ||
458 | /* even though we do not use raw we might as well set this | ||
459 | accurately, in case we ever find a need for it */ | ||
460 | if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | ||
461 | server->maxRw = 0xFF00; | ||
462 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; | ||
463 | } else { | ||
464 | server->maxRw = 0;/* we do not need to use raw anyway */ | ||
465 | server->capabilities = CAP_MPX_MODE; | ||
466 | } | ||
467 | server->timeZone = le16_to_cpu(rsp->ServerTimeZone); | ||
468 | |||
469 | /* BB get server time for time conversions and add | ||
470 | code to use it and timezone since this is not UTC */ | ||
471 | |||
472 | if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { | ||
473 | memcpy(server->cryptKey, rsp->EncryptionKey, | ||
474 | CIFS_CRYPTO_KEY_SIZE); | ||
475 | } else if (server->secMode & SECMODE_PW_ENCRYPT) { | ||
476 | rc = -EIO; /* need cryptkey unless plain text */ | ||
477 | goto neg_err_exit; | ||
478 | } | ||
479 | |||
480 | cFYI(1,("LANMAN negotiated")); | ||
481 | /* we will not end up setting signing flags - as no signing | ||
482 | was in LANMAN and server did not return the flags on */ | ||
483 | goto signing_check; | ||
484 | #else /* weak security disabled */ | ||
485 | } else if(pSMBr->hdr.WordCount == 13) { | ||
486 | cERROR(1,("mount failed, cifs module not built " | ||
487 | "with CIFS_WEAK_PW_HASH support")); | ||
488 | rc = -EOPNOTSUPP; | ||
489 | #endif /* WEAK_PW_HASH */ | ||
490 | goto neg_err_exit; | ||
491 | } else if(pSMBr->hdr.WordCount != 17) { | ||
492 | /* unknown wct */ | ||
493 | rc = -EOPNOTSUPP; | ||
494 | goto neg_err_exit; | ||
495 | } | ||
496 | /* else wct == 17 NTLM */ | ||
497 | server->secMode = pSMBr->SecurityMode; | ||
498 | if((server->secMode & SECMODE_USER) == 0) | ||
499 | cFYI(1,("share mode security")); | ||
500 | |||
501 | if((server->secMode & SECMODE_PW_ENCRYPT) == 0) | ||
502 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
503 | if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0) | ||
504 | #endif /* CIFS_WEAK_PW_HASH */ | ||
505 | cERROR(1,("Server requests plain text password" | ||
506 | " but client support disabled")); | ||
507 | |||
508 | if(extended_security & CIFSSEC_MUST_NTLMV2) | ||
509 | server->secType = NTLMv2; | ||
510 | else | ||
511 | server->secType = NTLM; | ||
512 | /* else krb5 ... */ | ||
513 | |||
514 | /* one byte, so no need to convert this or EncryptionKeyLen from | ||
515 | little endian */ | ||
516 | server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); | ||
517 | /* probably no need to store and check maxvcs */ | ||
518 | server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), | ||
415 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 519 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
416 | server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); | 520 | server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); |
417 | cFYI(0, ("Max buf = %d", ses->server->maxBuf)); | 521 | cFYI(0, ("Max buf = %d", ses->server->maxBuf)); |
418 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | 522 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); |
419 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 523 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
420 | server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); | 524 | server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); |
421 | /* BB with UTC do we ever need to be using srvr timezone? */ | 525 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { |
422 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { | 526 | memcpy(server->cryptKey, pSMBr->u.EncryptionKey, |
423 | memcpy(server->cryptKey, pSMBr->u.EncryptionKey, | 527 | CIFS_CRYPTO_KEY_SIZE); |
424 | CIFS_CRYPTO_KEY_SIZE); | 528 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) |
425 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) | 529 | && (pSMBr->EncryptionKeyLength == 0)) { |
426 | && (pSMBr->EncryptionKeyLength == 0)) { | 530 | /* decode security blob */ |
427 | /* decode security blob */ | 531 | } else if (server->secMode & SECMODE_PW_ENCRYPT) { |
428 | } else | 532 | rc = -EIO; /* no crypt key only if plain text pwd */ |
429 | rc = -EIO; | 533 | goto neg_err_exit; |
534 | } | ||
430 | 535 | ||
431 | /* BB might be helpful to save off the domain of server here */ | 536 | /* BB might be helpful to save off the domain of server here */ |
432 | 537 | ||
433 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && | 538 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && |
434 | (server->capabilities & CAP_EXTENDED_SECURITY)) { | 539 | (server->capabilities & CAP_EXTENDED_SECURITY)) { |
435 | count = pSMBr->ByteCount; | 540 | count = pSMBr->ByteCount; |
436 | if (count < 16) | 541 | if (count < 16) |
437 | rc = -EIO; | 542 | rc = -EIO; |
438 | else if (count == 16) { | 543 | else if (count == 16) { |
439 | server->secType = RawNTLMSSP; | 544 | server->secType = RawNTLMSSP; |
440 | if (server->socketUseCount.counter > 1) { | 545 | if (server->socketUseCount.counter > 1) { |
441 | if (memcmp | 546 | if (memcmp(server->server_GUID, |
442 | (server->server_GUID, | 547 | pSMBr->u.extended_response. |
443 | pSMBr->u.extended_response. | 548 | GUID, 16) != 0) { |
444 | GUID, 16) != 0) { | 549 | cFYI(1, ("server UID changed")); |
445 | cFYI(1, ("server UID changed")); | ||
446 | memcpy(server-> | ||
447 | server_GUID, | ||
448 | pSMBr->u. | ||
449 | extended_response. | ||
450 | GUID, 16); | ||
451 | } | ||
452 | } else | ||
453 | memcpy(server->server_GUID, | 550 | memcpy(server->server_GUID, |
454 | pSMBr->u.extended_response. | 551 | pSMBr->u.extended_response.GUID, |
455 | GUID, 16); | 552 | 16); |
456 | } else { | ||
457 | rc = decode_negTokenInit(pSMBr->u. | ||
458 | extended_response. | ||
459 | SecurityBlob, | ||
460 | count - 16, | ||
461 | &server->secType); | ||
462 | if(rc == 1) { | ||
463 | /* BB Need to fill struct for sessetup here */ | ||
464 | rc = -EOPNOTSUPP; | ||
465 | } else { | ||
466 | rc = -EINVAL; | ||
467 | } | 553 | } |
554 | } else | ||
555 | memcpy(server->server_GUID, | ||
556 | pSMBr->u.extended_response.GUID, 16); | ||
557 | } else { | ||
558 | rc = decode_negTokenInit(pSMBr->u.extended_response. | ||
559 | SecurityBlob, | ||
560 | count - 16, | ||
561 | &server->secType); | ||
562 | if(rc == 1) { | ||
563 | /* BB Need to fill struct for sessetup here */ | ||
564 | rc = -EOPNOTSUPP; | ||
565 | } else { | ||
566 | rc = -EINVAL; | ||
468 | } | 567 | } |
469 | } else | ||
470 | server->capabilities &= ~CAP_EXTENDED_SECURITY; | ||
471 | if(sign_CIFS_PDUs == FALSE) { | ||
472 | if(server->secMode & SECMODE_SIGN_REQUIRED) | ||
473 | cERROR(1, | ||
474 | ("Server requires /proc/fs/cifs/PacketSigningEnabled")); | ||
475 | server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
476 | } else if(sign_CIFS_PDUs == 1) { | ||
477 | if((server->secMode & SECMODE_SIGN_REQUIRED) == 0) | ||
478 | server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
479 | } | 568 | } |
480 | 569 | } else | |
570 | server->capabilities &= ~CAP_EXTENDED_SECURITY; | ||
571 | |||
572 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
573 | signing_check: | ||
574 | #endif | ||
575 | if(sign_CIFS_PDUs == FALSE) { | ||
576 | if(server->secMode & SECMODE_SIGN_REQUIRED) | ||
577 | cERROR(1,("Server requires " | ||
578 | "/proc/fs/cifs/PacketSigningEnabled to be on")); | ||
579 | server->secMode &= | ||
580 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
581 | } else if(sign_CIFS_PDUs == 1) { | ||
582 | if((server->secMode & SECMODE_SIGN_REQUIRED) == 0) | ||
583 | server->secMode &= | ||
584 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
585 | } else if(sign_CIFS_PDUs == 2) { | ||
586 | if((server->secMode & | ||
587 | (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { | ||
588 | cERROR(1,("signing required but server lacks support")); | ||
589 | } | ||
481 | } | 590 | } |
482 | 591 | neg_err_exit: | |
483 | cifs_buf_release(pSMB); | 592 | cifs_buf_release(pSMB); |
593 | |||
594 | cFYI(1,("negprot rc %d",rc)); | ||
484 | return rc; | 595 | return rc; |
485 | } | 596 | } |
486 | 597 | ||
@@ -2239,7 +2350,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
2239 | } | 2350 | } |
2240 | symlinkinfo[buflen] = 0; /* just in case so the caller | 2351 | symlinkinfo[buflen] = 0; /* just in case so the caller |
2241 | does not go off the end of the buffer */ | 2352 | does not go off the end of the buffer */ |
2242 | cFYI(1,("readlink result - %s ",symlinkinfo)); | 2353 | cFYI(1,("readlink result - %s",symlinkinfo)); |
2243 | } | 2354 | } |
2244 | } | 2355 | } |
2245 | qreparse_out: | 2356 | qreparse_out: |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bae1479318d1..01608bb4d673 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -49,8 +49,6 @@ | |||
49 | 49 | ||
50 | static DECLARE_COMPLETION(cifsd_complete); | 50 | static DECLARE_COMPLETION(cifsd_complete); |
51 | 51 | ||
52 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | ||
53 | unsigned char *p24); | ||
54 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 52 | extern 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 { |
@@ -1762,11 +1767,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1762 | if (volume_info.username) | 1767 | if (volume_info.username) |
1763 | strncpy(pSesInfo->userName, | 1768 | strncpy(pSesInfo->userName, |
1764 | volume_info.username,MAX_USERNAME_SIZE); | 1769 | volume_info.username,MAX_USERNAME_SIZE); |
1765 | if (volume_info.domainname) | 1770 | if (volume_info.domainname) { |
1766 | strncpy(pSesInfo->domainName, | 1771 | int len = strlen(volume_info.domainname); |
1767 | volume_info.domainname,MAX_USERNAME_SIZE); | 1772 | pSesInfo->domainName = |
1773 | kmalloc(len + 1, GFP_KERNEL); | ||
1774 | if(pSesInfo->domainName) | ||
1775 | strcpy(pSesInfo->domainName, | ||
1776 | volume_info.domainname); | ||
1777 | } | ||
1768 | pSesInfo->linux_uid = volume_info.linux_uid; | 1778 | pSesInfo->linux_uid = volume_info.linux_uid; |
1769 | down(&pSesInfo->sesSem); | 1779 | down(&pSesInfo->sesSem); |
1780 | /* BB FIXME need to pass vol->secFlgs BB */ | ||
1770 | rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); | 1781 | rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); |
1771 | up(&pSesInfo->sesSem); | 1782 | up(&pSesInfo->sesSem); |
1772 | if(!rc) | 1783 | if(!rc) |
@@ -1980,7 +1991,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1980 | 1991 | ||
1981 | static int | 1992 | static int |
1982 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 1993 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, |
1983 | char session_key[CIFS_SESSION_KEY_SIZE], | 1994 | char session_key[CIFS_SESS_KEY_SIZE], |
1984 | const struct nls_table *nls_codepage) | 1995 | const struct nls_table *nls_codepage) |
1985 | { | 1996 | { |
1986 | struct smb_hdr *smb_buffer; | 1997 | struct smb_hdr *smb_buffer; |
@@ -2038,15 +2049,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2038 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | 2049 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); |
2039 | 2050 | ||
2040 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | 2051 | pSMB->req_no_secext.CaseInsensitivePasswordLength = |
2041 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2052 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2042 | 2053 | ||
2043 | pSMB->req_no_secext.CaseSensitivePasswordLength = | 2054 | pSMB->req_no_secext.CaseSensitivePasswordLength = |
2044 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2055 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2045 | bcc_ptr = pByteArea(smb_buffer); | 2056 | bcc_ptr = pByteArea(smb_buffer); |
2046 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); | 2057 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); |
2047 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2058 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
2048 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); | 2059 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); |
2049 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2060 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
2050 | 2061 | ||
2051 | if (ses->capabilities & CAP_UNICODE) { | 2062 | if (ses->capabilities & CAP_UNICODE) { |
2052 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ | 2063 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ |
@@ -2054,7 +2065,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2054 | bcc_ptr++; | 2065 | bcc_ptr++; |
2055 | } | 2066 | } |
2056 | if(user == NULL) | 2067 | if(user == NULL) |
2057 | bytes_returned = 0; /* skill null user */ | 2068 | bytes_returned = 0; /* skip null user */ |
2058 | else | 2069 | else |
2059 | bytes_returned = | 2070 | bytes_returned = |
2060 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, | 2071 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, |
@@ -2274,292 +2285,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings, | |||
2274 | } | 2285 | } |
2275 | 2286 | ||
2276 | static int | 2287 | static int |
2277 | CIFSSpnegoSessSetup(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 | |||
2562 | static int | ||
2563 | CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | 2288 | CIFSNTLMSSPNegotiateSessSetup(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 | ||
@@ -2994,14 +2719,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2994 | SecurityBlob->LmChallengeResponse.Buffer = 0; | 2719 | SecurityBlob->LmChallengeResponse.Buffer = 0; |
2995 | 2720 | ||
2996 | SecurityBlob->NtChallengeResponse.Length = | 2721 | SecurityBlob->NtChallengeResponse.Length = |
2997 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2722 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2998 | SecurityBlob->NtChallengeResponse.MaximumLength = | 2723 | SecurityBlob->NtChallengeResponse.MaximumLength = |
2999 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2724 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3000 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); | 2725 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE); |
3001 | SecurityBlob->NtChallengeResponse.Buffer = | 2726 | SecurityBlob->NtChallengeResponse.Buffer = |
3002 | cpu_to_le32(SecurityBlobLength); | 2727 | cpu_to_le32(SecurityBlobLength); |
3003 | SecurityBlobLength += CIFS_SESSION_KEY_SIZE; | 2728 | SecurityBlobLength += CIFS_SESS_KEY_SIZE; |
3004 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2729 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
3005 | 2730 | ||
3006 | if (ses->capabilities & CAP_UNICODE) { | 2731 | if (ses->capabilities & CAP_UNICODE) { |
3007 | if (domain == NULL) { | 2732 | if (domain == NULL) { |
@@ -3340,22 +3065,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3340 | bcc_ptr = &pSMB->Password[0]; | 3065 | bcc_ptr = &pSMB->Password[0]; |
3341 | if((ses->server->secMode) & SECMODE_USER) { | 3066 | if((ses->server->secMode) & SECMODE_USER) { |
3342 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | 3067 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ |
3068 | *bcc_ptr = 0; /* password is null byte */ | ||
3343 | bcc_ptr++; /* skip password */ | 3069 | bcc_ptr++; /* skip password */ |
3070 | /* already aligned so no need to do it below */ | ||
3344 | } else { | 3071 | } else { |
3345 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 3072 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3346 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos | 3073 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos |
3347 | specified as required (when that support is added to | 3074 | specified as required (when that support is added to |
3348 | the vfs in the future) as only NTLM or the much | 3075 | the vfs in the future) as only NTLM or the much |
3349 | weaker LANMAN (which we do not send) is accepted | 3076 | weaker LANMAN (which we do not send by default) is accepted |
3350 | by Samba (not sure whether other servers allow | 3077 | by Samba (not sure whether other servers allow |
3351 | NTLMv2 password here) */ | 3078 | NTLMv2 password here) */ |
3079 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
3080 | if((extended_security & CIFSSEC_MAY_LANMAN) && | ||
3081 | (ses->server->secType == LANMAN)) | ||
3082 | calc_lanman_hash(ses, bcc_ptr); | ||
3083 | else | ||
3084 | #endif /* CIFS_WEAK_PW_HASH */ | ||
3352 | SMBNTencrypt(ses->password, | 3085 | SMBNTencrypt(ses->password, |
3353 | ses->server->cryptKey, | 3086 | ses->server->cryptKey, |
3354 | bcc_ptr); | 3087 | bcc_ptr); |
3355 | 3088 | ||
3356 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 3089 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
3357 | *bcc_ptr = 0; | 3090 | if(ses->capabilities & CAP_UNICODE) { |
3358 | bcc_ptr++; /* align */ | 3091 | /* must align unicode strings */ |
3092 | *bcc_ptr = 0; /* null byte password */ | ||
3093 | bcc_ptr++; | ||
3094 | } | ||
3359 | } | 3095 | } |
3360 | 3096 | ||
3361 | if(ses->server->secMode & | 3097 | if(ses->server->secMode & |
@@ -3429,7 +3165,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3429 | } | 3165 | } |
3430 | /* else do not bother copying these informational fields */ | 3166 | /* else do not bother copying these informational fields */ |
3431 | } | 3167 | } |
3432 | tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); | 3168 | if(smb_buffer_response->WordCount == 3) |
3169 | tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); | ||
3170 | else | ||
3171 | tcon->Flags = 0; | ||
3433 | cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); | 3172 | cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); |
3434 | } else if ((rc == 0) && tcon == NULL) { | 3173 | } else if ((rc == 0) && tcon == NULL) { |
3435 | /* all we need to save for IPC$ connection */ | 3174 | /* all we need to save for IPC$ connection */ |
@@ -3494,7 +3233,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3494 | struct nls_table * nls_info) | 3233 | struct nls_table * nls_info) |
3495 | { | 3234 | { |
3496 | int rc = 0; | 3235 | int rc = 0; |
3497 | char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; | 3236 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; |
3498 | int ntlmv2_flag = FALSE; | 3237 | int ntlmv2_flag = FALSE; |
3499 | int first_time = 0; | 3238 | int first_time = 0; |
3500 | 3239 | ||
@@ -3526,20 +3265,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3526 | pSesInfo->server->secMode, | 3265 | pSesInfo->server->secMode, |
3527 | pSesInfo->server->capabilities, | 3266 | pSesInfo->server->capabilities, |
3528 | pSesInfo->server->timeZone)); | 3267 | pSesInfo->server->timeZone)); |
3529 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 3268 | if(experimEnabled < 2) |
3530 | if(experimEnabled > 1) | 3269 | rc = CIFS_SessSetup(xid, pSesInfo, |
3531 | rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, | 3270 | first_time, nls_info); |
3532 | &ntlmv2_flag, nls_info); | 3271 | else if (extended_security |
3533 | else | ||
3534 | #endif | ||
3535 | if (extended_security | ||
3536 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3272 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
3537 | && (pSesInfo->server->secType == NTLMSSP)) { | 3273 | && (pSesInfo->server->secType == NTLMSSP)) { |
3538 | cFYI(1, ("New style sesssetup")); | 3274 | rc = -EOPNOTSUPP; |
3539 | rc = CIFSSpnegoSessSetup(xid, pSesInfo, | ||
3540 | NULL /* security blob */, | ||
3541 | 0 /* blob length */, | ||
3542 | nls_info); | ||
3543 | } else if (extended_security | 3275 | } else if (extended_security |
3544 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3276 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
3545 | && (pSesInfo->server->secType == RawNTLMSSP)) { | 3277 | && (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; |
114 | BB remove above eight lines BB */ | 114 | BB 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 | ||
118 | int | 118 | int |
119 | cifs_create(struct inode *inode, struct dentry *direntry, int mode, | 119 | cifs_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..616b140534be 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -201,7 +201,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
201 | } else { | 201 | } else { |
202 | if (file->f_flags & O_EXCL) | 202 | if (file->f_flags & O_EXCL) |
203 | cERROR(1, ("could not find file instance for " | 203 | cERROR(1, ("could not find file instance for " |
204 | "new file %p ", file)); | 204 | "new file %p", file)); |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
@@ -260,10 +260,15 @@ int cifs_open(struct inode *inode, struct file *file) | |||
260 | rc = -ENOMEM; | 260 | rc = -ENOMEM; |
261 | goto out; | 261 | goto out; |
262 | } | 262 | } |
263 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, | 263 | |
264 | CREATE_NOT_DIR, &netfid, &oplock, buf, | 264 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) |
265 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, | ||
266 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | ||
265 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | 267 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags |
266 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 268 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
269 | else | ||
270 | rc = -EIO; /* no NT SMB support fall into legacy open below */ | ||
271 | |||
267 | if (rc == -EIO) { | 272 | if (rc == -EIO) { |
268 | /* Old server, try legacy style OpenX */ | 273 | /* Old server, try legacy style OpenX */ |
269 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | 274 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, |
@@ -272,7 +277,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
272 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 277 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
273 | } | 278 | } |
274 | if (rc) { | 279 | if (rc) { |
275 | cFYI(1, ("cifs_open returned 0x%x ", rc)); | 280 | cFYI(1, ("cifs_open returned 0x%x", rc)); |
276 | goto out; | 281 | goto out; |
277 | } | 282 | } |
278 | file->private_data = | 283 | file->private_data = |
@@ -409,8 +414,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, | |||
409 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 414 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
410 | if (rc) { | 415 | if (rc) { |
411 | up(&pCifsFile->fh_sem); | 416 | up(&pCifsFile->fh_sem); |
412 | cFYI(1, ("cifs_open returned 0x%x ", rc)); | 417 | cFYI(1, ("cifs_open returned 0x%x", rc)); |
413 | cFYI(1, ("oplock: %d ", oplock)); | 418 | cFYI(1, ("oplock: %d", oplock)); |
414 | } else { | 419 | } else { |
415 | pCifsFile->netfid = netfid; | 420 | pCifsFile->netfid = netfid; |
416 | pCifsFile->invalidHandle = FALSE; | 421 | pCifsFile->invalidHandle = FALSE; |
@@ -531,7 +536,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
531 | (struct cifsFileInfo *)file->private_data; | 536 | (struct cifsFileInfo *)file->private_data; |
532 | char *ptmp; | 537 | char *ptmp; |
533 | 538 | ||
534 | cFYI(1, ("Closedir inode = 0x%p with ", inode)); | 539 | cFYI(1, ("Closedir inode = 0x%p", inode)); |
535 | 540 | ||
536 | xid = GetXid(); | 541 | xid = GetXid(); |
537 | 542 | ||
@@ -605,7 +610,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
605 | } | 610 | } |
606 | if (pfLock->fl_flags & FL_ACCESS) | 611 | if (pfLock->fl_flags & FL_ACCESS) |
607 | cFYI(1, ("Process suspended by mandatory locking - " | 612 | cFYI(1, ("Process suspended by mandatory locking - " |
608 | "not implemented yet ")); | 613 | "not implemented yet")); |
609 | if (pfLock->fl_flags & FL_LEASE) | 614 | if (pfLock->fl_flags & FL_LEASE) |
610 | cFYI(1, ("Lease on file - not implemented yet")); | 615 | cFYI(1, ("Lease on file - not implemented yet")); |
611 | if (pfLock->fl_flags & | 616 | if (pfLock->fl_flags & |
@@ -1375,7 +1380,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1375 | 1380 | ||
1376 | xid = GetXid(); | 1381 | xid = GetXid(); |
1377 | 1382 | ||
1378 | cFYI(1, ("Sync file - name: %s datasync: 0x%x ", | 1383 | cFYI(1, ("Sync file - name: %s datasync: 0x%x", |
1379 | dentry->d_name.name, datasync)); | 1384 | dentry->d_name.name, datasync)); |
1380 | 1385 | ||
1381 | rc = filemap_fdatawrite(inode->i_mapping); | 1386 | rc = filemap_fdatawrite(inode->i_mapping); |
@@ -1404,7 +1409,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1404 | /* fill in rpages then | 1409 | /* fill in rpages then |
1405 | result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ | 1410 | result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ |
1406 | 1411 | ||
1407 | /* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); | 1412 | /* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index)); |
1408 | 1413 | ||
1409 | #if 0 | 1414 | #if 0 |
1410 | if (rc < 0) | 1415 | if (rc < 0) |
@@ -1836,7 +1841,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
1836 | if (rc < 0) | 1841 | if (rc < 0) |
1837 | goto io_error; | 1842 | goto io_error; |
1838 | else | 1843 | else |
1839 | cFYI(1, ("Bytes read %d ",rc)); | 1844 | cFYI(1, ("Bytes read %d",rc)); |
1840 | 1845 | ||
1841 | file->f_dentry->d_inode->i_atime = | 1846 | file->f_dentry->d_inode->i_atime = |
1842 | current_fs_time(file->f_dentry->d_inode->i_sb); | 1847 | current_fs_time(file->f_dentry->d_inode->i_sb); |
@@ -1957,3 +1962,19 @@ struct address_space_operations cifs_addr_ops = { | |||
1957 | /* .sync_page = cifs_sync_page, */ | 1962 | /* .sync_page = cifs_sync_page, */ |
1958 | /* .direct_IO = */ | 1963 | /* .direct_IO = */ |
1959 | }; | 1964 | }; |
1965 | |||
1966 | /* | ||
1967 | * cifs_readpages requires the server to support a buffer large enough to | ||
1968 | * contain the header plus one complete page of data. Otherwise, we need | ||
1969 | * to leave cifs_readpages out of the address space operations. | ||
1970 | */ | ||
1971 | struct address_space_operations cifs_addr_ops_smallbuf = { | ||
1972 | .readpage = cifs_readpage, | ||
1973 | .writepage = cifs_writepage, | ||
1974 | .writepages = cifs_writepages, | ||
1975 | .prepare_write = cifs_prepare_write, | ||
1976 | .commit_write = cifs_commit_write, | ||
1977 | .set_page_dirty = __set_page_dirty_nobuffers, | ||
1978 | /* .sync_page = cifs_sync_page, */ | ||
1979 | /* .direct_IO = */ | ||
1980 | }; | ||
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 | ||
1357 | void cifs_delete_inode(struct inode *inode) | 1360 | void 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 | ||
85 | static const struct smb_to_posix_error mapping_table_ERRSRV[] = { | 85 | static 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 | ||
31 | static __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 | } | ||
68 | int | ||
69 | CIFS_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) | 36 | static 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 | ||
110 | static void fill_in_inode(struct inode *tmp_inode, | 112 | static 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) | |||
415 | ffirst_retry: | 440 | ffirst_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 | ||
454 | static char *nxt_dir_entry(char *old_entry, char *end_of_smb) | 482 | static 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 */ |
675 | static int cifs_get_name_from_search_buf(struct qstr *pqst, | 725 | static 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 | ||
743 | static int cifs_filldir(char *pfindEntry, struct file *file, | 805 | static 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..70e32a81c213 --- /dev/null +++ b/fs/cifs/sess.c | |||
@@ -0,0 +1,525 @@ | |||
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 | |||
33 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | ||
34 | unsigned char *p24); | ||
35 | |||
36 | static __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 | |||
77 | static 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 | /* align unicode strings, must be word aligned */ | ||
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 | |||
127 | static 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, 200); | ||
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 | |||
170 | static 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 | |||
252 | static 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 | |||
308 | int | ||
309 | CIFS_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 | SESSION_SETUP_ANDX *pSMB; | ||
317 | __u32 capabilities; | ||
318 | int count; | ||
319 | int resp_buf_type = 0; | ||
320 | struct kvec iov[2]; /* BB split variable length info into 2nd iovec */ | ||
321 | enum securityEnum type; | ||
322 | __u16 action; | ||
323 | int bytes_remaining; | ||
324 | |||
325 | cFYI(1,("new sess setup")); | ||
326 | if(ses == NULL) | ||
327 | return -EINVAL; | ||
328 | |||
329 | type = ses->server->secType; | ||
330 | if(type == LANMAN) { | ||
331 | #ifndef CONFIG_CIFS_WEAK_PW_HASH | ||
332 | /* LANMAN and plaintext are less secure and off by default. | ||
333 | So we make this explicitly be turned on in kconfig (in the | ||
334 | build) and turned on at runtime (changed from the default) | ||
335 | in proc/fs/cifs or via mount parm. Unfortunately this is | ||
336 | needed for old Win (e.g. Win95), some obscure NAS and OS/2 */ | ||
337 | return -EOPNOTSUPP; | ||
338 | #endif | ||
339 | wct = 10; /* lanman 2 style sessionsetup */ | ||
340 | } else if((type == NTLM) || (type == NTLMv2)) { | ||
341 | /* For NTLMv2 failures eventually may need to retry NTLM */ | ||
342 | wct = 13; /* old style NTLM sessionsetup */ | ||
343 | } else /* same size for negotiate or auth, NTLMSSP or extended security */ | ||
344 | wct = 12; | ||
345 | |||
346 | rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, | ||
347 | (void **)&smb_buf); | ||
348 | if(rc) | ||
349 | return rc; | ||
350 | |||
351 | pSMB = (SESSION_SETUP_ANDX *)smb_buf; | ||
352 | |||
353 | capabilities = cifs_ssetup_hdr(ses, pSMB); | ||
354 | bcc_ptr = pByteArea(smb_buf); | ||
355 | |||
356 | if(type == LANMAN) { | ||
357 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
358 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; | ||
359 | |||
360 | /* no capabilities flags in old lanman negotiation */ | ||
361 | |||
362 | pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; | ||
363 | /* BB calculate hash with password */ | ||
364 | /* and copy into bcc */ | ||
365 | |||
366 | calc_lanman_hash(ses, lnm_session_key); | ||
367 | |||
368 | #ifdef CONFIG_CIFS_DEBUG2 | ||
369 | cifs_dump_mem("cryptkey: ",ses->server->cryptKey, | ||
370 | CIFS_SESS_KEY_SIZE); | ||
371 | #endif | ||
372 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); | ||
373 | bcc_ptr += CIFS_SESS_KEY_SIZE; | ||
374 | |||
375 | /* can not sign if LANMAN negotiated so no need | ||
376 | to calculate signing key? but what if server | ||
377 | changed to do higher than lanman dialect and | ||
378 | we reconnected would we ever calc signing_key? */ | ||
379 | |||
380 | cERROR(1,("Negotiating LANMAN setting up strings")); | ||
381 | /* Unicode not allowed for LANMAN dialects */ | ||
382 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
383 | #endif | ||
384 | } else if (type == NTLM) { | ||
385 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; | ||
386 | |||
387 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | ||
388 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | ||
389 | cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
390 | pSMB->req_no_secext.CaseSensitivePasswordLength = | ||
391 | cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
392 | |||
393 | /* calculate session key */ | ||
394 | SMBNTencrypt(ses->password, ses->server->cryptKey, | ||
395 | ntlm_session_key); | ||
396 | |||
397 | if(first_time) /* should this be moved into common code | ||
398 | with similar ntlmv2 path? */ | ||
399 | cifs_calculate_mac_key( ses->server->mac_signing_key, | ||
400 | ntlm_session_key, ses->password); | ||
401 | /* copy session key */ | ||
402 | |||
403 | memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); | ||
404 | bcc_ptr += CIFS_SESS_KEY_SIZE; | ||
405 | memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); | ||
406 | bcc_ptr += CIFS_SESS_KEY_SIZE; | ||
407 | if(ses->capabilities & CAP_UNICODE) | ||
408 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
409 | else | ||
410 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
411 | } else if (type == NTLMv2) { | ||
412 | char * v2_sess_key = | ||
413 | kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL); | ||
414 | |||
415 | /* BB FIXME change all users of v2_sess_key to | ||
416 | struct ntlmv2_resp */ | ||
417 | |||
418 | if(v2_sess_key == NULL) { | ||
419 | cifs_small_buf_release(smb_buf); | ||
420 | return -ENOMEM; | ||
421 | } | ||
422 | |||
423 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | ||
424 | |||
425 | /* LM2 password would be here if we supported it */ | ||
426 | pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; | ||
427 | /* cpu_to_le16(LM2_SESS_KEY_SIZE); */ | ||
428 | |||
429 | pSMB->req_no_secext.CaseSensitivePasswordLength = | ||
430 | cpu_to_le16(sizeof(struct ntlmv2_resp)); | ||
431 | |||
432 | /* calculate session key */ | ||
433 | setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); | ||
434 | if(first_time) /* should this be moved into common code | ||
435 | with similar ntlmv2 path? */ | ||
436 | /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, | ||
437 | response BB FIXME, v2_sess_key); */ | ||
438 | |||
439 | /* copy session key */ | ||
440 | |||
441 | /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE); | ||
442 | bcc_ptr += LM2_SESS_KEY_SIZE; */ | ||
443 | memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp)); | ||
444 | bcc_ptr += sizeof(struct ntlmv2_resp); | ||
445 | kfree(v2_sess_key); | ||
446 | if(ses->capabilities & CAP_UNICODE) | ||
447 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
448 | else | ||
449 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
450 | } else /* NTLMSSP or SPNEGO */ { | ||
451 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
452 | capabilities |= CAP_EXTENDED_SECURITY; | ||
453 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | ||
454 | /* BB set password lengths */ | ||
455 | } | ||
456 | |||
457 | count = (long) bcc_ptr - (long) pByteArea(smb_buf); | ||
458 | smb_buf->smb_buf_length += count; | ||
459 | |||
460 | /* if we switch to small buffers, count will need to be fewer | ||
461 | than 383 (strings less than 335 bytes) */ | ||
462 | |||
463 | BCC_LE(smb_buf) = cpu_to_le16(count); | ||
464 | |||
465 | |||
466 | /* BB FIXME check for other non ntlm code paths */ | ||
467 | |||
468 | /* BB check is this too big for a small smb? */ | ||
469 | |||
470 | iov[0].iov_base = (char *)pSMB; | ||
471 | iov[0].iov_len = smb_buf->smb_buf_length + 4; | ||
472 | |||
473 | rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0); | ||
474 | /* SMB request buf freed in SendReceive2 */ | ||
475 | |||
476 | cFYI(1,("ssetup rc from sendrecv2 is %d",rc)); | ||
477 | if(rc) | ||
478 | goto ssetup_exit; | ||
479 | |||
480 | pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; | ||
481 | smb_buf = (struct smb_hdr *)iov[0].iov_base; | ||
482 | |||
483 | if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { | ||
484 | rc = -EIO; | ||
485 | cERROR(1,("bad word count %d", smb_buf->WordCount)); | ||
486 | goto ssetup_exit; | ||
487 | } | ||
488 | action = le16_to_cpu(pSMB->resp.Action); | ||
489 | if (action & GUEST_LOGIN) | ||
490 | cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ | ||
491 | ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ | ||
492 | cFYI(1, ("UID = %d ", ses->Suid)); | ||
493 | /* response can have either 3 or 4 word count - Samba sends 3 */ | ||
494 | /* and lanman response is 3 */ | ||
495 | bytes_remaining = BCC(smb_buf); | ||
496 | bcc_ptr = pByteArea(smb_buf); | ||
497 | |||
498 | if(smb_buf->WordCount == 4) { | ||
499 | __u16 blob_len; | ||
500 | blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); | ||
501 | bcc_ptr += blob_len; | ||
502 | if(blob_len > bytes_remaining) { | ||
503 | cERROR(1,("bad security blob length %d", blob_len)); | ||
504 | rc = -EINVAL; | ||
505 | goto ssetup_exit; | ||
506 | } | ||
507 | bytes_remaining -= blob_len; | ||
508 | } | ||
509 | |||
510 | /* BB check if Unicode and decode strings */ | ||
511 | if(smb_buf->Flags2 & SMBFLG2_UNICODE) | ||
512 | rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, | ||
513 | ses, nls_cp); | ||
514 | else | ||
515 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp); | ||
516 | |||
517 | ssetup_exit: | ||
518 | if(resp_buf_type == CIFS_SMALL_BUFFER) { | ||
519 | cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base)); | ||
520 | cifs_small_buf_release(iov[0].iov_base); | ||
521 | } else if(resp_buf_type == CIFS_LARGE_BUFFER) | ||
522 | cifs_buf_release(iov[0].iov_base); | ||
523 | |||
524 | return rc; | ||
525 | } | ||
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 */ |