0001
0002 #include <linux/ceph/ceph_debug.h>
0003
0004 #include <linux/module.h>
0005 #include <linux/err.h>
0006 #include <linux/slab.h>
0007
0008 #include <linux/ceph/types.h>
0009 #include <linux/ceph/decode.h>
0010 #include <linux/ceph/libceph.h>
0011 #include <linux/ceph/messenger.h>
0012 #include "auth_none.h"
0013 #include "auth_x.h"
0014
0015
0016
0017
0018
0019 static u32 supported_protocols[] = {
0020 CEPH_AUTH_NONE,
0021 CEPH_AUTH_CEPHX
0022 };
0023
0024 static int init_protocol(struct ceph_auth_client *ac, int proto)
0025 {
0026 dout("%s proto %d\n", __func__, proto);
0027
0028 switch (proto) {
0029 case CEPH_AUTH_NONE:
0030 return ceph_auth_none_init(ac);
0031 case CEPH_AUTH_CEPHX:
0032 return ceph_x_init(ac);
0033 default:
0034 pr_err("bad auth protocol %d\n", proto);
0035 return -EINVAL;
0036 }
0037 }
0038
0039 void ceph_auth_set_global_id(struct ceph_auth_client *ac, u64 global_id)
0040 {
0041 dout("%s global_id %llu\n", __func__, global_id);
0042
0043 if (!global_id)
0044 pr_err("got zero global_id\n");
0045
0046 if (ac->global_id && global_id != ac->global_id)
0047 pr_err("global_id changed from %llu to %llu\n", ac->global_id,
0048 global_id);
0049
0050 ac->global_id = global_id;
0051 }
0052
0053
0054
0055
0056 struct ceph_auth_client *ceph_auth_init(const char *name,
0057 const struct ceph_crypto_key *key,
0058 const int *con_modes)
0059 {
0060 struct ceph_auth_client *ac;
0061
0062 ac = kzalloc(sizeof(*ac), GFP_NOFS);
0063 if (!ac)
0064 return ERR_PTR(-ENOMEM);
0065
0066 mutex_init(&ac->mutex);
0067 ac->negotiating = true;
0068 if (name)
0069 ac->name = name;
0070 else
0071 ac->name = CEPH_AUTH_NAME_DEFAULT;
0072 ac->key = key;
0073 ac->preferred_mode = con_modes[0];
0074 ac->fallback_mode = con_modes[1];
0075
0076 dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__,
0077 ac->name, ac->preferred_mode, ac->fallback_mode);
0078 return ac;
0079 }
0080
0081 void ceph_auth_destroy(struct ceph_auth_client *ac)
0082 {
0083 dout("auth_destroy %p\n", ac);
0084 if (ac->ops)
0085 ac->ops->destroy(ac);
0086 kfree(ac);
0087 }
0088
0089
0090
0091
0092 void ceph_auth_reset(struct ceph_auth_client *ac)
0093 {
0094 mutex_lock(&ac->mutex);
0095 dout("auth_reset %p\n", ac);
0096 if (ac->ops && !ac->negotiating)
0097 ac->ops->reset(ac);
0098 ac->negotiating = true;
0099 mutex_unlock(&ac->mutex);
0100 }
0101
0102
0103
0104
0105 int ceph_auth_entity_name_encode(const char *name, void **p, void *end)
0106 {
0107 int len = strlen(name);
0108
0109 if (*p + 2*sizeof(u32) + len > end)
0110 return -ERANGE;
0111 ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
0112 ceph_encode_32(p, len);
0113 ceph_encode_copy(p, name, len);
0114 return 0;
0115 }
0116
0117
0118
0119
0120
0121 int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
0122 {
0123 struct ceph_mon_request_header *monhdr = buf;
0124 void *p = monhdr + 1, *end = buf + len, *lenp;
0125 int i, num;
0126 int ret;
0127
0128 mutex_lock(&ac->mutex);
0129 dout("auth_build_hello\n");
0130 monhdr->have_version = 0;
0131 monhdr->session_mon = cpu_to_le16(-1);
0132 monhdr->session_mon_tid = 0;
0133
0134 ceph_encode_32(&p, CEPH_AUTH_UNKNOWN);
0135
0136 lenp = p;
0137 p += sizeof(u32);
0138
0139 ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
0140 ceph_encode_8(&p, 1);
0141 num = ARRAY_SIZE(supported_protocols);
0142 ceph_encode_32(&p, num);
0143 ceph_decode_need(&p, end, num * sizeof(u32), bad);
0144 for (i = 0; i < num; i++)
0145 ceph_encode_32(&p, supported_protocols[i]);
0146
0147 ret = ceph_auth_entity_name_encode(ac->name, &p, end);
0148 if (ret < 0)
0149 goto out;
0150 ceph_decode_need(&p, end, sizeof(u64), bad);
0151 ceph_encode_64(&p, ac->global_id);
0152
0153 ceph_encode_32(&lenp, p - lenp - sizeof(u32));
0154 ret = p - buf;
0155 out:
0156 mutex_unlock(&ac->mutex);
0157 return ret;
0158
0159 bad:
0160 ret = -ERANGE;
0161 goto out;
0162 }
0163
0164 static int build_request(struct ceph_auth_client *ac, bool add_header,
0165 void *buf, int buf_len)
0166 {
0167 void *end = buf + buf_len;
0168 void *p;
0169 int ret;
0170
0171 p = buf;
0172 if (add_header) {
0173
0174 ceph_encode_64_safe(&p, end, 0, e_range);
0175 ceph_encode_16_safe(&p, end, -1, e_range);
0176 ceph_encode_64_safe(&p, end, 0, e_range);
0177 ceph_encode_32_safe(&p, end, ac->protocol, e_range);
0178 }
0179
0180 ceph_encode_need(&p, end, sizeof(u32), e_range);
0181 ret = ac->ops->build_request(ac, p + sizeof(u32), end);
0182 if (ret < 0) {
0183 pr_err("auth protocol '%s' building request failed: %d\n",
0184 ceph_auth_proto_name(ac->protocol), ret);
0185 return ret;
0186 }
0187 dout(" built request %d bytes\n", ret);
0188 ceph_encode_32(&p, ret);
0189 return p + ret - buf;
0190
0191 e_range:
0192 return -ERANGE;
0193 }
0194
0195
0196
0197
0198 int ceph_handle_auth_reply(struct ceph_auth_client *ac,
0199 void *buf, size_t len,
0200 void *reply_buf, size_t reply_len)
0201 {
0202 void *p = buf;
0203 void *end = buf + len;
0204 int protocol;
0205 s32 result;
0206 u64 global_id;
0207 void *payload, *payload_end;
0208 int payload_len;
0209 char *result_msg;
0210 int result_msg_len;
0211 int ret = -EINVAL;
0212
0213 mutex_lock(&ac->mutex);
0214 dout("handle_auth_reply %p %p\n", p, end);
0215 ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
0216 protocol = ceph_decode_32(&p);
0217 result = ceph_decode_32(&p);
0218 global_id = ceph_decode_64(&p);
0219 payload_len = ceph_decode_32(&p);
0220 payload = p;
0221 p += payload_len;
0222 ceph_decode_need(&p, end, sizeof(u32), bad);
0223 result_msg_len = ceph_decode_32(&p);
0224 result_msg = p;
0225 p += result_msg_len;
0226 if (p != end)
0227 goto bad;
0228
0229 dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
0230 result_msg, global_id, payload_len);
0231
0232 payload_end = payload + payload_len;
0233
0234 if (ac->negotiating) {
0235
0236 if (!protocol && result < 0) {
0237 ret = result;
0238 goto out;
0239 }
0240
0241 if (ac->protocol && ac->protocol != protocol) {
0242 ac->ops->destroy(ac);
0243 ac->protocol = 0;
0244 ac->ops = NULL;
0245 }
0246 if (ac->protocol != protocol) {
0247 ret = init_protocol(ac, protocol);
0248 if (ret) {
0249 pr_err("auth protocol '%s' init failed: %d\n",
0250 ceph_auth_proto_name(protocol), ret);
0251 goto out;
0252 }
0253 }
0254
0255 ac->negotiating = false;
0256 }
0257
0258 if (result) {
0259 pr_err("auth protocol '%s' mauth authentication failed: %d\n",
0260 ceph_auth_proto_name(ac->protocol), result);
0261 ret = result;
0262 goto out;
0263 }
0264
0265 ret = ac->ops->handle_reply(ac, global_id, payload, payload_end,
0266 NULL, NULL, NULL, NULL);
0267 if (ret == -EAGAIN) {
0268 ret = build_request(ac, true, reply_buf, reply_len);
0269 goto out;
0270 } else if (ret) {
0271 goto out;
0272 }
0273
0274 out:
0275 mutex_unlock(&ac->mutex);
0276 return ret;
0277
0278 bad:
0279 pr_err("failed to decode auth msg\n");
0280 ret = -EINVAL;
0281 goto out;
0282 }
0283
0284 int ceph_build_auth(struct ceph_auth_client *ac,
0285 void *msg_buf, size_t msg_len)
0286 {
0287 int ret = 0;
0288
0289 mutex_lock(&ac->mutex);
0290 if (ac->ops->should_authenticate(ac))
0291 ret = build_request(ac, true, msg_buf, msg_len);
0292 mutex_unlock(&ac->mutex);
0293 return ret;
0294 }
0295
0296 int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
0297 {
0298 int ret = 0;
0299
0300 mutex_lock(&ac->mutex);
0301 if (ac->ops)
0302 ret = ac->ops->is_authenticated(ac);
0303 mutex_unlock(&ac->mutex);
0304 return ret;
0305 }
0306 EXPORT_SYMBOL(ceph_auth_is_authenticated);
0307
0308 int __ceph_auth_get_authorizer(struct ceph_auth_client *ac,
0309 struct ceph_auth_handshake *auth,
0310 int peer_type, bool force_new,
0311 int *proto, int *pref_mode, int *fallb_mode)
0312 {
0313 int ret;
0314
0315 mutex_lock(&ac->mutex);
0316 if (force_new && auth->authorizer) {
0317 ceph_auth_destroy_authorizer(auth->authorizer);
0318 auth->authorizer = NULL;
0319 }
0320 if (!auth->authorizer)
0321 ret = ac->ops->create_authorizer(ac, peer_type, auth);
0322 else if (ac->ops->update_authorizer)
0323 ret = ac->ops->update_authorizer(ac, peer_type, auth);
0324 else
0325 ret = 0;
0326 if (ret)
0327 goto out;
0328
0329 *proto = ac->protocol;
0330 if (pref_mode && fallb_mode) {
0331 *pref_mode = ac->preferred_mode;
0332 *fallb_mode = ac->fallback_mode;
0333 }
0334
0335 out:
0336 mutex_unlock(&ac->mutex);
0337 return ret;
0338 }
0339 EXPORT_SYMBOL(__ceph_auth_get_authorizer);
0340
0341 void ceph_auth_destroy_authorizer(struct ceph_authorizer *a)
0342 {
0343 a->destroy(a);
0344 }
0345 EXPORT_SYMBOL(ceph_auth_destroy_authorizer);
0346
0347 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac,
0348 struct ceph_authorizer *a,
0349 void *challenge_buf,
0350 int challenge_buf_len)
0351 {
0352 int ret = 0;
0353
0354 mutex_lock(&ac->mutex);
0355 if (ac->ops && ac->ops->add_authorizer_challenge)
0356 ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf,
0357 challenge_buf_len);
0358 mutex_unlock(&ac->mutex);
0359 return ret;
0360 }
0361 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge);
0362
0363 int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
0364 struct ceph_authorizer *a,
0365 void *reply, int reply_len,
0366 u8 *session_key, int *session_key_len,
0367 u8 *con_secret, int *con_secret_len)
0368 {
0369 int ret = 0;
0370
0371 mutex_lock(&ac->mutex);
0372 if (ac->ops && ac->ops->verify_authorizer_reply)
0373 ret = ac->ops->verify_authorizer_reply(ac, a,
0374 reply, reply_len, session_key, session_key_len,
0375 con_secret, con_secret_len);
0376 mutex_unlock(&ac->mutex);
0377 return ret;
0378 }
0379 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply);
0380
0381 void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type)
0382 {
0383 mutex_lock(&ac->mutex);
0384 if (ac->ops && ac->ops->invalidate_authorizer)
0385 ac->ops->invalidate_authorizer(ac, peer_type);
0386 mutex_unlock(&ac->mutex);
0387 }
0388 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
0389
0390
0391
0392
0393
0394 static bool contains(const int *arr, int cnt, int val)
0395 {
0396 int i;
0397
0398 for (i = 0; i < cnt; i++) {
0399 if (arr[i] == val)
0400 return true;
0401 }
0402
0403 return false;
0404 }
0405
0406 static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode)
0407 {
0408 WARN_ON(pref_mode == CEPH_CON_MODE_UNKNOWN);
0409 if (fallb_mode != CEPH_CON_MODE_UNKNOWN) {
0410 ceph_encode_32_safe(p, end, 2, e_range);
0411 ceph_encode_32_safe(p, end, pref_mode, e_range);
0412 ceph_encode_32_safe(p, end, fallb_mode, e_range);
0413 } else {
0414 ceph_encode_32_safe(p, end, 1, e_range);
0415 ceph_encode_32_safe(p, end, pref_mode, e_range);
0416 }
0417
0418 return 0;
0419
0420 e_range:
0421 return -ERANGE;
0422 }
0423
0424
0425
0426
0427 int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len)
0428 {
0429 int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE;
0430 void *end = buf + buf_len;
0431 void *lenp;
0432 void *p;
0433 int ret;
0434
0435 mutex_lock(&ac->mutex);
0436 if (ac->protocol == CEPH_AUTH_UNKNOWN) {
0437 ret = init_protocol(ac, proto);
0438 if (ret) {
0439 pr_err("auth protocol '%s' init failed: %d\n",
0440 ceph_auth_proto_name(proto), ret);
0441 goto out;
0442 }
0443 } else {
0444 WARN_ON(ac->protocol != proto);
0445 ac->ops->reset(ac);
0446 }
0447
0448 p = buf;
0449 ceph_encode_32_safe(&p, end, ac->protocol, e_range);
0450 ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode);
0451 if (ret)
0452 goto out;
0453
0454 lenp = p;
0455 p += 4;
0456
0457 ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range);
0458 ret = ceph_auth_entity_name_encode(ac->name, &p, end);
0459 if (ret)
0460 goto out;
0461
0462 ceph_encode_64_safe(&p, end, ac->global_id, e_range);
0463 ceph_encode_32(&lenp, p - lenp - 4);
0464 ret = p - buf;
0465
0466 out:
0467 mutex_unlock(&ac->mutex);
0468 return ret;
0469
0470 e_range:
0471 ret = -ERANGE;
0472 goto out;
0473 }
0474
0475 int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply,
0476 int reply_len, void *buf, int buf_len)
0477 {
0478 int ret;
0479
0480 mutex_lock(&ac->mutex);
0481 ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len,
0482 NULL, NULL, NULL, NULL);
0483 if (ret == -EAGAIN)
0484 ret = build_request(ac, false, buf, buf_len);
0485 else
0486 WARN_ON(ret >= 0);
0487 mutex_unlock(&ac->mutex);
0488 return ret;
0489 }
0490
0491 int ceph_auth_handle_reply_done(struct ceph_auth_client *ac,
0492 u64 global_id, void *reply, int reply_len,
0493 u8 *session_key, int *session_key_len,
0494 u8 *con_secret, int *con_secret_len)
0495 {
0496 int ret;
0497
0498 mutex_lock(&ac->mutex);
0499 ret = ac->ops->handle_reply(ac, global_id, reply, reply + reply_len,
0500 session_key, session_key_len,
0501 con_secret, con_secret_len);
0502 WARN_ON(ret == -EAGAIN || ret > 0);
0503 mutex_unlock(&ac->mutex);
0504 return ret;
0505 }
0506
0507 bool ceph_auth_handle_bad_method(struct ceph_auth_client *ac,
0508 int used_proto, int result,
0509 const int *allowed_protos, int proto_cnt,
0510 const int *allowed_modes, int mode_cnt)
0511 {
0512 mutex_lock(&ac->mutex);
0513 WARN_ON(used_proto != ac->protocol);
0514
0515 if (result == -EOPNOTSUPP) {
0516 if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
0517 pr_err("auth protocol '%s' not allowed\n",
0518 ceph_auth_proto_name(ac->protocol));
0519 goto not_allowed;
0520 }
0521 if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
0522 (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
0523 !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
0524 pr_err("preferred mode '%s' not allowed\n",
0525 ceph_con_mode_name(ac->preferred_mode));
0526 if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
0527 pr_err("no fallback mode\n");
0528 else
0529 pr_err("fallback mode '%s' not allowed\n",
0530 ceph_con_mode_name(ac->fallback_mode));
0531 goto not_allowed;
0532 }
0533 }
0534
0535 WARN_ON(result == -EOPNOTSUPP || result >= 0);
0536 pr_err("auth protocol '%s' msgr authentication failed: %d\n",
0537 ceph_auth_proto_name(ac->protocol), result);
0538
0539 mutex_unlock(&ac->mutex);
0540 return true;
0541
0542 not_allowed:
0543 mutex_unlock(&ac->mutex);
0544 return false;
0545 }
0546
0547 int ceph_auth_get_authorizer(struct ceph_auth_client *ac,
0548 struct ceph_auth_handshake *auth,
0549 int peer_type, void *buf, int *buf_len)
0550 {
0551 void *end = buf + *buf_len;
0552 int pref_mode, fallb_mode;
0553 int proto;
0554 void *p;
0555 int ret;
0556
0557 ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto,
0558 &pref_mode, &fallb_mode);
0559 if (ret)
0560 return ret;
0561
0562 p = buf;
0563 ceph_encode_32_safe(&p, end, proto, e_range);
0564 ret = encode_con_modes(&p, end, pref_mode, fallb_mode);
0565 if (ret)
0566 return ret;
0567
0568 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
0569 *buf_len = p - buf;
0570 return 0;
0571
0572 e_range:
0573 return -ERANGE;
0574 }
0575 EXPORT_SYMBOL(ceph_auth_get_authorizer);
0576
0577 int ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac,
0578 struct ceph_auth_handshake *auth,
0579 void *reply, int reply_len,
0580 void *buf, int *buf_len)
0581 {
0582 void *end = buf + *buf_len;
0583 void *p;
0584 int ret;
0585
0586 ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer,
0587 reply, reply_len);
0588 if (ret)
0589 return ret;
0590
0591 p = buf;
0592 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
0593 *buf_len = p - buf;
0594 return 0;
0595
0596 e_range:
0597 return -ERANGE;
0598 }
0599 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more);
0600
0601 int ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac,
0602 struct ceph_auth_handshake *auth,
0603 void *reply, int reply_len,
0604 u8 *session_key, int *session_key_len,
0605 u8 *con_secret, int *con_secret_len)
0606 {
0607 return ceph_auth_verify_authorizer_reply(ac, auth->authorizer,
0608 reply, reply_len, session_key, session_key_len,
0609 con_secret, con_secret_len);
0610 }
0611 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done);
0612
0613 bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac,
0614 int peer_type, int used_proto, int result,
0615 const int *allowed_protos, int proto_cnt,
0616 const int *allowed_modes, int mode_cnt)
0617 {
0618 mutex_lock(&ac->mutex);
0619 WARN_ON(used_proto != ac->protocol);
0620
0621 if (result == -EOPNOTSUPP) {
0622 if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
0623 pr_err("auth protocol '%s' not allowed by %s\n",
0624 ceph_auth_proto_name(ac->protocol),
0625 ceph_entity_type_name(peer_type));
0626 goto not_allowed;
0627 }
0628 if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
0629 (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
0630 !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
0631 pr_err("preferred mode '%s' not allowed by %s\n",
0632 ceph_con_mode_name(ac->preferred_mode),
0633 ceph_entity_type_name(peer_type));
0634 if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
0635 pr_err("no fallback mode\n");
0636 else
0637 pr_err("fallback mode '%s' not allowed by %s\n",
0638 ceph_con_mode_name(ac->fallback_mode),
0639 ceph_entity_type_name(peer_type));
0640 goto not_allowed;
0641 }
0642 }
0643
0644 WARN_ON(result == -EOPNOTSUPP || result >= 0);
0645 pr_err("auth protocol '%s' authorization to %s failed: %d\n",
0646 ceph_auth_proto_name(ac->protocol),
0647 ceph_entity_type_name(peer_type), result);
0648
0649 if (ac->ops->invalidate_authorizer)
0650 ac->ops->invalidate_authorizer(ac, peer_type);
0651
0652 mutex_unlock(&ac->mutex);
0653 return true;
0654
0655 not_allowed:
0656 mutex_unlock(&ac->mutex);
0657 return false;
0658 }
0659 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer);