diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 95 |
1 files changed, 85 insertions, 10 deletions
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 | 557 | neg_err_exit: | |
483 | cifs_buf_release(pSMB); | 558 | cifs_buf_release(pSMB); |
484 | return rc; | 559 | return rc; |
485 | } | 560 | } |