Commit 9f6ed2ca authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

keys: add a "logon" key type

For CIFS, we want to be able to store NTLM credentials (aka username
and password) in the keyring. We do not, however want to allow users
to fetch those keys back out of the keyring since that would be a
security risk.

Unfortunately, due to the nuances of key permission bits, it's not
possible to do this. We need to grant search permissions so the kernel
can find these keys, but that also implies permissions to read the
payload.

Resolve this by adding a new key_type. This key type is essentially
the same as key_type_user, but does not define a .read op. This
prevents the payload from ever being visible from userspace. This
key type also vets the description to ensure that it's "qualified"
by checking to ensure that it has a ':' in it that is preceded by
other characters.
Acked-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent ce91acb3
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/*****************************************************************************/ /*****************************************************************************/
/* /*
* the payload for a key of type "user" * the payload for a key of type "user" or "logon"
* - once filled in and attached to a key: * - once filled in and attached to a key:
* - the payload struct is invariant may not be changed, only replaced * - the payload struct is invariant may not be changed, only replaced
* - the payload must be read with RCU procedures or with the key semaphore * - the payload must be read with RCU procedures or with the key semaphore
...@@ -33,6 +33,7 @@ struct user_key_payload { ...@@ -33,6 +33,7 @@ struct user_key_payload {
}; };
extern struct key_type key_type_user; extern struct key_type key_type_user;
extern struct key_type key_type_logon;
extern int user_instantiate(struct key *key, const void *data, size_t datalen); extern int user_instantiate(struct key *key, const void *data, size_t datalen);
extern int user_update(struct key *key, const void *data, size_t datalen); extern int user_update(struct key *key, const void *data, size_t datalen);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
extern struct key_type key_type_dead; extern struct key_type key_type_dead;
extern struct key_type key_type_user; extern struct key_type key_type_user;
extern struct key_type key_type_logon;
/*****************************************************************************/ /*****************************************************************************/
/* /*
......
...@@ -999,6 +999,7 @@ void __init key_init(void) ...@@ -999,6 +999,7 @@ void __init key_init(void)
list_add_tail(&key_type_keyring.link, &key_types_list); list_add_tail(&key_type_keyring.link, &key_types_list);
list_add_tail(&key_type_dead.link, &key_types_list); list_add_tail(&key_type_dead.link, &key_types_list);
list_add_tail(&key_type_user.link, &key_types_list); list_add_tail(&key_type_user.link, &key_types_list);
list_add_tail(&key_type_logon.link, &key_types_list);
/* record the root user tracking */ /* record the root user tracking */
rb_link_node(&root_key_user.node, rb_link_node(&root_key_user.node,
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "internal.h" #include "internal.h"
static int logon_vet_description(const char *desc);
/* /*
* user defined keys take an arbitrary string as the description and an * user defined keys take an arbitrary string as the description and an
* arbitrary blob of data as the payload * arbitrary blob of data as the payload
...@@ -35,6 +37,24 @@ struct key_type key_type_user = { ...@@ -35,6 +37,24 @@ struct key_type key_type_user = {
EXPORT_SYMBOL_GPL(key_type_user); EXPORT_SYMBOL_GPL(key_type_user);
/*
* This key type is essentially the same as key_type_user, but it does
* not define a .read op. This is suitable for storing username and
* password pairs in the keyring that you do not want to be readable
* from userspace.
*/
struct key_type key_type_logon = {
.name = "logon",
.instantiate = user_instantiate,
.update = user_update,
.match = user_match,
.revoke = user_revoke,
.destroy = user_destroy,
.describe = user_describe,
.vet_description = logon_vet_description,
};
EXPORT_SYMBOL_GPL(key_type_logon);
/* /*
* instantiate a user defined key * instantiate a user defined key
*/ */
...@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) ...@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
} }
EXPORT_SYMBOL_GPL(user_read); EXPORT_SYMBOL_GPL(user_read);
/* Vet the description for a "logon" key */
static int logon_vet_description(const char *desc)
{
char *p;
/* require a "qualified" description string */
p = strchr(desc, ':');
if (!p)
return -EINVAL;
/* also reject description with ':' as first char */
if (p == desc)
return -EINVAL;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment