aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c273
1 files changed, 192 insertions, 81 deletions
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
573signing_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 591neg_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 }
2245qreparse_out: 2356qreparse_out: