libceph: Get secret from the kernel keys api when mounting with key=NAME.
authorTommi Virtanen <tommi.virtanen@dreamhost.com>
Fri, 25 Mar 2011 23:40:48 +0000 (16:40 -0700)
committerSage Weil <sage@newdream.net>
Tue, 29 Mar 2011 19:11:19 +0000 (12:11 -0700)
Signed-off-by: Tommi Virtanen <tommi.virtanen@dreamhost.com>
Signed-off-by: Sage Weil <sage@newdream.net>
net/ceph/Kconfig
net/ceph/ceph_common.c

index ad42404..be683f2 100644 (file)
@@ -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
index 02e084f..c92bc8d 100644 (file)
@@ -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: