diff options
Diffstat (limited to 'net/ceph/ceph_common.c')
| -rw-r--r-- | net/ceph/ceph_common.c | 112 |
1 files changed, 102 insertions, 10 deletions
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 95f96ab94bba..132963abc266 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <linux/fs.h> | 5 | #include <linux/fs.h> |
| 6 | #include <linux/inet.h> | 6 | #include <linux/inet.h> |
| 7 | #include <linux/in6.h> | 7 | #include <linux/in6.h> |
| 8 | #include <linux/key.h> | ||
| 9 | #include <keys/ceph-type.h> | ||
| 8 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 9 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
| 10 | #include <linux/parser.h> | 12 | #include <linux/parser.h> |
| @@ -20,6 +22,7 @@ | |||
| 20 | #include <linux/ceph/decode.h> | 22 | #include <linux/ceph/decode.h> |
| 21 | #include <linux/ceph/mon_client.h> | 23 | #include <linux/ceph/mon_client.h> |
| 22 | #include <linux/ceph/auth.h> | 24 | #include <linux/ceph/auth.h> |
| 25 | #include "crypto.h" | ||
| 23 | 26 | ||
| 24 | 27 | ||
| 25 | 28 | ||
| @@ -117,9 +120,29 @@ int ceph_compare_options(struct ceph_options *new_opt, | |||
| 117 | if (ret) | 120 | if (ret) |
| 118 | return ret; | 121 | return ret; |
| 119 | 122 | ||
| 120 | ret = strcmp_null(opt1->secret, opt2->secret); | 123 | if (opt1->key && !opt2->key) |
| 121 | if (ret) | 124 | return -1; |
| 122 | return ret; | 125 | if (!opt1->key && opt2->key) |
| 126 | return 1; | ||
| 127 | if (opt1->key && opt2->key) { | ||
| 128 | if (opt1->key->type != opt2->key->type) | ||
| 129 | return -1; | ||
| 130 | if (opt1->key->created.tv_sec != opt2->key->created.tv_sec) | ||
| 131 | return -1; | ||
| 132 | if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec) | ||
| 133 | return -1; | ||
| 134 | if (opt1->key->len != opt2->key->len) | ||
| 135 | return -1; | ||
| 136 | if (opt1->key->key && !opt2->key->key) | ||
| 137 | return -1; | ||
| 138 | if (!opt1->key->key && opt2->key->key) | ||
| 139 | return 1; | ||
| 140 | if (opt1->key->key && opt2->key->key) { | ||
| 141 | ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len); | ||
| 142 | if (ret) | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | } | ||
| 123 | 146 | ||
| 124 | /* any matching mon ip implies a match */ | 147 | /* any matching mon ip implies a match */ |
| 125 | for (i = 0; i < opt1->num_mon; i++) { | 148 | for (i = 0; i < opt1->num_mon; i++) { |
| @@ -176,6 +199,7 @@ enum { | |||
| 176 | Opt_fsid, | 199 | Opt_fsid, |
| 177 | Opt_name, | 200 | Opt_name, |
| 178 | Opt_secret, | 201 | Opt_secret, |
| 202 | Opt_key, | ||
| 179 | Opt_ip, | 203 | Opt_ip, |
| 180 | Opt_last_string, | 204 | Opt_last_string, |
| 181 | /* string args above */ | 205 | /* string args above */ |
| @@ -192,6 +216,7 @@ static match_table_t opt_tokens = { | |||
| 192 | {Opt_fsid, "fsid=%s"}, | 216 | {Opt_fsid, "fsid=%s"}, |
| 193 | {Opt_name, "name=%s"}, | 217 | {Opt_name, "name=%s"}, |
| 194 | {Opt_secret, "secret=%s"}, | 218 | {Opt_secret, "secret=%s"}, |
| 219 | {Opt_key, "key=%s"}, | ||
| 195 | {Opt_ip, "ip=%s"}, | 220 | {Opt_ip, "ip=%s"}, |
| 196 | /* string args above */ | 221 | /* string args above */ |
| 197 | {Opt_noshare, "noshare"}, | 222 | {Opt_noshare, "noshare"}, |
| @@ -203,11 +228,56 @@ void ceph_destroy_options(struct ceph_options *opt) | |||
| 203 | { | 228 | { |
| 204 | dout("destroy_options %p\n", opt); | 229 | dout("destroy_options %p\n", opt); |
| 205 | kfree(opt->name); | 230 | kfree(opt->name); |
| 206 | kfree(opt->secret); | 231 | if (opt->key) { |
| 232 | ceph_crypto_key_destroy(opt->key); | ||
| 233 | kfree(opt->key); | ||
| 234 | } | ||
| 207 | kfree(opt); | 235 | kfree(opt); |
| 208 | } | 236 | } |
| 209 | EXPORT_SYMBOL(ceph_destroy_options); | 237 | EXPORT_SYMBOL(ceph_destroy_options); |
| 210 | 238 | ||
| 239 | /* get secret from key store */ | ||
| 240 | static int get_secret(struct ceph_crypto_key *dst, const char *name) { | ||
| 241 | struct key *ukey; | ||
| 242 | int key_err; | ||
| 243 | int err = 0; | ||
| 244 | struct ceph_crypto_key *ckey; | ||
| 245 | |||
| 246 | ukey = request_key(&key_type_ceph, name, NULL); | ||
| 247 | if (!ukey || IS_ERR(ukey)) { | ||
| 248 | /* request_key errors don't map nicely to mount(2) | ||
| 249 | errors; don't even try, but still printk */ | ||
| 250 | key_err = PTR_ERR(ukey); | ||
| 251 | switch (key_err) { | ||
| 252 | case -ENOKEY: | ||
| 253 | pr_warning("ceph: Mount failed due to key not found: %s\n", name); | ||
| 254 | break; | ||
| 255 | case -EKEYEXPIRED: | ||
| 256 | pr_warning("ceph: Mount failed due to expired key: %s\n", name); | ||
| 257 | break; | ||
| 258 | case -EKEYREVOKED: | ||
| 259 | pr_warning("ceph: Mount failed due to revoked key: %s\n", name); | ||
| 260 | break; | ||
| 261 | default: | ||
| 262 | pr_warning("ceph: Mount failed due to unknown key error" | ||
| 263 | " %d: %s\n", key_err, name); | ||
| 264 | } | ||
| 265 | err = -EPERM; | ||
| 266 | goto out; | ||
| 267 | } | ||
| 268 | |||
| 269 | ckey = ukey->payload.data; | ||
| 270 | err = ceph_crypto_key_clone(dst, ckey); | ||
| 271 | if (err) | ||
| 272 | goto out_key; | ||
| 273 | /* pass through, err is 0 */ | ||
| 274 | |||
| 275 | out_key: | ||
| 276 | key_put(ukey); | ||
| 277 | out: | ||
| 278 | return err; | ||
| 279 | } | ||
| 280 | |||
| 211 | int ceph_parse_options(struct ceph_options **popt, char *options, | 281 | int ceph_parse_options(struct ceph_options **popt, char *options, |
| 212 | const char *dev_name, const char *dev_name_end, | 282 | const char *dev_name, const char *dev_name_end, |
| 213 | int (*parse_extra_token)(char *c, void *private), | 283 | int (*parse_extra_token)(char *c, void *private), |
| @@ -295,9 +365,24 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
| 295 | GFP_KERNEL); | 365 | GFP_KERNEL); |
| 296 | break; | 366 | break; |
| 297 | case Opt_secret: | 367 | case Opt_secret: |
| 298 | opt->secret = kstrndup(argstr[0].from, | 368 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
| 299 | argstr[0].to-argstr[0].from, | 369 | if (!opt->key) { |
| 300 | GFP_KERNEL); | 370 | err = -ENOMEM; |
| 371 | goto out; | ||
| 372 | } | ||
| 373 | err = ceph_crypto_key_unarmor(opt->key, argstr[0].from); | ||
| 374 | if (err < 0) | ||
| 375 | goto out; | ||
| 376 | break; | ||
| 377 | case Opt_key: | ||
| 378 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); | ||
| 379 | if (!opt->key) { | ||
| 380 | err = -ENOMEM; | ||
| 381 | goto out; | ||
| 382 | } | ||
| 383 | err = get_secret(opt->key, argstr[0].from); | ||
| 384 | if (err < 0) | ||
| 385 | goto out; | ||
| 301 | break; | 386 | break; |
| 302 | 387 | ||
| 303 | /* misc */ | 388 | /* misc */ |
| @@ -394,8 +479,8 @@ void ceph_destroy_client(struct ceph_client *client) | |||
| 394 | ceph_osdc_stop(&client->osdc); | 479 | ceph_osdc_stop(&client->osdc); |
| 395 | 480 | ||
| 396 | /* | 481 | /* |
| 397 | * make sure mds and osd connections close out before destroying | 482 | * make sure osd connections close out before destroying the |
| 398 | * the auth module, which is needed to free those connections' | 483 | * auth module, which is needed to free those connections' |
| 399 | * ceph_authorizers. | 484 | * ceph_authorizers. |
| 400 | */ | 485 | */ |
| 401 | ceph_msgr_flush(); | 486 | ceph_msgr_flush(); |
| @@ -496,10 +581,14 @@ static int __init init_ceph_lib(void) | |||
| 496 | if (ret < 0) | 581 | if (ret < 0) |
| 497 | goto out; | 582 | goto out; |
| 498 | 583 | ||
| 499 | ret = ceph_msgr_init(); | 584 | ret = ceph_crypto_init(); |
| 500 | if (ret < 0) | 585 | if (ret < 0) |
| 501 | goto out_debugfs; | 586 | goto out_debugfs; |
| 502 | 587 | ||
| 588 | ret = ceph_msgr_init(); | ||
| 589 | if (ret < 0) | ||
| 590 | goto out_crypto; | ||
| 591 | |||
| 503 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", | 592 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", |
| 504 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, | 593 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, |
| 505 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, | 594 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, |
| @@ -507,6 +596,8 @@ static int __init init_ceph_lib(void) | |||
| 507 | 596 | ||
| 508 | return 0; | 597 | return 0; |
| 509 | 598 | ||
| 599 | out_crypto: | ||
| 600 | ceph_crypto_shutdown(); | ||
| 510 | out_debugfs: | 601 | out_debugfs: |
| 511 | ceph_debugfs_cleanup(); | 602 | ceph_debugfs_cleanup(); |
| 512 | out: | 603 | out: |
| @@ -517,6 +608,7 @@ static void __exit exit_ceph_lib(void) | |||
| 517 | { | 608 | { |
| 518 | dout("exit_ceph_lib\n"); | 609 | dout("exit_ceph_lib\n"); |
| 519 | ceph_msgr_exit(); | 610 | ceph_msgr_exit(); |
| 611 | ceph_crypto_shutdown(); | ||
| 520 | ceph_debugfs_cleanup(); | 612 | ceph_debugfs_cleanup(); |
| 521 | } | 613 | } |
| 522 | 614 | ||
