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.c279
1 files changed, 144 insertions, 135 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 77cca3809467..0442c3b36799 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -411,8 +411,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
411 return rc; 411 return rc;
412 pSMB->hdr.Mid = GetNextMid(server); 412 pSMB->hdr.Mid = GetNextMid(server);
413 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 413 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
414/* if (extended_security) 414 if((extended_security & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
415 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;*/ 415 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
416 416
417 count = 0; 417 count = 0;
418 for(i=0;i<CIFS_NUM_PROT;i++) { 418 for(i=0;i<CIFS_NUM_PROT;i++) {
@@ -425,162 +425,171 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
425 425
426 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, 426 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
427 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 427 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
428 if (rc == 0) { 428 if (rc != 0)
429 cFYI(1,("Dialect: %d", pSMBr->DialectIndex)); 429 goto neg_err_exit;
430 /* Check wct = 1 error case */ 430
431 if((pSMBr->hdr.WordCount < 13) 431 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
432 || (pSMBr->DialectIndex == BAD_PROT)) { 432 /* Check wct = 1 error case */
433 /* core returns wct = 1, but we do not ask for 433 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
434 core - otherwise it just comes when dialect 434 /* core returns wct = 1, but we do not ask for core - otherwise
435 index is -1 indicating we could not negotiate 435 small wct just comes when dialect index is -1 indicating we
436 a common dialect */ 436 could not negotiate a common dialect */
437 rc = -EOPNOTSUPP;
438 goto neg_err_exit;
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"));
437 rc = -EOPNOTSUPP; 450 rc = -EOPNOTSUPP;
438 goto neg_err_exit; 451 goto neg_err_exit;
439#ifdef CONFIG_CIFS_WEAK_PW_HASH 452 }
440 } else if((pSMBr->hdr.WordCount == 13) 453 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
441 && (pSMBr->DialectIndex == LANMAN_PROT)) { 454 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
442 struct lanman_neg_rsp * rsp = 455 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
443 (struct lanman_neg_rsp *)pSMBr;
444
445 if((extended_security & CIFSSEC_MAY_LANMAN) ||
446 (extended_security & CIFSSEC_MAY_PLNTXT))
447 server->secType = LANMAN;
448 else {
449 cERROR(1, ("mount failed weak security disabled"
450 " in /proc/fs/cifs/SecurityFlags"));
451 rc = -EOPNOTSUPP;
452 goto neg_err_exit;
453 }
454 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
455 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
456 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
457 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 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);
458 468
459 /* BB what do we do with raw mode? BB */ 469 /* BB get server time for time conversions and add
460 server->timeZone = le16_to_cpu(rsp->ServerTimeZone); 470 code to use it and timezone since this is not UTC */
461 /* Do we have to set signing flags? no signing
462 was available LANMAN - default should be ok */
463
464 /* BB FIXME set default dummy capabilities since
465 they are not returned by the server in this dialect */
466
467 /* get server time for time conversions and add
468 code to use it and timezone since this is not UTC */
469 471
470 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 472 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
471 memcpy(server->cryptKey, rsp->EncryptionKey, 473 memcpy(server->cryptKey, rsp->EncryptionKey,
472 CIFS_CRYPTO_KEY_SIZE); 474 CIFS_CRYPTO_KEY_SIZE);
473 } else { 475 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
474 rc = -EIO; 476 rc = -EIO; /* need cryptkey unless plain text */
475 goto neg_err_exit; 477 goto neg_err_exit;
476 } 478 }
477 479
478 cFYI(1,("LANMAN negotiated")); /* BB removeme BB */ 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;
479#else /* weak security disabled */ 484#else /* weak security disabled */
480 } else if(pSMBr->hdr.WordCount == 13) { 485 } else if(pSMBr->hdr.WordCount == 13) {
481 cERROR(1,("mount failed, cifs module not built " 486 cERROR(1,("mount failed, cifs module not built "
482 "with CIFS_WEAK_PW_HASH support")); 487 "with CIFS_WEAK_PW_HASH support"));
483 rc = -EOPNOTSUPP; 488 rc = -EOPNOTSUPP;
484#endif /* WEAK_PW_HASH */ 489#endif /* WEAK_PW_HASH */
485 goto neg_err_exit; 490 goto neg_err_exit;
486 } else if(pSMBr->hdr.WordCount != 17) { 491 } else if(pSMBr->hdr.WordCount != 17) {
487 /* unknown wct */ 492 /* unknown wct */
488 rc = -EOPNOTSUPP; 493 rc = -EOPNOTSUPP;
489 goto neg_err_exit; 494 goto neg_err_exit;
490 } 495 }
491 496 /* else wct == 17 NTLM */
492 server->secMode = pSMBr->SecurityMode; 497 server->secMode = pSMBr->SecurityMode;
493 if((server->secMode & SECMODE_USER) == 0) 498 if((server->secMode & SECMODE_USER) == 0)
494 cFYI(1,("share mode security")); 499 cFYI(1,("share mode security"));
495 500
496 if((server->secMode & SECMODE_PW_ENCRYPT) == 0) 501 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
497#ifdef CONFIG_CIFS_WEAK_PW_HASH 502#ifdef CONFIG_CIFS_WEAK_PW_HASH
498 if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0) 503 if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0)
499#endif /* CIFS_WEAK_PW_HASH */ 504#endif /* CIFS_WEAK_PW_HASH */
500 cERROR(1,("Server requests plain text password" 505 cERROR(1,("Server requests plain text password"
501 " but client support disabled")); 506 " but client support disabled"));
502 507
503 if(extended_security & CIFSSEC_MUST_NTLMV2) 508 if(extended_security & CIFSSEC_MUST_NTLMV2)
504 server->secType = NTLMv2; 509 server->secType = NTLMv2;
505 else 510 else
506 server->secType = NTLM; 511 server->secType = NTLM;
507 /* else krb5 ... */ 512 /* else krb5 ... */
508 513
509 /* one byte - no need to convert this or EncryptionKeyLen 514 /* one byte, so no need to convert this or EncryptionKeyLen from
510 from little endian */ 515 little endian */
511 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 516 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
512 /* probably no need to store and check maxvcs */ 517 /* probably no need to store and check maxvcs */
513 server->maxBuf = 518 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
514 min(le32_to_cpu(pSMBr->MaxBufferSize),
515 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 519 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
516 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 520 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
517 cFYI(0, ("Max buf = %d", ses->server->maxBuf)); 521 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
518 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 522 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
519 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 523 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
520 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); 524 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
521 /* BB with UTC do we ever need to be using srvr timezone? */ 525 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
522 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 526 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
523 memcpy(server->cryptKey, pSMBr->u.EncryptionKey, 527 CIFS_CRYPTO_KEY_SIZE);
524 CIFS_CRYPTO_KEY_SIZE); 528 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
525 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) 529 && (pSMBr->EncryptionKeyLength == 0)) {
526 && (pSMBr->EncryptionKeyLength == 0)) { 530 /* decode security blob */
527 /* decode security blob */ 531 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
528 } else 532 rc = -EIO; /* no crypt key only if plain text pwd */
529 rc = -EIO; 533 goto neg_err_exit;
534 }
530 535
531 /* 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 */
532 537
533 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 538 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
534 (server->capabilities & CAP_EXTENDED_SECURITY)) { 539 (server->capabilities & CAP_EXTENDED_SECURITY)) {
535 count = pSMBr->ByteCount; 540 count = pSMBr->ByteCount;
536 if (count < 16) 541 if (count < 16)
537 rc = -EIO; 542 rc = -EIO;
538 else if (count == 16) { 543 else if (count == 16) {
539 server->secType = RawNTLMSSP; 544 server->secType = RawNTLMSSP;
540 if (server->socketUseCount.counter > 1) { 545 if (server->socketUseCount.counter > 1) {
541 if (memcmp 546 if (memcmp(server->server_GUID,
542 (server->server_GUID, 547 pSMBr->u.extended_response.
543 pSMBr->u.extended_response. 548 GUID, 16) != 0) {
544 GUID, 16) != 0) { 549 cFYI(1, ("server UID changed"));
545 cFYI(1, ("server UID changed"));
546 memcpy(server->
547 server_GUID,
548 pSMBr->u.
549 extended_response.
550 GUID, 16);
551 }
552 } else
553 memcpy(server->server_GUID, 550 memcpy(server->server_GUID,
554 pSMBr->u.extended_response. 551 pSMBr->u.extended_response.GUID,
555 GUID, 16); 552 16);
556 } else {
557 rc = decode_negTokenInit(pSMBr->u.
558 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;
567 } 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;
568 } 567 }
569 } else
570 server->capabilities &= ~CAP_EXTENDED_SECURITY;
571 if(sign_CIFS_PDUs == FALSE) {
572 if(server->secMode & SECMODE_SIGN_REQUIRED)
573 cERROR(1,
574 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
575 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
576 } else if(sign_CIFS_PDUs == 1) {
577 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
578 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
579 } 568 }
580 569 } else
570 server->capabilities &= ~CAP_EXTENDED_SECURITY;
571
572signing_check:
573 if(sign_CIFS_PDUs == FALSE) {
574 if(server->secMode & SECMODE_SIGN_REQUIRED)
575 cERROR(1,("Server requires "
576 "/proc/fs/cifs/PacketSigningEnabled to be on"));
577 server->secMode &=
578 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
579 } else if(sign_CIFS_PDUs == 1) {
580 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
581 server->secMode &=
582 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
583 } else if(sign_CIFS_PDUs == 2) {
584 if((server->secMode &
585 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
586 cERROR(1,("signing required but server lacks support"));
587 }
581 } 588 }
582neg_err_exit: 589neg_err_exit:
583 cifs_buf_release(pSMB); 590 cifs_buf_release(pSMB);
591
592 cFYI(1,("negprot rc %d",rc));
584 return rc; 593 return rc;
585} 594}
586 595