summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsfs.c8
-rw-r--r--fs/cifs/cifsglob.h9
-rw-r--r--fs/cifs/cifspdu.h3
-rw-r--r--fs/cifs/cifssmb.c8
-rw-r--r--fs/cifs/connect.c1
-rw-r--r--fs/cifs/sess.c23
6 files changed, 32 insertions, 20 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ca53720fa5b..d6d226addde 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -199,10 +199,12 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
/* Only need to call the old QFSInfo if failed
on newer one */
if(rc)
- rc = CIFSSMBQFSInfo(xid, pTcon, buf);
+ if((pTcon->ses->flags & CIFS_SES_LANMAN) == 0)
+ rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
- /* Old Windows servers do not support level 103, retry with level
- one if old server failed the previous call */
+ /* Some old Windows servers also do not support level 103, retry with
+ older level one if old server failed the previous call or we
+ bypassed it because we detected that this was an older LANMAN sess */
if(rc)
rc = SMBOldQFSInfo(xid, pTcon, buf);
/*
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 98eb5446e8c..597afdf4c69 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -203,9 +203,14 @@ struct cifsSesInfo {
char * domainName;
char * password;
};
-/* session flags */
+/* no more than one of the following three session flags may be set */
#define CIFS_SES_NT4 1
-
+#define CIFS_SES_OS2 2
+#define CIFS_SES_W9X 4
+/* following flag is set for old servers such as OS2 (and Win95?)
+ which do not negotiate NTLM or POSIX dialects, but instead
+ negotiate one of the older LANMAN dialects */
+#define CIFS_SES_LANMAN 8
/*
* there is one of these for each connection to a resource on a particular
* session
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index e5dd8708d63..50505422dbb 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -26,7 +26,8 @@
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define LANMAN_PROT 0
-#define CIFS_PROT 1
+#define LANMAN2_PROT 1
+#define CIFS_PROT 2
#else
#define CIFS_PROT 0
#endif
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6e004587fa4..f2fa05bbcb4 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -46,6 +46,7 @@ static struct {
} protocols[] = {
#ifdef CONFIG_CIFS_WEAK_PW_HASH
{LANMAN_PROT, "\2LM1.2X002"},
+ {LANMAN2_PROT, "\2LANMAN2.1"},
#endif /* weak password hashing for legacy clients */
{CIFS_PROT, "\2NT LM 0.12"},
{POSIX_PROT, "\2POSIX 2"},
@@ -67,13 +68,13 @@ static struct {
/* define the number of elements in the cifs dialect array */
#ifdef CONFIG_CIFS_POSIX
#ifdef CONFIG_CIFS_WEAK_PW_HASH
-#define CIFS_NUM_PROT 3
+#define CIFS_NUM_PROT 4
#else
#define CIFS_NUM_PROT 2
#endif /* CIFS_WEAK_PW_HASH */
#else /* not posix */
#ifdef CONFIG_CIFS_WEAK_PW_HASH
-#define CIFS_NUM_PROT 2
+#define CIFS_NUM_PROT 3
#else
#define CIFS_NUM_PROT 1
#endif /* CONFIG_CIFS_WEAK_PW_HASH */
@@ -446,7 +447,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
goto neg_err_exit;
#ifdef CONFIG_CIFS_WEAK_PW_HASH
} else if((pSMBr->hdr.WordCount == 13)
- && (pSMBr->DialectIndex == LANMAN_PROT)) {
+ && ((pSMBr->DialectIndex == LANMAN_PROT)
+ || (pSMBr->DialectIndex == LANMAN2_PROT))) {
int tmp, adjust;
struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 083b2b2c157..c96f3edf1b9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3316,6 +3316,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
first_time = 1;
}
if (!rc) {
+ pSesInfo->flags = 0;
pSesInfo->capabilities = pSesInfo->server->capabilities;
if(linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index d1705ab8136..e4c4e466e32 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -268,6 +268,10 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
if(ses->serverOS)
strncpy(ses->serverOS, bcc_ptr, len);
+ if(strncmp(ses->serverOS, "OS/2",4) == 0) {
+ cFYI(1,("OS/2 server"));
+ ses->flags |= CIFS_SES_OS2;
+ }
bcc_ptr += len + 1;
bleft -= len + 1;
@@ -290,16 +294,11 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
if(len > bleft)
return rc;
- if(ses->serverDomain)
- kfree(ses->serverDomain);
-
- ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
- if(ses->serverOS)
- strncpy(ses->serverOS, bcc_ptr, len);
-
- bcc_ptr += len + 1;
- bleft -= len + 1;
-
+ /* No domain field in LANMAN case. Domain is
+ returned by old servers in the SMB negprot response */
+ /* BB For newer servers which do not support Unicode,
+ but thus do return domain here we could add parsing
+ for it later, but it is not very important */
cFYI(1,("ascii: bytes left %d",bleft));
return rc;
@@ -366,6 +365,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
str_area = kmalloc(2000, GFP_KERNEL);
bcc_ptr = str_area;
+ ses->flags &= ~CIFS_SES_LANMAN;
+
if(type == LANMAN) {
#ifdef CONFIG_CIFS_WEAK_PW_HASH
char lnm_session_key[CIFS_SESS_KEY_SIZE];
@@ -377,7 +378,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
/* and copy into bcc */
calc_lanman_hash(ses, lnm_session_key);
-
+ ses->flags |= CIFS_SES_LANMAN;
/* #ifdef CONFIG_CIFS_DEBUG2
cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
CIFS_SESS_KEY_SIZE);