ceph: Move secret key parsing earlier.
Tommi Virtanen [Fri, 25 Mar 2011 23:32:57 +0000 (16:32 -0700)]
This makes the base64 logic be contained in mount option parsing,
and prepares us for replacing the homebew key management with the
kernel key retention service.

Signed-off-by: Tommi Virtanen <tommi.virtanen@dreamhost.com>
Signed-off-by: Sage Weil <sage@newdream.net>

fs/ceph/super.c
include/linux/ceph/auth.h
include/linux/ceph/libceph.h
net/ceph/auth.c
net/ceph/auth_x.c
net/ceph/ceph_common.c
net/ceph/crypto.c
net/ceph/crypto.h
net/ceph/mon_client.c

index a9e78b4..f2f77fd 100644 (file)
@@ -353,7 +353,7 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
 
        if (opt->name)
                seq_printf(m, ",name=%s", opt->name);
-       if (opt->secret)
+       if (opt->key)
                seq_puts(m, ",secret=<hidden>");
 
        if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
index 7fff521..aa13392 100644 (file)
@@ -67,12 +67,12 @@ struct ceph_auth_client {
        bool negotiating;       /* true if negotiating protocol */
        const char *name;       /* entity name */
        u64 global_id;          /* our unique id in system */
-       const char *secret;     /* our secret key */
+       const struct ceph_crypto_key *key;     /* our secret key */
        unsigned want_keys;     /* which services we want */
 };
 
 extern struct ceph_auth_client *ceph_auth_init(const char *name,
-                                              const char *secret);
+                                              const struct ceph_crypto_key *key);
 extern void ceph_auth_destroy(struct ceph_auth_client *ac);
 
 extern void ceph_auth_reset(struct ceph_auth_client *ac);
index 0d2e0ff..6365f04 100644 (file)
@@ -61,7 +61,7 @@ struct ceph_options {
                                              pointer type of args */
        int num_mon;
        char *name;
-       char *secret;
+       struct ceph_crypto_key *key;
 };
 
 /*
index 549c1f4..b4bf4ac 100644 (file)
@@ -35,12 +35,12 @@ static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
 /*
  * setup, teardown.
  */
-struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret)
+struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key)
 {
        struct ceph_auth_client *ac;
        int ret;
 
-       dout("auth_init name '%s' secret '%s'\n", name, secret);
+       dout("auth_init name '%s'\n", name);
 
        ret = -ENOMEM;
        ac = kzalloc(sizeof(*ac), GFP_NOFS);
@@ -52,8 +52,8 @@ struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret)
                ac->name = name;
        else
                ac->name = CEPH_AUTH_NAME_DEFAULT;
-       dout("auth_init name %s secret %s\n", ac->name, secret);
-       ac->secret = secret;
+       dout("auth_init name %s\n", ac->name);
+       ac->key = key;
        return ac;
 
 out:
index 7fd5dfc..1587dc6 100644 (file)
@@ -662,14 +662,16 @@ int ceph_x_init(struct ceph_auth_client *ac)
                goto out;
 
        ret = -EINVAL;
-       if (!ac->secret) {
+       if (!ac->key) {
                pr_err("no secret set (for auth_x protocol)\n");
                goto out_nomem;
        }
 
-       ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret);
-       if (ret)
+       ret = ceph_crypto_key_clone(&xi->secret, ac->key);
+       if (ret < 0) {
+               pr_err("cannot clone key: %d\n", ret);
                goto out_nomem;
+       }
 
        xi->starting = true;
        xi->ticket_handlers = RB_ROOT;
index 9bbb356..02e084f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ceph/decode.h>
 #include <linux/ceph/mon_client.h>
 #include <linux/ceph/auth.h>
+#include "crypto.h"
 
 
 
@@ -117,9 +118,29 @@ int ceph_compare_options(struct ceph_options *new_opt,
        if (ret)
                return ret;
 
-       ret = strcmp_null(opt1->secret, opt2->secret);
-       if (ret)
-               return ret;
+       if (opt1->key && !opt2->key)
+               return -1;
+       if (!opt1->key && opt2->key)
+               return 1;
+       if (opt1->key && opt2->key) {
+               if (opt1->key->type != opt2->key->type)
+                       return -1;
+               if (opt1->key->created.tv_sec != opt2->key->created.tv_sec)
+                       return -1;
+               if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec)
+                       return -1;
+               if (opt1->key->len != opt2->key->len)
+                       return -1;
+               if (opt1->key->key && !opt2->key->key)
+                       return -1;
+               if (!opt1->key->key && opt2->key->key)
+                       return 1;
+               if (opt1->key->key && opt2->key->key) {
+                       ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len);
+                       if (ret)
+                               return ret;
+               }
+       }
 
        /* any matching mon ip implies a match */
        for (i = 0; i < opt1->num_mon; i++) {
@@ -203,7 +224,10 @@ void ceph_destroy_options(struct ceph_options *opt)
 {
        dout("destroy_options %p\n", opt);
        kfree(opt->name);
-       kfree(opt->secret);
+       if (opt->key) {
+               ceph_crypto_key_destroy(opt->key);
+               kfree(opt->key);
+       }
        kfree(opt);
 }
 EXPORT_SYMBOL(ceph_destroy_options);
@@ -295,9 +319,14 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
                                              GFP_KERNEL);
                        break;
                case Opt_secret:
-                       opt->secret = kstrndup(argstr[0].from,
-                                               argstr[0].to-argstr[0].from,
-                                               GFP_KERNEL);
+                       opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
+                       if (!opt->key) {
+                               err = -ENOMEM;
+                               goto out;
+                       }
+                       err = ceph_crypto_key_unarmor(opt->key, argstr[0].from);
+                       if (err < 0)
+                               goto out;
                        break;
 
                        /* misc */
index 7b505b0..75f0893 100644 (file)
@@ -9,6 +9,17 @@
 #include <linux/ceph/decode.h>
 #include "crypto.h"
 
+int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
+                         const struct ceph_crypto_key *src)
+{
+       memcpy(dst, src, sizeof(struct ceph_crypto_key));
+       dst->key = kmalloc(src->len, GFP_NOFS);
+       if (!dst->key)
+               return -ENOMEM;
+       memcpy(dst->key, src->key, src->len);
+       return 0;
+}
+
 int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
 {
        if (*p + sizeof(u16) + sizeof(key->created) +
index f9eccac..6cf6edc 100644 (file)
@@ -19,6 +19,8 @@ static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
        kfree(key->key);
 }
 
+extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
+                                const struct ceph_crypto_key *src);
 extern int ceph_crypto_key_encode(struct ceph_crypto_key *key,
                                  void **p, void *end);
 extern int ceph_crypto_key_decode(struct ceph_crypto_key *key,
index 8a07939..cbe31fa 100644 (file)
@@ -759,7 +759,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
 
        /* authentication */
        monc->auth = ceph_auth_init(cl->options->name,
-                                   cl->options->secret);
+                                   cl->options->key);
        if (IS_ERR(monc->auth))
                return PTR_ERR(monc->auth);
        monc->auth->want_keys =