aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-09-30 00:13:17 -0400
committerSteve French <sfrench@us.ibm.com>2006-09-30 00:13:17 -0400
commit9ac00b7d96045fa3ce573e0ad5cdc0350ad8e1d2 (patch)
tree80ee9890d64f6c4b899144df8ee0c6cd9361aafb
parentf46d3e11903e452924ef2996aa9aca2aae4427e2 (diff)
[CIFS] Do not send newer QFSInfo to legacy servers which can not support it
Fix dialect negotiation to save off when we have negotiated lanman. This allows us to avoid sending some somewhat newer requests that the server can not handle and go directly to the older version (infolevel) of the same call. Make sure we try to negotiate a level which allows us to get the server OS (which we check so we can detect Win9x vs. other legacy servers and eventually work around the Win9x DOS time bug (they reverse date/time fields). Signed-off-by: Steve French <sfrench@us.ibm.com>
-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 ca53720fa5b1..d6d226addde2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -199,10 +199,12 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
199 /* Only need to call the old QFSInfo if failed 199 /* Only need to call the old QFSInfo if failed
200 on newer one */ 200 on newer one */
201 if(rc) 201 if(rc)
202 rc = CIFSSMBQFSInfo(xid, pTcon, buf); 202 if((pTcon->ses->flags & CIFS_SES_LANMAN) == 0)
203 rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
203 204
204 /* Old Windows servers do not support level 103, retry with level 205 /* Some old Windows servers also do not support level 103, retry with
205 one if old server failed the previous call */ 206 older level one if old server failed the previous call or we
207 bypassed it because we detected that this was an older LANMAN sess */
206 if(rc) 208 if(rc)
207 rc = SMBOldQFSInfo(xid, pTcon, buf); 209 rc = SMBOldQFSInfo(xid, pTcon, buf);
208 /* 210 /*
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 98eb5446e8c1..597afdf4c69c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -203,9 +203,14 @@ struct cifsSesInfo {
203 char * domainName; 203 char * domainName;
204 char * password; 204 char * password;
205}; 205};
206/* session flags */ 206/* no more than one of the following three session flags may be set */
207#define CIFS_SES_NT4 1 207#define CIFS_SES_NT4 1
208 208#define CIFS_SES_OS2 2
209#define CIFS_SES_W9X 4
210/* following flag is set for old servers such as OS2 (and Win95?)
211 which do not negotiate NTLM or POSIX dialects, but instead
212 negotiate one of the older LANMAN dialects */
213#define CIFS_SES_LANMAN 8
209/* 214/*
210 * there is one of these for each connection to a resource on a particular 215 * there is one of these for each connection to a resource on a particular
211 * session 216 * session
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index e5dd8708d636..50505422dbb4 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -26,7 +26,8 @@
26 26
27#ifdef CONFIG_CIFS_WEAK_PW_HASH 27#ifdef CONFIG_CIFS_WEAK_PW_HASH
28#define LANMAN_PROT 0 28#define LANMAN_PROT 0
29#define CIFS_PROT 1 29#define LANMAN2_PROT 1
30#define CIFS_PROT 2
30#else 31#else
31#define CIFS_PROT 0 32#define CIFS_PROT 0
32#endif 33#endif
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6e004587fa48..f2fa05bbcb47 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -46,6 +46,7 @@ static struct {
46} protocols[] = { 46} protocols[] = {
47#ifdef CONFIG_CIFS_WEAK_PW_HASH 47#ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"}, 48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
49#endif /* weak password hashing for legacy clients */ 50#endif /* weak password hashing for legacy clients */
50 {CIFS_PROT, "\2NT LM 0.12"}, 51 {CIFS_PROT, "\2NT LM 0.12"},
51 {POSIX_PROT, "\2POSIX 2"}, 52 {POSIX_PROT, "\2POSIX 2"},
@@ -67,13 +68,13 @@ static struct {
67/* define the number of elements in the cifs dialect array */ 68/* define the number of elements in the cifs dialect array */
68#ifdef CONFIG_CIFS_POSIX 69#ifdef CONFIG_CIFS_POSIX
69#ifdef CONFIG_CIFS_WEAK_PW_HASH 70#ifdef CONFIG_CIFS_WEAK_PW_HASH
70#define CIFS_NUM_PROT 3 71#define CIFS_NUM_PROT 4
71#else 72#else
72#define CIFS_NUM_PROT 2 73#define CIFS_NUM_PROT 2
73#endif /* CIFS_WEAK_PW_HASH */ 74#endif /* CIFS_WEAK_PW_HASH */
74#else /* not posix */ 75#else /* not posix */
75#ifdef CONFIG_CIFS_WEAK_PW_HASH 76#ifdef CONFIG_CIFS_WEAK_PW_HASH
76#define CIFS_NUM_PROT 2 77#define CIFS_NUM_PROT 3
77#else 78#else
78#define CIFS_NUM_PROT 1 79#define CIFS_NUM_PROT 1
79#endif /* CONFIG_CIFS_WEAK_PW_HASH */ 80#endif /* CONFIG_CIFS_WEAK_PW_HASH */
@@ -446,7 +447,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
446 goto neg_err_exit; 447 goto neg_err_exit;
447#ifdef CONFIG_CIFS_WEAK_PW_HASH 448#ifdef CONFIG_CIFS_WEAK_PW_HASH
448 } else if((pSMBr->hdr.WordCount == 13) 449 } else if((pSMBr->hdr.WordCount == 13)
449 && (pSMBr->DialectIndex == LANMAN_PROT)) { 450 && ((pSMBr->DialectIndex == LANMAN_PROT)
451 || (pSMBr->DialectIndex == LANMAN2_PROT))) {
450 int tmp, adjust; 452 int tmp, adjust;
451 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; 453 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
452 454
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 083b2b2c1571..c96f3edf1b9c 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,
3316 first_time = 1; 3316 first_time = 1;
3317 } 3317 }
3318 if (!rc) { 3318 if (!rc) {
3319 pSesInfo->flags = 0;
3319 pSesInfo->capabilities = pSesInfo->server->capabilities; 3320 pSesInfo->capabilities = pSesInfo->server->capabilities;
3320 if(linuxExtEnabled == 0) 3321 if(linuxExtEnabled == 0)
3321 pSesInfo->capabilities &= (~CAP_UNIX); 3322 pSesInfo->capabilities &= (~CAP_UNIX);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index d1705ab8136e..e4c4e466e320 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
268 ses->serverOS = kzalloc(len + 1, GFP_KERNEL); 268 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
269 if(ses->serverOS) 269 if(ses->serverOS)
270 strncpy(ses->serverOS, bcc_ptr, len); 270 strncpy(ses->serverOS, bcc_ptr, len);
271 if(strncmp(ses->serverOS, "OS/2",4) == 0) {
272 cFYI(1,("OS/2 server"));
273 ses->flags |= CIFS_SES_OS2;
274 }
271 275
272 bcc_ptr += len + 1; 276 bcc_ptr += len + 1;
273 bleft -= len + 1; 277 bleft -= len + 1;
@@ -290,16 +294,11 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
290 if(len > bleft) 294 if(len > bleft)
291 return rc; 295 return rc;
292 296
293 if(ses->serverDomain) 297 /* No domain field in LANMAN case. Domain is
294 kfree(ses->serverDomain); 298 returned by old servers in the SMB negprot response */
295 299 /* BB For newer servers which do not support Unicode,
296 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); 300 but thus do return domain here we could add parsing
297 if(ses->serverOS) 301 for it later, but it is not very important */
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)); 302 cFYI(1,("ascii: bytes left %d",bleft));
304 303
305 return rc; 304 return rc;
@@ -366,6 +365,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
366 str_area = kmalloc(2000, GFP_KERNEL); 365 str_area = kmalloc(2000, GFP_KERNEL);
367 bcc_ptr = str_area; 366 bcc_ptr = str_area;
368 367
368 ses->flags &= ~CIFS_SES_LANMAN;
369
369 if(type == LANMAN) { 370 if(type == LANMAN) {
370#ifdef CONFIG_CIFS_WEAK_PW_HASH 371#ifdef CONFIG_CIFS_WEAK_PW_HASH
371 char lnm_session_key[CIFS_SESS_KEY_SIZE]; 372 char lnm_session_key[CIFS_SESS_KEY_SIZE];
@@ -377,7 +378,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
377 /* and copy into bcc */ 378 /* and copy into bcc */
378 379
379 calc_lanman_hash(ses, lnm_session_key); 380 calc_lanman_hash(ses, lnm_session_key);
380 381 ses->flags |= CIFS_SES_LANMAN;
381/* #ifdef CONFIG_CIFS_DEBUG2 382/* #ifdef CONFIG_CIFS_DEBUG2
382 cifs_dump_mem("cryptkey: ",ses->server->cryptKey, 383 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
383 CIFS_SESS_KEY_SIZE); 384 CIFS_SESS_KEY_SIZE);