aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2013-05-26 07:01:00 -0400
committerSteve French <smfrench@gmail.com>2013-06-24 02:56:43 -0400
commit38d77c50b4f4e3ea1687e119871364f1c8d2f531 (patch)
treeb222f1aa85155a24fafcabea2f8e8c17197fb2ae /fs/cifs/cifssmb.c
parent1e3cc57e474867771aba2bdf23d0c7d8fb5e4822 (diff)
cifs: track the enablement of signing in the TCP_Server_Info
Currently, we determine this according to flags in the sec_mode, flags in the global_secflags and via other methods. That makes the semantics very hard to follow and there are corner cases where we don't handle this correctly. Add a new bool to the TCP_Server_Info that acts as a simple flag to tell us whether signing is enabled on this connection or not, and fix up the places that need to determine this to use that flag. This is a bit weird for the SMB2 case, where signing is per-session. SMB2 needs work in this area already though. The existing SMB2 code has similar logic to what we're using here, so there should be no real change in behavior. These changes should make it easier to implement per-session signing in the future though. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 80ca6886a816..dd7e2f61f607 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -418,32 +418,43 @@ decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
418} 418}
419 419
420int 420int
421cifs_enable_signing(struct TCP_Server_Info *server, unsigned int secFlags) 421cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
422{ 422{
423 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) { 423 bool srv_sign_required = server->sec_mode & SECMODE_SIGN_REQUIRED;
424 /* MUST_SIGN already includes the MAY_SIGN FLAG 424 bool srv_sign_enabled = server->sec_mode & SECMODE_SIGN_ENABLED;
425 so if this is zero it means that signing is disabled */ 425 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
426 cifs_dbg(FYI, "Signing disabled\n"); 426
427 if (server->sec_mode & SECMODE_SIGN_REQUIRED) { 427 /*
428 cifs_dbg(VFS, "Server requires packet signing to be enabled in /proc/fs/cifs/SecurityFlags\n"); 428 * Is signing required by mnt options? If not then check
429 return -EOPNOTSUPP; 429 * global_secflags to see if it is there.
430 */
431 if (!mnt_sign_required)
432 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
433 CIFSSEC_MUST_SIGN);
434
435 /*
436 * If signing is required then it's automatically enabled too,
437 * otherwise, check to see if the secflags allow it.
438 */
439 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
440 (global_secflags & CIFSSEC_MAY_SIGN);
441
442 /* If server requires signing, does client allow it? */
443 if (srv_sign_required) {
444 if (!mnt_sign_enabled) {
445 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
446 return -ENOTSUPP;
430 } 447 }
431 server->sec_mode &= 448 server->sign = true;
432 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); 449 }
433 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { 450
434 /* signing required */ 451 /* If client requires signing, does server allow it? */
435 cifs_dbg(FYI, "Must sign - secFlags 0x%x\n", secFlags); 452 if (mnt_sign_required) {
436 if ((server->sec_mode & 453 if (!srv_sign_enabled) {
437 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { 454 cifs_dbg(VFS, "Server does not support signing!");
438 cifs_dbg(VFS, "signing required but server lacks support\n"); 455 return -ENOTSUPP;
439 return -EOPNOTSUPP; 456 }
440 } else 457 server->sign = true;
441 server->sec_mode |= SECMODE_SIGN_REQUIRED;
442 } else {
443 /* signing optional ie CIFSSEC_MAY_SIGN */
444 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
445 server->sec_mode &=
446 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
447 } 458 }
448 459
449 return 0; 460 return 0;
@@ -685,7 +696,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
685 696
686signing_check: 697signing_check:
687 if (!rc) 698 if (!rc)
688 rc = cifs_enable_signing(server, secFlags); 699 rc = cifs_enable_signing(server, ses->sign);
689neg_err_exit: 700neg_err_exit:
690 cifs_buf_release(pSMB); 701 cifs_buf_release(pSMB);
691 702
@@ -810,9 +821,8 @@ CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
810 821
811 pSMB->hdr.Mid = get_next_mid(ses->server); 822 pSMB->hdr.Mid = get_next_mid(ses->server);
812 823
813 if (ses->server->sec_mode & 824 if (ses->server->sign)
814 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 825 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
815 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
816 826
817 pSMB->hdr.Uid = ses->Suid; 827 pSMB->hdr.Uid = ses->Suid;
818 828
@@ -1573,8 +1583,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
1573 switch (mid->mid_state) { 1583 switch (mid->mid_state) {
1574 case MID_RESPONSE_RECEIVED: 1584 case MID_RESPONSE_RECEIVED:
1575 /* result already set, check signature */ 1585 /* result already set, check signature */
1576 if (server->sec_mode & 1586 if (server->sign) {
1577 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1578 int rc = 0; 1587 int rc = 0;
1579 1588
1580 rc = cifs_verify_signature(&rqst, server, 1589 rc = cifs_verify_signature(&rqst, server,
@@ -4827,11 +4836,8 @@ getDFSRetry:
4827 strncpy(pSMB->RequestFileName, search_name, name_len); 4836 strncpy(pSMB->RequestFileName, search_name, name_len);
4828 } 4837 }
4829 4838
4830 if (ses->server) { 4839 if (ses->server && ses->server->sign)
4831 if (ses->server->sec_mode & 4840 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4832 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4833 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4834 }
4835 4841
4836 pSMB->hdr.Uid = ses->Suid; 4842 pSMB->hdr.Uid = ses->Suid;
4837 4843