diff options
author | Tommi Virtanen <tommi.virtanen@dreamhost.com> | 2011-03-28 23:59:38 +0200 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-03-29 21:11:24 +0200 |
commit | 4b2a58abd1e17c0ee53c8dded879e015917cca67 (patch) | |
tree | 585a02b8e3e36f7e6069d43000355e75aba097d3 /net | |
parent | libceph: Get secret from the kernel keys api when mounting with key=NAME. (diff) | |
download | linux-4b2a58abd1e17c0ee53c8dded879e015917cca67.tar.xz linux-4b2a58abd1e17c0ee53c8dded879e015917cca67.zip |
libceph: Create a new key type "ceph".
This allows us to use existence of the key type as a feature test,
from userspace.
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/ceph_common.c | 21 | ||||
-rw-r--r-- | net/ceph/crypto.c | 62 | ||||
-rw-r--r-- | net/ceph/crypto.h | 2 |
3 files changed, 77 insertions, 8 deletions
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index c92bc8d50597..132963abc266 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -6,7 +6,7 @@ #include <linux/inet.h> #include <linux/in6.h> #include <linux/key.h> -#include <keys/user-type.h> +#include <keys/ceph-type.h> #include <linux/module.h> #include <linux/mount.h> #include <linux/parser.h> @@ -241,10 +241,9 @@ 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; + struct ceph_crypto_key *ckey; - ukey = request_key(&key_type_user, name, NULL); + ukey = request_key(&key_type_ceph, 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 */ @@ -267,9 +266,8 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) { goto out; } - payload = ukey->payload.data; - p = payload->data; - err = ceph_crypto_key_decode(dst, &p, p + payload->datalen); + ckey = ukey->payload.data; + err = ceph_crypto_key_clone(dst, ckey); if (err) goto out_key; /* pass through, err is 0 */ @@ -583,10 +581,14 @@ static int __init init_ceph_lib(void) if (ret < 0) goto out; - ret = ceph_msgr_init(); + ret = ceph_crypto_init(); if (ret < 0) goto out_debugfs; + ret = ceph_msgr_init(); + if (ret < 0) + goto out_crypto; + pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, @@ -594,6 +596,8 @@ static int __init init_ceph_lib(void) return 0; +out_crypto: + ceph_crypto_shutdown(); out_debugfs: ceph_debugfs_cleanup(); out: @@ -604,6 +608,7 @@ static void __exit exit_ceph_lib(void) { dout("exit_ceph_lib\n"); ceph_msgr_exit(); + ceph_crypto_shutdown(); ceph_debugfs_cleanup(); } diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 75f0893fa11f..5a8009c9e0cd 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -5,7 +5,9 @@ #include <linux/scatterlist.h> #include <linux/slab.h> #include <crypto/hash.h> +#include <linux/key-type.h> +#include <keys/ceph-type.h> #include <linux/ceph/decode.h> #include "crypto.h" @@ -421,3 +423,63 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, return -EINVAL; } } + +int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) +{ + struct ceph_crypto_key *ckey; + int ret; + void *p; + + ret = -EINVAL; + if (datalen <= 0 || datalen > 32767 || !data) + goto err; + + ret = key_payload_reserve(key, datalen); + if (ret < 0) + goto err; + + ret = -ENOMEM; + ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); + if (!ckey) + goto err; + + /* TODO ceph_crypto_key_decode should really take const input */ + p = (void*)data; + ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); + if (ret < 0) + goto err_ckey; + + key->payload.data = ckey; + return 0; + +err_ckey: + kfree(ckey); +err: + return ret; +} + +int ceph_key_match(const struct key *key, const void *description) +{ + return strcmp(key->description, description) == 0; +} + +void ceph_key_destroy(struct key *key) { + struct ceph_crypto_key *ckey = key->payload.data; + + ceph_crypto_key_destroy(ckey); +} + +struct key_type key_type_ceph = { + .name = "ceph", + .instantiate = ceph_key_instantiate, + .match = ceph_key_match, + .destroy = ceph_key_destroy, +}; + +int ceph_crypto_init(void) { + return register_key_type(&key_type_ceph); +} + +void ceph_crypto_shutdown(void) { + unregister_key_type(&key_type_ceph); +} diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 6cf6edc91ec4..1919d1550d75 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -42,6 +42,8 @@ extern int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, const void *src1, size_t src1_len, const void *src2, size_t src2_len); +extern int ceph_crypto_init(void); +extern void ceph_crypto_shutdown(void); /* armor.c */ extern int ceph_armor(char *dst, const char *src, const char *end); |