summaryrefslogtreecommitdiffstats
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 17:31:55 -0500
commit52dfb446dbc1915e1df89f8ea9cae1fee7ab3d5e (patch)
tree69ab965c02081ef4a2ac82e3958a724e4ac6baa5 /fs/cifs
parent5d875cc928aa7c95c8c1e89497a9a644f32213d4 (diff)
downloadlinux-stable-52dfb446dbc1915e1df89f8ea9cae1fee7ab3d5e.tar.gz
linux-stable-52dfb446dbc1915e1df89f8ea9cae1fee7ab3d5e.tar.bz2
linux-stable-52dfb446dbc1915e1df89f8ea9cae1fee7ab3d5e.zip
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)
return single_open(file, cifs_security_flags_proc_show, NULL);
}
+/*
+ * Ensure that if someone sets a MUST flag, that we disable all other MAY
+ * flags except for the ones corresponding to the given MUST flag. If there are
+ * multiple MUST flags, then try to prefer more secure ones.
+ */
+static void
+cifs_security_flags_handle_must_flags(unsigned int *flags)
+{
+ unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
+
+ if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+ *flags = CIFSSEC_MUST_KRB5;
+ else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
+ *flags = CIFSSEC_MUST_NTLMSSP;
+ else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
+ *flags = CIFSSEC_MUST_NTLMV2;
+ else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM)
+ *flags = CIFSSEC_MUST_NTLM;
+ else if ((*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN)
+ *flags = CIFSSEC_MUST_LANMAN;
+ else if ((*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT)
+ *flags = CIFSSEC_MUST_PLNTXT;
+
+ *flags |= signflags;
+}
+
static ssize_t cifs_security_flags_proc_write(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos)
{
@@ -650,6 +676,8 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
return -EINVAL;
}
+ cifs_security_flags_handle_must_flags(&flags);
+
/* flags look ok - update the global security flags for cifs module */
global_secflags = flags;
if (global_secflags & CIFSSEC_MUST_SIGN) {