diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 425 |
1 files changed, 207 insertions, 218 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a58dc77cc443..a89c4cb4e6cf 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -367,6 +367,185 @@ vt2_err: | |||
367 | return -EINVAL; | 367 | return -EINVAL; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int | ||
371 | decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr) | ||
372 | { | ||
373 | int rc = 0; | ||
374 | u16 count; | ||
375 | char *guid = pSMBr->u.extended_response.GUID; | ||
376 | struct TCP_Server_Info *server = ses->server; | ||
377 | |||
378 | count = get_bcc(&pSMBr->hdr); | ||
379 | if (count < SMB1_CLIENT_GUID_SIZE) | ||
380 | return -EIO; | ||
381 | |||
382 | spin_lock(&cifs_tcp_ses_lock); | ||
383 | if (server->srv_count > 1) { | ||
384 | spin_unlock(&cifs_tcp_ses_lock); | ||
385 | if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) { | ||
386 | cifs_dbg(FYI, "server UID changed\n"); | ||
387 | memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE); | ||
388 | } | ||
389 | } else { | ||
390 | spin_unlock(&cifs_tcp_ses_lock); | ||
391 | memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE); | ||
392 | } | ||
393 | |||
394 | if (count == SMB1_CLIENT_GUID_SIZE) { | ||
395 | server->sec_ntlmssp = true; | ||
396 | } else { | ||
397 | count -= SMB1_CLIENT_GUID_SIZE; | ||
398 | rc = decode_negTokenInit( | ||
399 | pSMBr->u.extended_response.SecurityBlob, count, server); | ||
400 | if (rc != 1) | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | int | ||
408 | cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) | ||
409 | { | ||
410 | bool srv_sign_required = server->sec_mode & server->vals->signing_required; | ||
411 | bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled; | ||
412 | bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN; | ||
413 | |||
414 | /* | ||
415 | * Is signing required by mnt options? If not then check | ||
416 | * global_secflags to see if it is there. | ||
417 | */ | ||
418 | if (!mnt_sign_required) | ||
419 | mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) == | ||
420 | CIFSSEC_MUST_SIGN); | ||
421 | |||
422 | /* | ||
423 | * If signing is required then it's automatically enabled too, | ||
424 | * otherwise, check to see if the secflags allow it. | ||
425 | */ | ||
426 | mnt_sign_enabled = mnt_sign_required ? mnt_sign_required : | ||
427 | (global_secflags & CIFSSEC_MAY_SIGN); | ||
428 | |||
429 | /* If server requires signing, does client allow it? */ | ||
430 | if (srv_sign_required) { | ||
431 | if (!mnt_sign_enabled) { | ||
432 | cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!"); | ||
433 | return -ENOTSUPP; | ||
434 | } | ||
435 | server->sign = true; | ||
436 | } | ||
437 | |||
438 | /* If client requires signing, does server allow it? */ | ||
439 | if (mnt_sign_required) { | ||
440 | if (!srv_sign_enabled) { | ||
441 | cifs_dbg(VFS, "Server does not support signing!"); | ||
442 | return -ENOTSUPP; | ||
443 | } | ||
444 | server->sign = true; | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
451 | static int | ||
452 | decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) | ||
453 | { | ||
454 | __s16 tmp; | ||
455 | struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; | ||
456 | |||
457 | if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT) | ||
458 | return -EOPNOTSUPP; | ||
459 | |||
460 | server->sec_mode = le16_to_cpu(rsp->SecurityMode); | ||
461 | server->maxReq = min_t(unsigned int, | ||
462 | le16_to_cpu(rsp->MaxMpxCount), | ||
463 | cifs_max_pending); | ||
464 | set_credits(server, server->maxReq); | ||
465 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); | ||
466 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | ||
467 | /* even though we do not use raw we might as well set this | ||
468 | accurately, in case we ever find a need for it */ | ||
469 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | ||
470 | server->max_rw = 0xFF00; | ||
471 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; | ||
472 | } else { | ||
473 | server->max_rw = 0;/* do not need to use raw anyway */ | ||
474 | server->capabilities = CAP_MPX_MODE; | ||
475 | } | ||
476 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); | ||
477 | if (tmp == -1) { | ||
478 | /* OS/2 often does not set timezone therefore | ||
479 | * we must use server time to calc time zone. | ||
480 | * Could deviate slightly from the right zone. | ||
481 | * Smallest defined timezone difference is 15 minutes | ||
482 | * (i.e. Nepal). Rounding up/down is done to match | ||
483 | * this requirement. | ||
484 | */ | ||
485 | int val, seconds, remain, result; | ||
486 | struct timespec ts, utc; | ||
487 | utc = CURRENT_TIME; | ||
488 | ts = cnvrtDosUnixTm(rsp->SrvTime.Date, | ||
489 | rsp->SrvTime.Time, 0); | ||
490 | cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n", | ||
491 | (int)ts.tv_sec, (int)utc.tv_sec, | ||
492 | (int)(utc.tv_sec - ts.tv_sec)); | ||
493 | val = (int)(utc.tv_sec - ts.tv_sec); | ||
494 | seconds = abs(val); | ||
495 | result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; | ||
496 | remain = seconds % MIN_TZ_ADJ; | ||
497 | if (remain >= (MIN_TZ_ADJ / 2)) | ||
498 | result += MIN_TZ_ADJ; | ||
499 | if (val < 0) | ||
500 | result = -result; | ||
501 | server->timeAdj = result; | ||
502 | } else { | ||
503 | server->timeAdj = (int)tmp; | ||
504 | server->timeAdj *= 60; /* also in seconds */ | ||
505 | } | ||
506 | cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj); | ||
507 | |||
508 | |||
509 | /* BB get server time for time conversions and add | ||
510 | code to use it and timezone since this is not UTC */ | ||
511 | |||
512 | if (rsp->EncryptionKeyLength == | ||
513 | cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { | ||
514 | memcpy(server->cryptkey, rsp->EncryptionKey, | ||
515 | CIFS_CRYPTO_KEY_SIZE); | ||
516 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | ||
517 | return -EIO; /* need cryptkey unless plain text */ | ||
518 | } | ||
519 | |||
520 | cifs_dbg(FYI, "LANMAN negotiated\n"); | ||
521 | return 0; | ||
522 | } | ||
523 | #else | ||
524 | static inline int | ||
525 | decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) | ||
526 | { | ||
527 | cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n"); | ||
528 | return -EOPNOTSUPP; | ||
529 | } | ||
530 | #endif | ||
531 | |||
532 | static bool | ||
533 | should_set_ext_sec_flag(enum securityEnum sectype) | ||
534 | { | ||
535 | switch (sectype) { | ||
536 | case RawNTLMSSP: | ||
537 | case Kerberos: | ||
538 | return true; | ||
539 | case Unspecified: | ||
540 | if (global_secflags & | ||
541 | (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)) | ||
542 | return true; | ||
543 | /* Fallthrough */ | ||
544 | default: | ||
545 | return false; | ||
546 | } | ||
547 | } | ||
548 | |||
370 | int | 549 | int |
371 | CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | 550 | CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) |
372 | { | 551 | { |
@@ -375,41 +554,24 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | |||
375 | int rc = 0; | 554 | int rc = 0; |
376 | int bytes_returned; | 555 | int bytes_returned; |
377 | int i; | 556 | int i; |
378 | struct TCP_Server_Info *server; | 557 | struct TCP_Server_Info *server = ses->server; |
379 | u16 count; | 558 | u16 count; |
380 | unsigned int secFlags; | ||
381 | 559 | ||
382 | if (ses->server) | 560 | if (!server) { |
383 | server = ses->server; | 561 | WARN(1, "%s: server is NULL!\n", __func__); |
384 | else { | 562 | return -EIO; |
385 | rc = -EIO; | ||
386 | return rc; | ||
387 | } | 563 | } |
564 | |||
388 | rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ , | 565 | rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ , |
389 | (void **) &pSMB, (void **) &pSMBr); | 566 | (void **) &pSMB, (void **) &pSMBr); |
390 | if (rc) | 567 | if (rc) |
391 | return rc; | 568 | return rc; |
392 | 569 | ||
393 | /* if any of auth flags (ie not sign or seal) are overriden use them */ | ||
394 | if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
395 | secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */ | ||
396 | else /* if override flags set only sign/seal OR them with global auth */ | ||
397 | secFlags = global_secflags | ses->overrideSecFlg; | ||
398 | |||
399 | cifs_dbg(FYI, "secFlags 0x%x\n", secFlags); | ||
400 | |||
401 | pSMB->hdr.Mid = get_next_mid(server); | 570 | pSMB->hdr.Mid = get_next_mid(server); |
402 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); | 571 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); |
403 | 572 | ||
404 | if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) | 573 | if (should_set_ext_sec_flag(ses->sectype)) { |
405 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 574 | cifs_dbg(FYI, "Requesting extended security."); |
406 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { | ||
407 | cifs_dbg(FYI, "Kerberos only mechanism, enable extended security\n"); | ||
408 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
409 | } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) | ||
410 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
411 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { | ||
412 | cifs_dbg(FYI, "NTLMSSP only mechanism, enable extended security\n"); | ||
413 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 575 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
414 | } | 576 | } |
415 | 577 | ||
@@ -436,127 +598,21 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | |||
436 | could not negotiate a common dialect */ | 598 | could not negotiate a common dialect */ |
437 | rc = -EOPNOTSUPP; | 599 | rc = -EOPNOTSUPP; |
438 | goto neg_err_exit; | 600 | goto neg_err_exit; |
439 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
440 | } else if ((pSMBr->hdr.WordCount == 13) | ||
441 | && ((server->dialect == LANMAN_PROT) | ||
442 | || (server->dialect == LANMAN2_PROT))) { | ||
443 | __s16 tmp; | ||
444 | struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; | ||
445 | |||
446 | if ((secFlags & CIFSSEC_MAY_LANMAN) || | ||
447 | (secFlags & CIFSSEC_MAY_PLNTXT)) | ||
448 | server->secType = LANMAN; | ||
449 | else { | ||
450 | cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n"); | ||
451 | rc = -EOPNOTSUPP; | ||
452 | goto neg_err_exit; | ||
453 | } | ||
454 | server->sec_mode = le16_to_cpu(rsp->SecurityMode); | ||
455 | server->maxReq = min_t(unsigned int, | ||
456 | le16_to_cpu(rsp->MaxMpxCount), | ||
457 | cifs_max_pending); | ||
458 | set_credits(server, server->maxReq); | ||
459 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); | ||
460 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | ||
461 | /* even though we do not use raw we might as well set this | ||
462 | accurately, in case we ever find a need for it */ | ||
463 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | ||
464 | server->max_rw = 0xFF00; | ||
465 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; | ||
466 | } else { | ||
467 | server->max_rw = 0;/* do not need to use raw anyway */ | ||
468 | server->capabilities = CAP_MPX_MODE; | ||
469 | } | ||
470 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); | ||
471 | if (tmp == -1) { | ||
472 | /* OS/2 often does not set timezone therefore | ||
473 | * we must use server time to calc time zone. | ||
474 | * Could deviate slightly from the right zone. | ||
475 | * Smallest defined timezone difference is 15 minutes | ||
476 | * (i.e. Nepal). Rounding up/down is done to match | ||
477 | * this requirement. | ||
478 | */ | ||
479 | int val, seconds, remain, result; | ||
480 | struct timespec ts, utc; | ||
481 | utc = CURRENT_TIME; | ||
482 | ts = cnvrtDosUnixTm(rsp->SrvTime.Date, | ||
483 | rsp->SrvTime.Time, 0); | ||
484 | cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n", | ||
485 | (int)ts.tv_sec, (int)utc.tv_sec, | ||
486 | (int)(utc.tv_sec - ts.tv_sec)); | ||
487 | val = (int)(utc.tv_sec - ts.tv_sec); | ||
488 | seconds = abs(val); | ||
489 | result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; | ||
490 | remain = seconds % MIN_TZ_ADJ; | ||
491 | if (remain >= (MIN_TZ_ADJ / 2)) | ||
492 | result += MIN_TZ_ADJ; | ||
493 | if (val < 0) | ||
494 | result = -result; | ||
495 | server->timeAdj = result; | ||
496 | } else { | ||
497 | server->timeAdj = (int)tmp; | ||
498 | server->timeAdj *= 60; /* also in seconds */ | ||
499 | } | ||
500 | cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj); | ||
501 | |||
502 | |||
503 | /* BB get server time for time conversions and add | ||
504 | code to use it and timezone since this is not UTC */ | ||
505 | |||
506 | if (rsp->EncryptionKeyLength == | ||
507 | cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { | ||
508 | memcpy(ses->server->cryptkey, rsp->EncryptionKey, | ||
509 | CIFS_CRYPTO_KEY_SIZE); | ||
510 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | ||
511 | rc = -EIO; /* need cryptkey unless plain text */ | ||
512 | goto neg_err_exit; | ||
513 | } | ||
514 | |||
515 | cifs_dbg(FYI, "LANMAN negotiated\n"); | ||
516 | /* we will not end up setting signing flags - as no signing | ||
517 | was in LANMAN and server did not return the flags on */ | ||
518 | goto signing_check; | ||
519 | #else /* weak security disabled */ | ||
520 | } else if (pSMBr->hdr.WordCount == 13) { | 601 | } else if (pSMBr->hdr.WordCount == 13) { |
521 | cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n"); | 602 | server->negflavor = CIFS_NEGFLAVOR_LANMAN; |
522 | rc = -EOPNOTSUPP; | 603 | rc = decode_lanman_negprot_rsp(server, pSMBr); |
523 | #endif /* WEAK_PW_HASH */ | 604 | goto signing_check; |
524 | goto neg_err_exit; | ||
525 | } else if (pSMBr->hdr.WordCount != 17) { | 605 | } else if (pSMBr->hdr.WordCount != 17) { |
526 | /* unknown wct */ | 606 | /* unknown wct */ |
527 | rc = -EOPNOTSUPP; | 607 | rc = -EOPNOTSUPP; |
528 | goto neg_err_exit; | 608 | goto neg_err_exit; |
529 | } | 609 | } |
530 | /* else wct == 17 NTLM */ | 610 | /* else wct == 17, NTLM or better */ |
611 | |||
531 | server->sec_mode = pSMBr->SecurityMode; | 612 | server->sec_mode = pSMBr->SecurityMode; |
532 | if ((server->sec_mode & SECMODE_USER) == 0) | 613 | if ((server->sec_mode & SECMODE_USER) == 0) |
533 | cifs_dbg(FYI, "share mode security\n"); | 614 | cifs_dbg(FYI, "share mode security\n"); |
534 | 615 | ||
535 | if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0) | ||
536 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
537 | if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0) | ||
538 | #endif /* CIFS_WEAK_PW_HASH */ | ||
539 | cifs_dbg(VFS, "Server requests plain text password but client support disabled\n"); | ||
540 | |||
541 | if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) | ||
542 | server->secType = NTLMv2; | ||
543 | else if (secFlags & CIFSSEC_MAY_NTLM) | ||
544 | server->secType = NTLM; | ||
545 | else if (secFlags & CIFSSEC_MAY_NTLMV2) | ||
546 | server->secType = NTLMv2; | ||
547 | else if (secFlags & CIFSSEC_MAY_KRB5) | ||
548 | server->secType = Kerberos; | ||
549 | else if (secFlags & CIFSSEC_MAY_NTLMSSP) | ||
550 | server->secType = RawNTLMSSP; | ||
551 | else if (secFlags & CIFSSEC_MAY_LANMAN) | ||
552 | server->secType = LANMAN; | ||
553 | else { | ||
554 | rc = -EOPNOTSUPP; | ||
555 | cifs_dbg(VFS, "Invalid security type\n"); | ||
556 | goto neg_err_exit; | ||
557 | } | ||
558 | /* else ... any others ...? */ | ||
559 | |||
560 | /* one byte, so no need to convert this or EncryptionKeyLen from | 616 | /* one byte, so no need to convert this or EncryptionKeyLen from |
561 | little endian */ | 617 | little endian */ |
562 | server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), | 618 | server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), |
@@ -569,90 +625,26 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) | |||
569 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 625 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
570 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); | 626 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); |
571 | server->timeAdj *= 60; | 627 | server->timeAdj *= 60; |
628 | |||
572 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { | 629 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { |
630 | server->negflavor = CIFS_NEGFLAVOR_UNENCAP; | ||
573 | memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, | 631 | memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, |
574 | CIFS_CRYPTO_KEY_SIZE); | 632 | CIFS_CRYPTO_KEY_SIZE); |
575 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || | 633 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || |
576 | server->capabilities & CAP_EXTENDED_SECURITY) && | 634 | server->capabilities & CAP_EXTENDED_SECURITY) && |
577 | (pSMBr->EncryptionKeyLength == 0)) { | 635 | (pSMBr->EncryptionKeyLength == 0)) { |
578 | /* decode security blob */ | 636 | server->negflavor = CIFS_NEGFLAVOR_EXTENDED; |
579 | count = get_bcc(&pSMBr->hdr); | 637 | rc = decode_ext_sec_blob(ses, pSMBr); |
580 | if (count < 16) { | ||
581 | rc = -EIO; | ||
582 | goto neg_err_exit; | ||
583 | } | ||
584 | spin_lock(&cifs_tcp_ses_lock); | ||
585 | if (server->srv_count > 1) { | ||
586 | spin_unlock(&cifs_tcp_ses_lock); | ||
587 | if (memcmp(server->server_GUID, | ||
588 | pSMBr->u.extended_response. | ||
589 | GUID, 16) != 0) { | ||
590 | cifs_dbg(FYI, "server UID changed\n"); | ||
591 | memcpy(server->server_GUID, | ||
592 | pSMBr->u.extended_response.GUID, | ||
593 | 16); | ||
594 | } | ||
595 | } else { | ||
596 | spin_unlock(&cifs_tcp_ses_lock); | ||
597 | memcpy(server->server_GUID, | ||
598 | pSMBr->u.extended_response.GUID, 16); | ||
599 | } | ||
600 | |||
601 | if (count == 16) { | ||
602 | server->secType = RawNTLMSSP; | ||
603 | } else { | ||
604 | rc = decode_negTokenInit(pSMBr->u.extended_response. | ||
605 | SecurityBlob, count - 16, | ||
606 | server); | ||
607 | if (rc == 1) | ||
608 | rc = 0; | ||
609 | else | ||
610 | rc = -EINVAL; | ||
611 | if (server->secType == Kerberos) { | ||
612 | if (!server->sec_kerberos && | ||
613 | !server->sec_mskerberos) | ||
614 | rc = -EOPNOTSUPP; | ||
615 | } else if (server->secType == RawNTLMSSP) { | ||
616 | if (!server->sec_ntlmssp) | ||
617 | rc = -EOPNOTSUPP; | ||
618 | } else | ||
619 | rc = -EOPNOTSUPP; | ||
620 | } | ||
621 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | 638 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { |
622 | rc = -EIO; /* no crypt key only if plain text pwd */ | 639 | rc = -EIO; /* no crypt key only if plain text pwd */ |
623 | goto neg_err_exit; | ||
624 | } else | ||
625 | server->capabilities &= ~CAP_EXTENDED_SECURITY; | ||
626 | |||
627 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
628 | signing_check: | ||
629 | #endif | ||
630 | if ((secFlags & CIFSSEC_MAY_SIGN) == 0) { | ||
631 | /* MUST_SIGN already includes the MAY_SIGN FLAG | ||
632 | so if this is zero it means that signing is disabled */ | ||
633 | cifs_dbg(FYI, "Signing disabled\n"); | ||
634 | if (server->sec_mode & SECMODE_SIGN_REQUIRED) { | ||
635 | cifs_dbg(VFS, "Server requires packet signing to be enabled in /proc/fs/cifs/SecurityFlags\n"); | ||
636 | rc = -EOPNOTSUPP; | ||
637 | } | ||
638 | server->sec_mode &= | ||
639 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
640 | } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { | ||
641 | /* signing required */ | ||
642 | cifs_dbg(FYI, "Must sign - secFlags 0x%x\n", secFlags); | ||
643 | if ((server->sec_mode & | ||
644 | (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { | ||
645 | cifs_dbg(VFS, "signing required but server lacks support\n"); | ||
646 | rc = -EOPNOTSUPP; | ||
647 | } else | ||
648 | server->sec_mode |= SECMODE_SIGN_REQUIRED; | ||
649 | } else { | 640 | } else { |
650 | /* signing optional ie CIFSSEC_MAY_SIGN */ | 641 | server->negflavor = CIFS_NEGFLAVOR_UNENCAP; |
651 | if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0) | 642 | server->capabilities &= ~CAP_EXTENDED_SECURITY; |
652 | server->sec_mode &= | ||
653 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | ||
654 | } | 643 | } |
655 | 644 | ||
645 | signing_check: | ||
646 | if (!rc) | ||
647 | rc = cifs_enable_signing(server, ses->sign); | ||
656 | neg_err_exit: | 648 | neg_err_exit: |
657 | cifs_buf_release(pSMB); | 649 | cifs_buf_release(pSMB); |
658 | 650 | ||
@@ -777,9 +769,8 @@ CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses) | |||
777 | 769 | ||
778 | pSMB->hdr.Mid = get_next_mid(ses->server); | 770 | pSMB->hdr.Mid = get_next_mid(ses->server); |
779 | 771 | ||
780 | if (ses->server->sec_mode & | 772 | if (ses->server->sign) |
781 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 773 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
782 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
783 | 774 | ||
784 | pSMB->hdr.Uid = ses->Suid; | 775 | pSMB->hdr.Uid = ses->Suid; |
785 | 776 | ||
@@ -1540,8 +1531,7 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
1540 | switch (mid->mid_state) { | 1531 | switch (mid->mid_state) { |
1541 | case MID_RESPONSE_RECEIVED: | 1532 | case MID_RESPONSE_RECEIVED: |
1542 | /* result already set, check signature */ | 1533 | /* result already set, check signature */ |
1543 | if (server->sec_mode & | 1534 | if (server->sign) { |
1544 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
1545 | int rc = 0; | 1535 | int rc = 0; |
1546 | 1536 | ||
1547 | rc = cifs_verify_signature(&rqst, server, | 1537 | rc = cifs_verify_signature(&rqst, server, |
@@ -3940,6 +3930,7 @@ QFileInfoRetry: | |||
3940 | pSMB->Pad = 0; | 3930 | pSMB->Pad = 0; |
3941 | pSMB->Fid = netfid; | 3931 | pSMB->Fid = netfid; |
3942 | inc_rfc1001_len(pSMB, byte_count); | 3932 | inc_rfc1001_len(pSMB, byte_count); |
3933 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | ||
3943 | 3934 | ||
3944 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3935 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3945 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3936 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -4108,6 +4099,7 @@ UnixQFileInfoRetry: | |||
4108 | pSMB->Pad = 0; | 4099 | pSMB->Pad = 0; |
4109 | pSMB->Fid = netfid; | 4100 | pSMB->Fid = netfid; |
4110 | inc_rfc1001_len(pSMB, byte_count); | 4101 | inc_rfc1001_len(pSMB, byte_count); |
4102 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | ||
4111 | 4103 | ||
4112 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4104 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
4113 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4105 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -4794,11 +4786,8 @@ getDFSRetry: | |||
4794 | strncpy(pSMB->RequestFileName, search_name, name_len); | 4786 | strncpy(pSMB->RequestFileName, search_name, name_len); |
4795 | } | 4787 | } |
4796 | 4788 | ||
4797 | if (ses->server) { | 4789 | if (ses->server && ses->server->sign) |
4798 | if (ses->server->sec_mode & | 4790 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
4799 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
4800 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
4801 | } | ||
4802 | 4791 | ||
4803 | pSMB->hdr.Uid = ses->Suid; | 4792 | pSMB->hdr.Uid = ses->Suid; |
4804 | 4793 | ||