aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-05-31 18:40:51 -0400
committerSteve French <sfrench@us.ibm.com>2006-05-31 18:40:51 -0400
commit3979877e5606ecc58c5a31bd0078c6d80ba9cbe7 (patch)
treed221455b5176ea8b26e750d6498c3ed822998ba3
parent26a21b980b1897b11fd7f9ba4bf6060c9e15df10 (diff)
[CIFS] Support for setting up SMB sessions to legacy lanman servers
-rw-r--r--fs/Kconfig40
-rw-r--r--fs/cifs/CHANGES5
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/cifs_debug.c84
-rw-r--r--fs/cifs/cifs_debug.h4
-rw-r--r--fs/cifs/cifs_unicode.c1
-rw-r--r--fs/cifs/cifsencrypt.c2
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsglob.h51
-rw-r--r--fs/cifs/cifspdu.h37
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c95
-rw-r--r--fs/cifs/connect.c39
-rw-r--r--fs/cifs/dir.c2
-rw-r--r--fs/cifs/fcntl.c4
-rw-r--r--fs/cifs/inode.c3
-rw-r--r--fs/cifs/misc.c10
-rw-r--r--fs/cifs/readdir.c16
-rw-r--r--fs/cifs/sess.c511
-rw-r--r--fs/cifs/smbencrypt.c1
20 files changed, 837 insertions, 76 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index f9b5842c8d2d..c4eaacb86071 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1663,7 +1663,7 @@ config CIFS_STATS
1663 mounted by the cifs client to be displayed in /proc/fs/cifs/Stats 1663 mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
1664 1664
1665config CIFS_STATS2 1665config CIFS_STATS2
1666 bool "CIFS extended statistics" 1666 bool "Extended statistics"
1667 depends on CIFS_STATS 1667 depends on CIFS_STATS
1668 help 1668 help
1669 Enabling this option will allow more detailed statistics on SMB 1669 Enabling this option will allow more detailed statistics on SMB
@@ -1676,6 +1676,32 @@ config CIFS_STATS2
1676 Unless you are a developer or are doing network performance analysis 1676 Unless you are a developer or are doing network performance analysis
1677 or tuning, say N. 1677 or tuning, say N.
1678 1678
1679config CIFS_WEAK_PW_HASH
1680 bool "Support legacy servers which use weaker LANMAN security"
1681 depends on CIFS
1682 help
1683 Modern CIFS servers including Samba and most Windows versions
1684 (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
1685 security mechanisms. These hash the password more securely
1686 than the mechanisms used in the older LANMAN version of the
1687 SMB protocol needed to establish sessions with old SMB servers.
1688
1689 Enabling this option allows the cifs module to mount to older
1690 LANMAN based servers such as OS/2 and Windows 95, but such
1691 mounts may be less secure than mounts using NTLM or more recent
1692 security mechanisms if you are on a public network. Unless you
1693 have a need to access old SMB servers (and are on a private
1694 network) you probably want to say N. Even if this support
1695 is enabled in the kernel build, they will not be used
1696 automatically. At runtime LANMAN mounts are disabled but
1697 can be set to required (or optional) either in
1698 /proc/fs/cifs (see fs/cifs/README for more detail) or via an
1699 option on the mount command. This support is disabled by
1700 default in order to reduce the possibility of a downgrade
1701 attack.
1702
1703 If unsure, say N.
1704
1679config CIFS_XATTR 1705config CIFS_XATTR
1680 bool "CIFS extended attributes" 1706 bool "CIFS extended attributes"
1681 depends on CIFS 1707 depends on CIFS
@@ -1704,6 +1730,16 @@ config CIFS_POSIX
1704 (such as Samba 3.10 and later) which can negotiate 1730 (such as Samba 3.10 and later) which can negotiate
1705 CIFS POSIX ACL support. If unsure, say N. 1731 CIFS POSIX ACL support. If unsure, say N.
1706 1732
1733config CIFS_DEBUG2
1734 bool "Enable additional CIFS debugging routines
1735 help
1736 Enabling this option adds a few more debugging routines
1737 to the cifs code which slightly increases the size of
1738 the cifs module and can cause additional logging of debug
1739 messages in some error paths, slowing performance. This
1740 option can be turned off unless you are debugging
1741 cifs problems. If unsure, say N.
1742
1707config CIFS_EXPERIMENTAL 1743config CIFS_EXPERIMENTAL
1708 bool "CIFS Experimental Features (EXPERIMENTAL)" 1744 bool "CIFS Experimental Features (EXPERIMENTAL)"
1709 depends on CIFS && EXPERIMENTAL 1745 depends on CIFS && EXPERIMENTAL
@@ -1719,7 +1755,7 @@ config CIFS_EXPERIMENTAL
1719 If unsure, say N. 1755 If unsure, say N.
1720 1756
1721config CIFS_UPCALL 1757config CIFS_UPCALL
1722 bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" 1758 bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
1723 depends on CIFS_EXPERIMENTAL 1759 depends on CIFS_EXPERIMENTAL
1724 select CONNECTOR 1760 select CONNECTOR
1725 help 1761 help
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 953d2f7f88b0..b878dfcff0f0 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,8 @@
1Version 1.44
2------------
3Rewritten sessionsetup support, including support for legacy SMB
4session setup needed for OS/2 and older servers such as Windows 95 and 98.
5
1Version 1.43 6Version 1.43
2------------ 7------------
3POSIX locking to servers which support CIFS POSIX Extensions 8POSIX locking to servers which support CIFS POSIX Extensions
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 58c77254a23b..a26f26ed5a17 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
3# 3#
4obj-$(CONFIG_CIFS) += cifs.o 4obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o 6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index f4124a32bef8..7f4013a8607f 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
39 char *charptr = data; 39 char *charptr = data;
40 char buf[10], line[80]; 40 char buf[10], line[80];
41 41
42 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", 42 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
43 label, length, data); 43 label, length, data);
44 for (i = 0; i < length; i += 16) { 44 for (i = 0; i < length; i += 16) {
45 line[0] = 0; 45 line[0] = 0;
@@ -57,6 +57,57 @@ cifs_dump_mem(char *label, void *data, int length)
57 } 57 }
58} 58}
59 59
60#ifdef CONFIG_CIFS_DEBUG2
61void cifs_dump_detail(struct smb_hdr * smb)
62{
63 cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
64 smb->Command, smb->Status.CifsError,
65 smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
66 cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
67}
68
69
70void cifs_dump_mids(struct TCP_Server_Info * server)
71{
72 struct list_head *tmp;
73 struct mid_q_entry * mid_entry;
74
75 if(server == NULL)
76 return;
77
78 cERROR(1,("Dump pending requests:"));
79 spin_lock(&GlobalMid_Lock);
80 list_for_each(tmp, &server->pending_mid_q) {
81 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
82 if(mid_entry) {
83 cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
84 mid_entry->midState,
85 (int)mid_entry->command,
86 mid_entry->pid,
87 mid_entry->tsk,
88 mid_entry->mid));
89#ifdef CONFIG_CIFS_STATS2
90 cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
91 mid_entry->largeBuf,
92 mid_entry->resp_buf,
93 mid_entry->when_received,
94 jiffies));
95#endif /* STATS2 */
96 cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
97 mid_entry->multiEnd));
98 if(mid_entry->resp_buf) {
99 cifs_dump_detail(mid_entry->resp_buf);
100 cifs_dump_mem("existing buf: ",
101 mid_entry->resp_buf,
102 62 /* fixme */);
103 }
104
105 }
106 }
107 spin_unlock(&GlobalMid_Lock);
108}
109#endif /* CONFIG_CIFS_DEBUG2 */
110
60#ifdef CONFIG_PROC_FS 111#ifdef CONFIG_PROC_FS
61static int 112static int
62cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, 113cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
@@ -73,7 +124,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
73 124
74 *beginBuffer = buf + offset; 125 *beginBuffer = buf + offset;
75 126
76
77 length = 127 length =
78 sprintf(buf, 128 sprintf(buf,
79 "Display Internal CIFS Data Structures for Debugging\n" 129 "Display Internal CIFS Data Structures for Debugging\n"
@@ -397,10 +447,10 @@ static read_proc_t multiuser_mount_read;
397static write_proc_t multiuser_mount_write; 447static write_proc_t multiuser_mount_write;
398static read_proc_t extended_security_read; 448static read_proc_t extended_security_read;
399static write_proc_t extended_security_write; 449static write_proc_t extended_security_write;
400static read_proc_t ntlmv2_enabled_read; 450/* static read_proc_t ntlmv2_enabled_read;
401static write_proc_t ntlmv2_enabled_write; 451static write_proc_t ntlmv2_enabled_write;
402static read_proc_t packet_signing_enabled_read; 452static read_proc_t packet_signing_enabled_read;
403static write_proc_t packet_signing_enabled_write; 453static write_proc_t packet_signing_enabled_write;*/
404static read_proc_t experimEnabled_read; 454static read_proc_t experimEnabled_read;
405static write_proc_t experimEnabled_write; 455static write_proc_t experimEnabled_write;
406static read_proc_t linuxExtensionsEnabled_read; 456static read_proc_t linuxExtensionsEnabled_read;
@@ -469,7 +519,7 @@ cifs_proc_init(void)
469 if (pde) 519 if (pde)
470 pde->write_proc = lookupFlag_write; 520 pde->write_proc = lookupFlag_write;
471 521
472 pde = 522/* pde =
473 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs, 523 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
474 ntlmv2_enabled_read, NULL); 524 ntlmv2_enabled_read, NULL);
475 if (pde) 525 if (pde)
@@ -479,7 +529,7 @@ cifs_proc_init(void)
479 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs, 529 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
480 packet_signing_enabled_read, NULL); 530 packet_signing_enabled_read, NULL);
481 if (pde) 531 if (pde)
482 pde->write_proc = packet_signing_enabled_write; 532 pde->write_proc = packet_signing_enabled_write;*/
483} 533}
484 534
485void 535void
@@ -496,9 +546,9 @@ cifs_proc_clean(void)
496#endif 546#endif
497 remove_proc_entry("MultiuserMount", proc_fs_cifs); 547 remove_proc_entry("MultiuserMount", proc_fs_cifs);
498 remove_proc_entry("OplockEnabled", proc_fs_cifs); 548 remove_proc_entry("OplockEnabled", proc_fs_cifs);
499 remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); 549/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
500 remove_proc_entry("ExtendedSecurity",proc_fs_cifs); 550 remove_proc_entry("ExtendedSecurity",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);
@@ -787,7 +837,7 @@ extended_security_read(char *page, char **start, off_t off,
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;
@@ -808,19 +858,25 @@ extended_security_write(struct file *file, const char __user *buffer,
808{ 858{
809 char c; 859 char c;
810 int rc; 860 int rc;
861 cERROR(1,("size %ld",count)); /* BB removeme BB */
862 if((count < 2) || (count > 8))
863 return -EINVAL;
811 864
812 rc = get_user(c, buffer); 865 rc = get_user(c, buffer);
866
867/* BB fixme need to parse more characters in order to handle CIFSSEC flags */
868
813 if (rc) 869 if (rc)
814 return rc; 870 return rc;
815 if (c == '0' || c == 'n' || c == 'N') 871 if (c == '0' || c == 'n' || c == 'N')
816 extended_security = 0; 872 extended_security = CIFSSEC_DEF; /* default */
817 else if (c == '1' || c == 'y' || c == 'Y') 873 else if (c == '1' || c == 'y' || c == 'Y')
818 extended_security = 1; 874 extended_security = CIFSSEC_MAX;
819 875
820 return count; 876 return count;
821} 877}
822 878
823static int 879/* static int
824ntlmv2_enabled_read(char *page, char **start, off_t off, 880ntlmv2_enabled_read(char *page, char **start, off_t off,
825 int count, int *eof, void *data) 881 int count, int *eof, void *data)
826{ 882{
@@ -855,6 +911,8 @@ ntlmv2_enabled_write(struct file *file, const char __user *buffer,
855 ntlmv2_support = 0; 911 ntlmv2_support = 0;
856 else if (c == '1' || c == 'y' || c == 'Y') 912 else if (c == '1' || c == 'y' || c == 'Y')
857 ntlmv2_support = 1; 913 ntlmv2_support = 1;
914 else if (c == '2')
915 ntlmv2_support = 2;
858 916
859 return count; 917 return count;
860} 918}
@@ -898,7 +956,7 @@ packet_signing_enabled_write(struct file *file, const char __user *buffer,
898 sign_CIFS_PDUs = 2; 956 sign_CIFS_PDUs = 2;
899 957
900 return count; 958 return count;
901} 959} */
902 960
903 961
904#endif 962#endif
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 4304d9dcfb6c..c26cd0d2c6d5 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -24,6 +24,10 @@
24#define _H_CIFS_DEBUG 24#define _H_CIFS_DEBUG
25 25
26void cifs_dump_mem(char *label, void *data, int length); 26void cifs_dump_mem(char *label, void *data, int length);
27#ifdef CONFIG_CIFS_DEBUG2
28void cifs_dump_detail(struct smb_hdr *);
29void cifs_dump_mids(struct TCP_Server_Info *);
30#endif
27extern int traceSMB; /* flag which enables the function below */ 31extern int traceSMB; /* flag which enables the function below */
28void dump_smb(struct smb_hdr *, int); 32void dump_smb(struct smb_hdr *, int);
29#define CIFS_INFO 0x01 33#define CIFS_INFO 0x01
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index d2b128255944..d2a8b2941fc2 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -22,6 +22,7 @@
22#include "cifs_unicode.h" 22#include "cifs_unicode.h"
23#include "cifs_uniupr.h" 23#include "cifs_uniupr.h"
24#include "cifspdu.h" 24#include "cifspdu.h"
25#include "cifsglob.h"
25#include "cifs_debug.h" 26#include "cifs_debug.h"
26 27
27/* 28/*
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index e7d63737e651..08781a4698b4 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -225,6 +225,8 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
225 user_name_len = strlen(ses->userName); 225 user_name_len = strlen(ses->userName);
226 if(user_name_len > MAX_USERNAME_SIZE) 226 if(user_name_len > MAX_USERNAME_SIZE)
227 return -EINVAL; 227 return -EINVAL;
228 if(ses->domainName == NULL)
229 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
228 dom_name_len = strlen(ses->domainName); 230 dom_name_len = strlen(ses->domainName);
229 if(dom_name_len > MAX_USERNAME_SIZE) 231 if(dom_name_len > MAX_USERNAME_SIZE)
230 return -EINVAL; 232 return -EINVAL;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c262d8874ce9..700570522b23 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -56,8 +56,8 @@ unsigned int experimEnabled = 0;
56unsigned int linuxExtEnabled = 1; 56unsigned int linuxExtEnabled = 1;
57unsigned int lookupCacheEnabled = 1; 57unsigned int lookupCacheEnabled = 1;
58unsigned int multiuser_mount = 0; 58unsigned int multiuser_mount = 0;
59unsigned int extended_security = 0; 59unsigned int extended_security = CIFSSEC_DEF;
60unsigned int ntlmv2_support = 0; 60/* unsigned int ntlmv2_support = 0; */
61unsigned int sign_CIFS_PDUs = 1; 61unsigned int sign_CIFS_PDUs = 1;
62extern struct task_struct * oplockThread; /* remove sparse warning */ 62extern struct task_struct * oplockThread; /* remove sparse warning */
63struct task_struct * oplockThread = NULL; 63struct task_struct * oplockThread = NULL;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 006eb33bff5f..7a042041a16a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -88,7 +88,8 @@ enum statusEnum {
88}; 88};
89 89
90enum securityEnum { 90enum securityEnum {
91 NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */ 91 LANMAN = 0, /* Legacy LANMAN auth */
92 NTLM, /* Legacy NTLM012 auth with NTLM hash */
92 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 93 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
93 RawNTLMSSP, /* NTLMSSP without SPNEGO */ 94 RawNTLMSSP, /* NTLMSSP without SPNEGO */
94 NTLMSSP, /* NTLMSSP via SPNEGO */ 95 NTLMSSP, /* NTLMSSP via SPNEGO */
@@ -179,7 +180,9 @@ struct cifsUidInfo {
179struct cifsSesInfo { 180struct cifsSesInfo {
180 struct list_head cifsSessionList; 181 struct list_head cifsSessionList;
181 struct semaphore sesSem; 182 struct semaphore sesSem;
183#if 0
182 struct cifsUidInfo *uidInfo; /* pointer to user info */ 184 struct cifsUidInfo *uidInfo; /* pointer to user info */
185#endif
183 struct TCP_Server_Info *server; /* pointer to server info */ 186 struct TCP_Server_Info *server; /* pointer to server info */
184 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 187 atomic_t inUse; /* # of mounts (tree connections) on this ses */
185 enum statusEnum status; 188 enum statusEnum status;
@@ -194,7 +197,7 @@ struct cifsSesInfo {
194 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for 197 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
195 TCP names - will ipv6 and sctp addresses fit? */ 198 TCP names - will ipv6 and sctp addresses fit? */
196 char userName[MAX_USERNAME_SIZE + 1]; 199 char userName[MAX_USERNAME_SIZE + 1];
197 char domainName[MAX_USERNAME_SIZE + 1]; 200 char * domainName;
198 char * password; 201 char * password;
199}; 202};
200/* session flags */ 203/* session flags */
@@ -391,9 +394,9 @@ struct mid_q_entry {
391 struct smb_hdr *resp_buf; /* response buffer */ 394 struct smb_hdr *resp_buf; /* response buffer */
392 int midState; /* wish this were enum but can not pass to wait_event */ 395 int midState; /* wish this were enum but can not pass to wait_event */
393 __u8 command; /* smb command code */ 396 __u8 command; /* smb command code */
394 unsigned multiPart:1; /* multiple responses to one SMB request */
395 unsigned largeBuf:1; /* if valid response, is pointer to large buf */ 397 unsigned largeBuf:1; /* if valid response, is pointer to large buf */
396 unsigned multiResp:1; /* multiple trans2 responses for one request */ 398 unsigned multiRsp:1; /* multiple trans2 responses for one request */
399 unsigned multiEnd:1; /* both received */
397}; 400};
398 401
399struct oplock_q_entry { 402struct oplock_q_entry {
@@ -430,15 +433,35 @@ struct dir_notify_req {
430#define CIFS_LARGE_BUFFER 2 433#define CIFS_LARGE_BUFFER 2
431#define CIFS_IOVEC 4 /* array of response buffers */ 434#define CIFS_IOVEC 4 /* array of response buffers */
432 435
433/* Type of session setup needed */ 436/* Security Flags: indicate type of session setup needed */
434#define CIFS_PLAINTEXT 0 437#define CIFSSEC_MAY_SIGN 0x00001
435#define CIFS_LANMAN 1 438#define CIFSSEC_MAY_NTLM 0x00002
436#define CIFS_NTLM 2 439#define CIFSSEC_MAY_NTLMV2 0x00004
437#define CIFS_NTLMSSP_NEG 3 440#define CIFSSEC_MAY_KRB5 0x00008
438#define CIFS_NTLMSSP_AUTH 4 441#ifdef CONFIG_CIFS_WEAK_PW_HASH
439#define CIFS_SPNEGO_INIT 5 442#define CIFSSEC_MAY_LANMAN 0x00010
440#define CIFS_SPNEGO_TARG 6 443#define CIFSSEC_MAY_PLNTXT 0x00020
441 444#endif /* weak passwords */
445#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
446
447#define CIFSSEC_MUST_SIGN 0x01001
448/* note that only one of the following can be set so the
449result of setting MUST flags more than once will be to
450require use of the stronger protocol */
451#define CIFSSEC_MUST_NTLM 0x02002
452#define CIFSSEC_MUST_NTLMV2 0x04004
453#define CIFSSEC_MUST_KRB5 0x08008
454#ifdef CONFIG_CIFS_WEAK_PW_HASH
455#define CIFSSEC_MUST_LANMAN 0x10010
456#define CIFSSEC_MUST_PLNTXT 0x20020
457#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
458#else
459#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
460#endif /* WEAK_PW_HASH */
461#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
462
463#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
464#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
442/* 465/*
443 ***************************************************************** 466 *****************************************************************
444 * All constants go here 467 * All constants go here
@@ -540,8 +563,8 @@ GLOBAL_EXTERN unsigned int experimEnabled;
540GLOBAL_EXTERN unsigned int lookupCacheEnabled; 563GLOBAL_EXTERN unsigned int lookupCacheEnabled;
541GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent 564GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
542 with more secure ntlmssp2 challenge/resp */ 565 with more secure ntlmssp2 challenge/resp */
543GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
544GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ 566GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
567GLOBAL_EXTERN unsigned int secFlags;
545GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ 568GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
546GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ 569GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
547GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ 570GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b2233ac05bd2..e0ff9b56cc4c 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
@@ -400,6 +406,25 @@ typedef struct negotiate_req {
400 unsigned char DialectsArray[1]; 406 unsigned char DialectsArray[1];
401} __attribute__((packed)) NEGOTIATE_REQ; 407} __attribute__((packed)) NEGOTIATE_REQ;
402 408
409/* Dialect index is 13 for LANMAN */
410
411typedef struct lanman_neg_rsp {
412 struct smb_hdr hdr; /* wct = 13 */
413 __le16 DialectIndex;
414 __le16 SecurityMode;
415 __le16 MaxBufSize;
416 __le16 MaxMpxCount;
417 __le16 MaxNumberVcs;
418 __le16 RawMode;
419 __le32 SessionKey;
420 __le32 ServerTime;
421 __le16 ServerTimeZone;
422 __le16 EncryptionKeyLength;
423 __le16 Reserved;
424 __u16 ByteCount;
425 unsigned char EncryptionKey[1];
426} __attribute__((packed)) LANMAN_NEG_RSP;
427
403typedef struct negotiate_rsp { 428typedef struct negotiate_rsp {
404 struct smb_hdr hdr; /* wct = 17 */ 429 struct smb_hdr hdr; /* wct = 17 */
405 __le16 DialectIndex; 430 __le16 DialectIndex;
@@ -520,8 +545,8 @@ typedef union smb_com_session_setup_andx {
520 __le16 MaxMpxCount; 545 __le16 MaxMpxCount;
521 __le16 VcNumber; 546 __le16 VcNumber;
522 __u32 SessionKey; 547 __u32 SessionKey;
523 __le16 PassswordLength; 548 __le16 PasswordLength;
524 __u32 Reserved; 549 __u32 Reserved; /* encrypt key len and offset */
525 __le16 ByteCount; 550 __le16 ByteCount;
526 unsigned char AccountPassword[1]; /* followed by */ 551 unsigned char AccountPassword[1]; /* followed by */
527 /* STRING AccountName */ 552 /* STRING AccountName */
@@ -1844,13 +1869,13 @@ typedef struct {
1844typedef struct { 1869typedef struct {
1845 __le32 DeviceType; 1870 __le32 DeviceType;
1846 __le32 DeviceCharacteristics; 1871 __le32 DeviceCharacteristics;
1847} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */ 1872} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
1848 1873
1849typedef struct { 1874typedef struct {
1850 __le32 Attributes; 1875 __le32 Attributes;
1851 __le32 MaxPathNameComponentLength; 1876 __le32 MaxPathNameComponentLength;
1852 __le32 FileSystemNameLen; 1877 __le32 FileSystemNameLen;
1853 char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ 1878 char FileSystemName[52]; /* do not have to save this - get subset? */
1854} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO; 1879} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
1855 1880
1856/******************************************************************************/ 1881/******************************************************************************/
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 310ea2f0e0bf..ff78cf7b0d1b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -69,7 +69,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
69 struct cifsSesInfo *ses, 69 struct cifsSesInfo *ses,
70 void ** request_buf); 70 void ** request_buf);
71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, 71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
72 const int stage, int * pNTLMv2_flg, 72 const int stage,
73 const struct nls_table *nls_cp); 73 const struct nls_table *nls_cp);
74#endif 74#endif
75extern __u16 GetNextMid(struct TCP_Server_Info *server); 75extern __u16 GetNextMid(struct TCP_Server_Info *server);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f00369277c06..da3154fa9c8a 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,19 +411,71 @@ 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)
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) {
429 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
430 /* Check wct = 1 error case */
431 if((pSMBr->hdr.WordCount < 13)
432 || (pSMBr->DialectIndex == BAD_PROT)) {
433 /* core returns wct = 1, but we do not ask for
434 core - otherwise it just comes when dialect
435 index is -1 indicating we could not negotiate
436 a common dialect */
437 rc = -EOPNOTSUPP;
438 goto neg_err_exit;
439 } else if((pSMBr->hdr.WordCount == 13) &&
440 (pSMBr->DialectIndex == LANMAN_PROT)) {
441 struct lanman_neg_rsp * rsp =
442 (struct lanman_neg_rsp *)pSMBr;
443
444
445 /* BB Mark ses struct as negotiated lanman level BB */
446 server->secType = LANMAN;
447 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
448 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
449 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
450 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
451
452 /* BB what do we do with raw mode? BB */
453 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
454 /* Do we have to set signing flags? no signing
455 was available LANMAN - default should be ok */
456
457 /* BB FIXME set default dummy capabilities since
458 they are not returned by the server in this dialect */
459
460 /* get server time for time conversions and add
461 code to use it and timezone since this is not UTC */
462
463 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
464 memcpy(server->cryptKey, rsp->EncryptionKey,
465 CIFS_CRYPTO_KEY_SIZE);
466 } else {
467 rc = -EIO;
468 goto neg_err_exit;
469 }
470
471 cFYI(1,("LANMAN negotiated")); /* BB removeme BB */
472 goto neg_err_exit;
473 } else if(pSMBr->hdr.WordCount != 17) {
474 /* unknown wct */
475 rc = -EOPNOTSUPP;
476 goto neg_err_exit;
477 }
478
404 server->secMode = pSMBr->SecurityMode; 479 server->secMode = pSMBr->SecurityMode;
405 if((server->secMode & SECMODE_USER) == 0) 480 if((server->secMode & SECMODE_USER) == 0)
406 cFYI(1,("share mode security")); 481 cFYI(1,("share mode security"));
@@ -479,7 +554,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
479 } 554 }
480 555
481 } 556 }
482 557neg_err_exit:
483 cifs_buf_release(pSMB); 558 cifs_buf_release(pSMB);
484 return rc; 559 return rc;
485} 560}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bae1479318d1..7ffb8f244f6a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -49,8 +49,6 @@
49 49
50static DECLARE_COMPLETION(cifsd_complete); 50static DECLARE_COMPLETION(cifsd_complete);
51 51
52extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24); 53 unsigned char *p24);
56 54
@@ -585,9 +583,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
585 /* merge response - fix up 1st*/ 583 /* merge response - fix up 1st*/
586 if(coalesce_t2(smb_buffer, 584 if(coalesce_t2(smb_buffer,
587 mid_entry->resp_buf)) { 585 mid_entry->resp_buf)) {
586 mid_entry->multiRsp = 1;
588 break; 587 break;
589 } else { 588 } else {
590 /* all parts received */ 589 /* all parts received */
590 mid_entry->multiEnd = 1;
591 goto multi_t2_fnd; 591 goto multi_t2_fnd;
592 } 592 }
593 } else { 593 } else {
@@ -632,9 +632,14 @@ multi_t2_fnd:
632 wake_up_process(task_to_wake); 632 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) 633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) { 634 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd!")); 635 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer, 636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr)); 637 sizeof(struct smb_hdr));
638#ifdef CONFIG_CIFS_DEBUG2
639 cifs_dump_detail(smb_buffer);
640 cifs_dump_mids(server);
641#endif /* CIFS_DEBUG2 */
642
638 } 643 }
639 } /* end while !EXITING */ 644 } /* end while !EXITING */
640 645
@@ -976,7 +981,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
976 } 981 }
977 /* BB are there cases in which a comma can be valid in 982 /* BB are there cases in which a comma can be valid in
978 a domain name and need special handling? */ 983 a domain name and need special handling? */
979 if (strnlen(value, 65) < 65) { 984 if (strnlen(value, 256) < 256) {
980 vol->domainname = value; 985 vol->domainname = value;
981 cFYI(1, ("Domain name set")); 986 cFYI(1, ("Domain name set"));
982 } else { 987 } else {
@@ -1762,9 +1767,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1762 if (volume_info.username) 1767 if (volume_info.username)
1763 strncpy(pSesInfo->userName, 1768 strncpy(pSesInfo->userName,
1764 volume_info.username,MAX_USERNAME_SIZE); 1769 volume_info.username,MAX_USERNAME_SIZE);
1765 if (volume_info.domainname) 1770 if (volume_info.domainname) {
1766 strncpy(pSesInfo->domainName, 1771 int len = strlen(volume_info.domainname);
1767 volume_info.domainname,MAX_USERNAME_SIZE); 1772 pSesInfo->domainName =
1773 kmalloc(len + 1, GFP_KERNEL);
1774 if(pSesInfo->domainName)
1775 strcpy(pSesInfo->domainName,
1776 volume_info.domainname);
1777 }
1768 pSesInfo->linux_uid = volume_info.linux_uid; 1778 pSesInfo->linux_uid = volume_info.linux_uid;
1769 down(&pSesInfo->sesSem); 1779 down(&pSesInfo->sesSem);
1770 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1780 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
@@ -2054,7 +2064,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2054 bcc_ptr++; 2064 bcc_ptr++;
2055 } 2065 }
2056 if(user == NULL) 2066 if(user == NULL)
2057 bytes_returned = 0; /* skill null user */ 2067 bytes_returned = 0; /* skip null user */
2058 else 2068 else
2059 bytes_returned = 2069 bytes_returned =
2060 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, 2070 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
@@ -2635,8 +2645,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2635 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2645 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2636 if(sign_CIFS_PDUs) 2646 if(sign_CIFS_PDUs)
2637 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2647 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2638 if(ntlmv2_support) 2648/* if(ntlmv2_support)
2639 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; 2649 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2640 /* setup pointers to domain name and workstation name */ 2650 /* setup pointers to domain name and workstation name */
2641 bcc_ptr += SecurityBlobLength; 2651 bcc_ptr += SecurityBlobLength;
2642 2652
@@ -3429,7 +3439,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3429 } 3439 }
3430 /* else do not bother copying these informational fields */ 3440 /* else do not bother copying these informational fields */
3431 } 3441 }
3432 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); 3442 if(smb_buffer_response->WordCount == 3)
3443 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3444 else
3445 tcon->Flags = 0;
3433 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); 3446 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3434 } else if ((rc == 0) && tcon == NULL) { 3447 } else if ((rc == 0) && tcon == NULL) {
3435 /* all we need to save for IPC$ connection */ 3448 /* all we need to save for IPC$ connection */
@@ -3528,8 +3541,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3528 pSesInfo->server->timeZone)); 3541 pSesInfo->server->timeZone));
3529#ifdef CONFIG_CIFS_EXPERIMENTAL 3542#ifdef CONFIG_CIFS_EXPERIMENTAL
3530 if(experimEnabled > 1) 3543 if(experimEnabled > 1)
3531 rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, 3544 rc = CIFS_SessSetup(xid, pSesInfo,
3532 &ntlmv2_flag, nls_info); 3545 first_time, nls_info);
3533 else 3546 else
3534#endif 3547#endif
3535 if (extended_security 3548 if (extended_security
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 57bdf7f734bf..e6ed64e94b7b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -113,7 +113,7 @@ cifs_bp_rename_retry:
113 full_path[namelen+2] = 0; 113 full_path[namelen+2] = 0;
114BB remove above eight lines BB */ 114BB remove above eight lines BB */
115 115
116/* Inode operations in similar order to how they appear in the Linux file fs.h */ 116/* Inode operations in similar order to how they appear in Linux file fs.h */
117 117
118int 118int
119cifs_create(struct inode *inode, struct dentry *direntry, int mode, 119cifs_create(struct inode *inode, struct dentry *direntry, int mode,
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/inode.c b/fs/cifs/inode.c
index 77a9e2f912fd..a609d2668032 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1121,7 +1121,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1121 1121
1122 xid = GetXid(); 1122 xid = GetXid();
1123 1123
1124 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x", 1124 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1125 direntry->d_name.name, attrs->ia_valid)); 1125 direntry->d_name.name, attrs->ia_valid));
1126 1126
1127 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1127 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
@@ -1157,6 +1157,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1157 when the local oplock break takes longer to flush 1157 when the local oplock break takes longer to flush
1158 writebehind data than the SMB timeout for the SetPathInfo 1158 writebehind data than the SMB timeout for the SetPathInfo
1159 request would allow */ 1159 request would allow */
1160
1160 open_file = find_writable_file(cifsInode); 1161 open_file = find_writable_file(cifsInode);
1161 if (open_file) { 1162 if (open_file) {
1162 __u16 nfid = open_file->netfid; 1163 __u16 nfid = open_file->netfid;
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/readdir.c b/fs/cifs/readdir.c
index 6b36c43d38f5..53903a27f786 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -31,8 +31,8 @@
31#include "cifs_fs_sb.h" 31#include "cifs_fs_sb.h"
32#include "cifsfs.h" 32#include "cifsfs.h"
33 33
34/* BB fixme - add debug wrappers around this function to disable it fixme BB */ 34#ifdef CONFIG_CIFS_DEBUG2
35/* static void dump_cifs_file_struct(struct file *file, char *label) 35static void dump_cifs_file_struct(struct file *file, char *label)
36{ 36{
37 struct cifsFileInfo * cf; 37 struct cifsFileInfo * cf;
38 38
@@ -53,7 +53,8 @@
53 } 53 }
54 54
55 } 55 }
56} */ 56}
57#endif /* DEBUG2 */
57 58
58/* Returns one if new inode created (which therefore needs to be hashed) */ 59/* 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 */ 60/* Might check in the future if inode number changed so we can rehash inode */
@@ -597,7 +598,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 598 . and .. for the root of a drive and for those we need
598 to start two entries earlier */ 599 to start two entries earlier */
599 600
600/* dump_cifs_file_struct(file, "In fce ");*/ 601#ifdef CONFIG_CIFS_DEBUG2
602 dump_cifs_file_struct(file, "In fce ");
603#endif
601 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 604 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
602 is_dir_changed(file)) || 605 is_dir_changed(file)) ||
603 (index_to_find < first_entry_in_buffer)) { 606 (index_to_find < first_entry_in_buffer)) {
@@ -980,9 +983,10 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
980 rc = cifs_filldir(current_entry, file, 983 rc = cifs_filldir(current_entry, file,
981 filldir, direntry,tmp_buf); 984 filldir, direntry,tmp_buf);
982 file->f_pos++; 985 file->f_pos++;
983 if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) { 986 if(file->f_pos ==
987 cifsFile->srch_inf.index_of_last_entry) {
984 cFYI(1,("last entry in buf at pos %lld %s", 988 cFYI(1,("last entry in buf at pos %lld %s",
985 file->f_pos,tmp_buf)); /* BB removeme BB */ 989 file->f_pos,tmp_buf));
986 cifs_save_resume_key(current_entry,cifsFile); 990 cifs_save_resume_key(current_entry,cifsFile);
987 break; 991 break;
988 } else 992 } else
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
new file mode 100644
index 000000000000..34998416eb73
--- /dev/null
+++ b/fs/cifs/sess.c
@@ -0,0 +1,511 @@
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/ctype.h>
32
33extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
34 unsigned char *p24);
35
36extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
37 unsigned char *p24);
38
39#ifdef CONFIG_CIFS_EXPERIMENTAL
40
41static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
42{
43 __u32 capabilities = 0;
44
45 /* init fields common to all four types of SessSetup */
46 /* note that header is initialized to zero in header_assemble */
47 pSMB->req.AndXCommand = 0xFF;
48 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
49 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
50
51 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
52
53 /* BB verify whether signing required on neg or just on auth frame
54 (and NTLM case) */
55
56 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
57 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
58
59 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
60 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
61
62 if (ses->capabilities & CAP_UNICODE) {
63 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
64 capabilities |= CAP_UNICODE;
65 }
66 if (ses->capabilities & CAP_STATUS32) {
67 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
68 capabilities |= CAP_STATUS32;
69 }
70 if (ses->capabilities & CAP_DFS) {
71 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
72 capabilities |= CAP_DFS;
73 }
74 if (ses->capabilities & CAP_UNIX) {
75 capabilities |= CAP_UNIX;
76 }
77
78 /* BB check whether to init vcnum BB */
79 return capabilities;
80}
81
82void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
83 const struct nls_table * nls_cp)
84{
85 char * bcc_ptr = *pbcc_area;
86 int bytes_ret = 0;
87
88 /* BB FIXME add check that strings total less
89 than 335 or will need to send them as arrays */
90
91 /* align unicode strings, must be word aligned */
92 if ((long) bcc_ptr % 2) {
93 *bcc_ptr = 0;
94 bcc_ptr++;
95 }
96 /* copy user */
97 if(ses->userName == NULL) {
98 /* BB what about null user mounts - check that we do this BB */
99 } else { /* 300 should be long enough for any conceivable user name */
100 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
101 300, nls_cp);
102 }
103 bcc_ptr += 2 * bytes_ret;
104 bcc_ptr += 2; /* account for null termination */
105 /* copy domain */
106 if(ses->domainName == NULL)
107 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
108 "CIFS_LINUX_DOM", 32, nls_cp);
109 else
110 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
111 256, nls_cp);
112 bcc_ptr += 2 * bytes_ret;
113 bcc_ptr += 2; /* account for null terminator */
114
115 /* Copy OS version */
116 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
117 nls_cp);
118 bcc_ptr += 2 * bytes_ret;
119 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
120 32, nls_cp);
121 bcc_ptr += 2 * bytes_ret;
122 bcc_ptr += 2; /* trailing null */
123
124 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
125 32, nls_cp);
126 bcc_ptr += 2 * bytes_ret;
127 bcc_ptr += 2; /* trailing null */
128
129 *pbcc_area = bcc_ptr;
130}
131
132void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
133 const struct nls_table * nls_cp)
134{
135 char * bcc_ptr = *pbcc_area;
136
137 /* copy user */
138 /* BB what about null user mounts - check that we do this BB */
139 /* copy user */
140 if(ses->userName == NULL) {
141 /* BB what about null user mounts - check that we do this BB */
142 } else { /* 300 should be long enough for any conceivable user name */
143 strncpy(bcc_ptr, ses->userName, 300);
144 }
145 /* BB improve check for overflow */
146 bcc_ptr += strnlen(ses->userName, 200);
147 *bcc_ptr = 0;
148 bcc_ptr++; /* account for null termination */
149
150 /* copy domain */
151
152 if(ses->domainName == NULL) {
153 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
154 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
155 } else {
156 strncpy(bcc_ptr, ses->domainName, 256);
157 bcc_ptr += strnlen(ses->domainName, 256);
158 }
159 *bcc_ptr = 0;
160 bcc_ptr++;
161
162 /* BB check for overflow here */
163
164 strcpy(bcc_ptr, "Linux version ");
165 bcc_ptr += strlen("Linux version ");
166 strcpy(bcc_ptr, system_utsname.release);
167 bcc_ptr += strlen(system_utsname.release) + 1;
168
169 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
170 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
171
172 *pbcc_area = bcc_ptr;
173}
174
175int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
176 const struct nls_table * nls_cp)
177{
178 int rc = 0;
179 int words_left, len;
180 char * data = *pbcc_area;
181
182
183
184 cFYI(1,("bleft %d",bleft));
185
186
187 /* word align, if bytes remaining is not even */
188 if(bleft % 2) {
189 bleft--;
190 data++;
191 }
192 words_left = bleft / 2;
193
194 /* save off server operating system */
195 len = UniStrnlen((wchar_t *) data, words_left);
196
197/* We look for obvious messed up bcc or strings in response so we do not go off
198 the end since (at least) WIN2K and Windows XP have a major bug in not null
199 terminating last Unicode string in response */
200 if(len >= words_left)
201 return rc;
202
203 if(ses->serverOS)
204 kfree(ses->serverOS);
205 /* UTF-8 string will not grow more than four times as big as UCS-16 */
206 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
207 if(ses->serverOS != NULL) {
208 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
209 nls_cp);
210 }
211 data += 2 * (len + 1);
212 words_left -= len + 1;
213
214 /* save off server network operating system */
215 len = UniStrnlen((wchar_t *) data, words_left);
216
217 if(len >= words_left)
218 return rc;
219
220 if(ses->serverNOS)
221 kfree(ses->serverNOS);
222 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
223 if(ses->serverNOS != NULL) {
224 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
225 nls_cp);
226 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
227 cFYI(1,("NT4 server"));
228 ses->flags |= CIFS_SES_NT4;
229 }
230 }
231 data += 2 * (len + 1);
232 words_left -= len + 1;
233
234 /* save off server domain */
235 len = UniStrnlen((wchar_t *) data, words_left);
236
237 if(len > words_left)
238 return rc;
239
240 if(ses->serverDomain)
241 kfree(ses->serverDomain);
242 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
243 if(ses->serverDomain != NULL) {
244 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
245 nls_cp);
246 ses->serverDomain[2*len] = 0;
247 ses->serverDomain[(2*len) + 1] = 0;
248 }
249 data += 2 * (len + 1);
250 words_left -= len + 1;
251
252 cFYI(1,("words left: %d",words_left));
253
254 return rc;
255}
256
257int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
258 const struct nls_table * nls_cp)
259{
260 int rc = 0;
261 int len;
262 char * bcc_ptr = *pbcc_area;
263
264 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
265
266 len = strnlen(bcc_ptr, bleft);
267 if(len >= bleft)
268 return rc;
269
270 if(ses->serverOS)
271 kfree(ses->serverOS);
272
273 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
274 if(ses->serverOS)
275 strncpy(ses->serverOS, bcc_ptr, len);
276
277 bcc_ptr += len + 1;
278 bleft -= len + 1;
279
280 len = strnlen(bcc_ptr, bleft);
281 if(len >= bleft)
282 return rc;
283
284 if(ses->serverNOS)
285 kfree(ses->serverNOS);
286
287 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
288 if(ses->serverNOS)
289 strncpy(ses->serverNOS, bcc_ptr, len);
290
291 bcc_ptr += len + 1;
292 bleft -= len + 1;
293
294 len = strnlen(bcc_ptr, bleft);
295 if(len > bleft)
296 return rc;
297
298 if(ses->serverDomain)
299 kfree(ses->serverDomain);
300
301 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
302 if(ses->serverOS)
303 strncpy(ses->serverOS, bcc_ptr, len);
304
305 bcc_ptr += len + 1;
306 bleft -= len + 1;
307
308 cFYI(1,("ascii: bytes left %d",bleft));
309
310 return rc;
311}
312
313int
314CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
315 const struct nls_table *nls_cp)
316{
317 int rc = 0;
318 int wct;
319 int i;
320 struct smb_hdr *smb_buf;
321 char *bcc_ptr;
322 SESSION_SETUP_ANDX *pSMB;
323 __u32 capabilities;
324 int count;
325 int resp_buf_type = 0;
326 struct kvec iov[1];
327 enum securityEnum type;
328 __u16 action;
329 int bytes_remaining;
330
331 if(ses == NULL)
332 return -EINVAL;
333
334 type = ses->server->secType;
335 if(type == LANMAN) {
336#ifndef CONFIG_CIFS_WEAK_PW_HASH
337 /* LANMAN and plaintext are less secure and off by default.
338 So we make this explicitly be turned on in kconfig (in the
339 build) and turned on at runtime (changed from the default)
340 in proc/fs/cifs or via mount parm. Unfortunately this is
341 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
342 return -EOPNOTSUPP;
343#endif
344 wct = 10; /* lanman 2 style sessionsetup */
345 } else if(type == NTLM) /* NTLMv2 may retry NTLM */
346 wct = 13; /* old style NTLM sessionsetup */
347 else /* same size for negotiate or auth, NTLMSSP or extended security */
348 wct = 12;
349
350 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
351 (void **)&smb_buf);
352 if(rc)
353 return rc;
354
355 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
356
357 capabilities = cifs_ssetup_hdr(ses, pSMB);
358 bcc_ptr = pByteArea(smb_buf);
359
360 if(type == LANMAN) {
361#ifdef CONFIG_CIFS_WEAK_PW_HASH
362 char lnm_session_key[CIFS_SESSION_KEY_SIZE];
363 char password_with_pad[CIFS_ENCPWD_SIZE];
364
365 /* no capabilities flags in old lanman negotiation */
366
367 pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE;
368 /* BB calculate hash with password */
369 /* and copy into bcc */
370
371 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
372 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
373
374 /* calculate old style session key */
375 /* toupper may be less broken then repeatedly calling
376 nls_toupper would be, but neither handles multibyte code pages
377 but the only alternative would be converting to UCS-16 (Unicode)
378 uppercasing and converting back which is only worth doing if
379 we knew it were utf8. utf8 code page needs its own
380 toupper and tolower and strnicmp functions */
381
382 for(i = 0; i< CIFS_ENCPWD_SIZE; i++) {
383 password_with_pad[i] = toupper(password_with_pad[i]);
384 }
385
386 SMBencrypt(password_with_pad, ses->server->cryptKey,
387 lnm_session_key);
388
389#ifdef CONFIG_CIFS_DEBUG2
390 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
391 CIFS_SESSION_KEY_SIZE);
392#endif
393 /* clear password before we return/free memory */
394 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
395 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESSION_KEY_SIZE);
396 bcc_ptr += CIFS_SESSION_KEY_SIZE;
397
398 /* can not sign if LANMAN negotiated so no need
399 to calculate signing key? but what if server
400 changed to do higher than lanman dialect and
401 we reconnected would we ever calc signing_key? */
402
403 cERROR(1,("Negotiating LANMAN setting up strings"));
404 /* Unicode not allowed for LANMAN dialects */
405 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
406#endif
407 } else if (type == NTLM) {
408 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
409
410 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
411 pSMB->req_no_secext.CaseInsensitivePasswordLength =
412 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
413 pSMB->req_no_secext.CaseSensitivePasswordLength =
414 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
415
416 /* calculate session key */
417 SMBNTencrypt(ses->password, ses->server->cryptKey,
418 ntlm_session_key);
419
420 if(first_time) /* should this be moved into common code
421 with similar ntlmv2 path? */
422 cifs_calculate_mac_key(
423 ses->server->mac_signing_key,
424 ntlm_session_key, ses->password);
425 /* copy session key */
426
427 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
428 bcc_ptr += CIFS_SESSION_KEY_SIZE;
429 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
430 bcc_ptr += CIFS_SESSION_KEY_SIZE;
431 if(ses->capabilities & CAP_UNICODE)
432 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
433 else
434 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
435 } else /* NTLMSSP or SPNEGO */ {
436 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
437 capabilities |= CAP_EXTENDED_SECURITY;
438 pSMB->req.Capabilities = cpu_to_le32(capabilities);
439 /* BB set password lengths */
440 }
441
442 count = (long) bcc_ptr - (long) pByteArea(smb_buf);
443 smb_buf->smb_buf_length += count;
444
445 /* if we switch to small buffers, count will need to be fewer
446 than 383 (strings less than 335 bytes) */
447
448 BCC_LE(smb_buf) = cpu_to_le16(count);
449
450
451 /* BB FIXME check for other non ntlm code paths */
452
453 /* BB check is this too big for a small smb? */
454
455 iov[0].iov_base = (char *)pSMB;
456 iov[0].iov_len = smb_buf->smb_buf_length + 4;
457
458 rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
459 /* SMB request buf freed in SendReceive2 */
460
461 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
462 if(rc)
463 goto ssetup_exit;
464
465 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
466 smb_buf = (struct smb_hdr *)iov[0].iov_base;
467
468 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
469 rc = -EIO;
470 cERROR(1,("bad word count %d", smb_buf->WordCount));
471 goto ssetup_exit;
472 }
473 action = le16_to_cpu(pSMB->resp.Action);
474 if (action & GUEST_LOGIN)
475 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
476 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
477 cFYI(1, ("UID = %d ", ses->Suid));
478 /* response can have either 3 or 4 word count - Samba sends 3 */
479 /* and lanman response is 3 */
480 bytes_remaining = BCC(smb_buf);
481 bcc_ptr = pByteArea(smb_buf);
482
483 if(smb_buf->WordCount == 4) {
484 __u16 blob_len;
485 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
486 bcc_ptr += blob_len;
487 if(blob_len > bytes_remaining) {
488 cERROR(1,("bad security blob length %d", blob_len));
489 rc = -EINVAL;
490 goto ssetup_exit;
491 }
492 bytes_remaining -= blob_len;
493 }
494
495 /* BB check if Unicode and decode strings */
496 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
497 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
498 ses, nls_cp);
499 else
500 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
501
502ssetup_exit:
503 if(resp_buf_type == CIFS_SMALL_BUFFER) {
504 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
505 cifs_small_buf_release(iov[0].iov_base);
506 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
507 cifs_buf_release(iov[0].iov_base);
508
509 return rc;
510}
511#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 6103bcdfb16d..f518c5e45035 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -30,6 +30,7 @@
30#include <linux/random.h> 30#include <linux/random.h>
31#include "cifs_unicode.h" 31#include "cifs_unicode.h"
32#include "cifspdu.h" 32#include "cifspdu.h"
33#include "cifsglob.h"
33#include "md5.h" 34#include "md5.h"
34#include "cifs_debug.h" 35#include "cifs_debug.h"
35#include "cifsencrypt.h" 36#include "cifsencrypt.h"