diff options
author | Tommi Virtanen <tommi.virtanen@dreamhost.com> | 2011-03-25 16:40:48 -0700 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-03-29 12:11:19 -0700 |
commit | e2c3d29b4295c3eec18294bc34f0c99a7b9ae413 (patch) | |
tree | 29fbffeeed7e2774a4f87883ae01798079d85ed2 /net | |
parent | 8323c3aa74cd92465350294567142d12ffdcc963 (diff) | |
download | lwn-e2c3d29b4295c3eec18294bc34f0c99a7b9ae413.tar.gz lwn-e2c3d29b4295c3eec18294bc34f0c99a7b9ae413.zip |
libceph: Get secret from the kernel keys api when mounting with key=NAME.
Signed-off-by: Tommi Virtanen <tommi.virtanen@dreamhost.com>
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/Kconfig | 1 | ||||
-rw-r--r-- | net/ceph/ceph_common.c | 58 |
2 files changed, 59 insertions, 0 deletions
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index ad424049b0cf..be683f2d401f 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig @@ -4,6 +4,7 @@ config CEPH_LIB select LIBCRC32C select CRYPTO_AES select CRYPTO + select KEYS default n help Choose Y or M here to include cephlib, which provides the diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 02e084f29d24..c92bc8d50597 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -5,6 +5,8 @@ #include <linux/fs.h> #include <linux/inet.h> #include <linux/in6.h> +#include <linux/key.h> +#include <keys/user-type.h> #include <linux/module.h> #include <linux/mount.h> #include <linux/parser.h> @@ -197,6 +199,7 @@ enum { Opt_fsid, Opt_name, Opt_secret, + Opt_key, Opt_ip, Opt_last_string, /* string args above */ @@ -213,6 +216,7 @@ static match_table_t opt_tokens = { {Opt_fsid, "fsid=%s"}, {Opt_name, "name=%s"}, {Opt_secret, "secret=%s"}, + {Opt_key, "key=%s"}, {Opt_ip, "ip=%s"}, /* string args above */ {Opt_noshare, "noshare"}, @@ -232,6 +236,50 @@ void ceph_destroy_options(struct ceph_options *opt) } EXPORT_SYMBOL(ceph_destroy_options); +/* get secret from key store */ +static int get_secret(struct ceph_crypto_key *dst, const char *name) { + struct key *ukey; + int key_err; + int err = 0; + struct user_key_payload *payload; + void *p; + + ukey = request_key(&key_type_user, name, NULL); + if (!ukey || IS_ERR(ukey)) { + /* request_key errors don't map nicely to mount(2) + errors; don't even try, but still printk */ + key_err = PTR_ERR(ukey); + switch (key_err) { + case -ENOKEY: + pr_warning("ceph: Mount failed due to key not found: %s\n", name); + break; + case -EKEYEXPIRED: + pr_warning("ceph: Mount failed due to expired key: %s\n", name); + break; + case -EKEYREVOKED: + pr_warning("ceph: Mount failed due to revoked key: %s\n", name); + break; + default: + pr_warning("ceph: Mount failed due to unknown key error" + " %d: %s\n", key_err, name); + } + err = -EPERM; + goto out; + } + + payload = ukey->payload.data; + p = payload->data; + err = ceph_crypto_key_decode(dst, &p, p + payload->datalen); + if (err) + goto out_key; + /* pass through, err is 0 */ + +out_key: + key_put(ukey); +out: + return err; +} + int ceph_parse_options(struct ceph_options **popt, char *options, const char *dev_name, const char *dev_name_end, int (*parse_extra_token)(char *c, void *private), @@ -328,6 +376,16 @@ int ceph_parse_options(struct ceph_options **popt, char *options, if (err < 0) goto out; break; + case Opt_key: + opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); + if (!opt->key) { + err = -ENOMEM; + goto out; + } + err = get_secret(opt->key, argstr[0].from); + if (err < 0) + goto out; + break; /* misc */ case Opt_osdtimeout: |