aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2013-05-26 07:01:02 -0400
committerSteve French <smfrench@gmail.com>2013-06-26 18:31:55 -0400
commit52dfb446dbc1915e1df89f8ea9cae1fee7ab3d5e (patch)
tree69ab965c02081ef4a2ac82e3958a724e4ac6baa5 /fs/cifs
parent5d875cc928aa7c95c8c1e89497a9a644f32213d4 (diff)
cifs: try to handle the MUST SecurityFlags sanely
The cifs.ko SecurityFlags interface wins my award for worst-designed interface ever, but we're sort of stuck with it since it's documented and people do use it (even if it doesn't work correctly). Case in point -- you can specify multiple sets of "MUST" flags. It makes absolutely no sense, but you can do it. What should the effect be in such a case? No one knows or seems to have considered this so far, so let's define it now. If you try to specify multiple MUST flags, clear any other MAY or MUST bits except for the ones that involve signing. 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')
-rw-r--r--fs/cifs/cifs_debug.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 0315824bbf01..f3ac4154cbb6 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -597,6 +597,32 @@ static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
597 return single_open(file, cifs_security_flags_proc_show, NULL); 597 return single_open(file, cifs_security_flags_proc_show, NULL);
598} 598}
599 599
600/*
601 * Ensure that if someone sets a MUST flag, that we disable all other MAY
602 * flags except for the ones corresponding to the given MUST flag. If there are
603 * multiple MUST flags, then try to prefer more secure ones.
604 */
605static void
606cifs_security_flags_handle_must_flags(unsigned int *flags)
607{
608 unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
609
610 if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
611 *flags = CIFSSEC_MUST_KRB5;
612 else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
613 *flags = CIFSSEC_MUST_NTLMSSP;
614 else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
615 *flags = CIFSSEC_MUST_NTLMV2;
616 else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM)
617 *flags = CIFSSEC_MUST_NTLM;
618 else if ((*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN)
619 *flags = CIFSSEC_MUST_LANMAN;
620 else if ((*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT)
621 *flags = CIFSSEC_MUST_PLNTXT;
622
623 *flags |= signflags;
624}
625
600static ssize_t cifs_security_flags_proc_write(struct file *file, 626static ssize_t cifs_security_flags_proc_write(struct file *file,
601 const char __user *buffer, size_t count, loff_t *ppos) 627 const char __user *buffer, size_t count, loff_t *ppos)
602{ 628{
@@ -650,6 +676,8 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
650 return -EINVAL; 676 return -EINVAL;
651 } 677 }
652 678
679 cifs_security_flags_handle_must_flags(&flags);
680
653 /* flags look ok - update the global security flags for cifs module */ 681 /* flags look ok - update the global security flags for cifs module */
654 global_secflags = flags; 682 global_secflags = flags;
655 if (global_secflags & CIFSSEC_MUST_SIGN) { 683 if (global_secflags & CIFSSEC_MUST_SIGN) {