Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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  * get protocol handler
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  * setup, teardown.
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  * Reset occurs when reconnecting to the monitor.
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  * EntityName, not to be confused with entity_name_t
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  * Initiate protocol negotiation with monitor.  Include entity name
0119  * and list supported protocols.
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);  /* no protocol, yet */
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         /* struct ceph_mon_request_header + protocol */
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  * Handle auth message from monitor.
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         /* server does not support our protocols? */
0236         if (!protocol && result < 0) {
0237             ret = result;
0238             goto out;
0239         }
0240         /* set up (new) protocol handler? */
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  * msgr2 authentication
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  * Similar to ceph_auth_build_hello().
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;  /* space for len */
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);