162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/ceph/ceph_debug.h> 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/module.h> 562306a36Sopenharmony_ci#include <linux/err.h> 662306a36Sopenharmony_ci#include <linux/slab.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/ceph/types.h> 962306a36Sopenharmony_ci#include <linux/ceph/decode.h> 1062306a36Sopenharmony_ci#include <linux/ceph/libceph.h> 1162306a36Sopenharmony_ci#include <linux/ceph/messenger.h> 1262306a36Sopenharmony_ci#include "auth_none.h" 1362306a36Sopenharmony_ci#include "auth_x.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* 1762306a36Sopenharmony_ci * get protocol handler 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_cistatic u32 supported_protocols[] = { 2062306a36Sopenharmony_ci CEPH_AUTH_NONE, 2162306a36Sopenharmony_ci CEPH_AUTH_CEPHX 2262306a36Sopenharmony_ci}; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic int init_protocol(struct ceph_auth_client *ac, int proto) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci dout("%s proto %d\n", __func__, proto); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci switch (proto) { 2962306a36Sopenharmony_ci case CEPH_AUTH_NONE: 3062306a36Sopenharmony_ci return ceph_auth_none_init(ac); 3162306a36Sopenharmony_ci case CEPH_AUTH_CEPHX: 3262306a36Sopenharmony_ci return ceph_x_init(ac); 3362306a36Sopenharmony_ci default: 3462306a36Sopenharmony_ci pr_err("bad auth protocol %d\n", proto); 3562306a36Sopenharmony_ci return -EINVAL; 3662306a36Sopenharmony_ci } 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_civoid ceph_auth_set_global_id(struct ceph_auth_client *ac, u64 global_id) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci dout("%s global_id %llu\n", __func__, global_id); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (!global_id) 4462306a36Sopenharmony_ci pr_err("got zero global_id\n"); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (ac->global_id && global_id != ac->global_id) 4762306a36Sopenharmony_ci pr_err("global_id changed from %llu to %llu\n", ac->global_id, 4862306a36Sopenharmony_ci global_id); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci ac->global_id = global_id; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * setup, teardown. 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_cistruct ceph_auth_client *ceph_auth_init(const char *name, 5762306a36Sopenharmony_ci const struct ceph_crypto_key *key, 5862306a36Sopenharmony_ci const int *con_modes) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct ceph_auth_client *ac; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci ac = kzalloc(sizeof(*ac), GFP_NOFS); 6362306a36Sopenharmony_ci if (!ac) 6462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci mutex_init(&ac->mutex); 6762306a36Sopenharmony_ci ac->negotiating = true; 6862306a36Sopenharmony_ci if (name) 6962306a36Sopenharmony_ci ac->name = name; 7062306a36Sopenharmony_ci else 7162306a36Sopenharmony_ci ac->name = CEPH_AUTH_NAME_DEFAULT; 7262306a36Sopenharmony_ci ac->key = key; 7362306a36Sopenharmony_ci ac->preferred_mode = con_modes[0]; 7462306a36Sopenharmony_ci ac->fallback_mode = con_modes[1]; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__, 7762306a36Sopenharmony_ci ac->name, ac->preferred_mode, ac->fallback_mode); 7862306a36Sopenharmony_ci return ac; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_civoid ceph_auth_destroy(struct ceph_auth_client *ac) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci dout("auth_destroy %p\n", ac); 8462306a36Sopenharmony_ci if (ac->ops) 8562306a36Sopenharmony_ci ac->ops->destroy(ac); 8662306a36Sopenharmony_ci kfree(ac); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * Reset occurs when reconnecting to the monitor. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_civoid ceph_auth_reset(struct ceph_auth_client *ac) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci mutex_lock(&ac->mutex); 9562306a36Sopenharmony_ci dout("auth_reset %p\n", ac); 9662306a36Sopenharmony_ci if (ac->ops && !ac->negotiating) 9762306a36Sopenharmony_ci ac->ops->reset(ac); 9862306a36Sopenharmony_ci ac->negotiating = true; 9962306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* 10362306a36Sopenharmony_ci * EntityName, not to be confused with entity_name_t 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ciint ceph_auth_entity_name_encode(const char *name, void **p, void *end) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci int len = strlen(name); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (*p + 2*sizeof(u32) + len > end) 11062306a36Sopenharmony_ci return -ERANGE; 11162306a36Sopenharmony_ci ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT); 11262306a36Sopenharmony_ci ceph_encode_32(p, len); 11362306a36Sopenharmony_ci ceph_encode_copy(p, name, len); 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* 11862306a36Sopenharmony_ci * Initiate protocol negotiation with monitor. Include entity name 11962306a36Sopenharmony_ci * and list supported protocols. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ciint ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct ceph_mon_request_header *monhdr = buf; 12462306a36Sopenharmony_ci void *p = monhdr + 1, *end = buf + len, *lenp; 12562306a36Sopenharmony_ci int i, num; 12662306a36Sopenharmony_ci int ret; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci mutex_lock(&ac->mutex); 12962306a36Sopenharmony_ci dout("auth_build_hello\n"); 13062306a36Sopenharmony_ci monhdr->have_version = 0; 13162306a36Sopenharmony_ci monhdr->session_mon = cpu_to_le16(-1); 13262306a36Sopenharmony_ci monhdr->session_mon_tid = 0; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci ceph_encode_32(&p, CEPH_AUTH_UNKNOWN); /* no protocol, yet */ 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci lenp = p; 13762306a36Sopenharmony_ci p += sizeof(u32); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ceph_decode_need(&p, end, 1 + sizeof(u32), bad); 14062306a36Sopenharmony_ci ceph_encode_8(&p, 1); 14162306a36Sopenharmony_ci num = ARRAY_SIZE(supported_protocols); 14262306a36Sopenharmony_ci ceph_encode_32(&p, num); 14362306a36Sopenharmony_ci ceph_decode_need(&p, end, num * sizeof(u32), bad); 14462306a36Sopenharmony_ci for (i = 0; i < num; i++) 14562306a36Sopenharmony_ci ceph_encode_32(&p, supported_protocols[i]); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci ret = ceph_auth_entity_name_encode(ac->name, &p, end); 14862306a36Sopenharmony_ci if (ret < 0) 14962306a36Sopenharmony_ci goto out; 15062306a36Sopenharmony_ci ceph_decode_need(&p, end, sizeof(u64), bad); 15162306a36Sopenharmony_ci ceph_encode_64(&p, ac->global_id); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci ceph_encode_32(&lenp, p - lenp - sizeof(u32)); 15462306a36Sopenharmony_ci ret = p - buf; 15562306a36Sopenharmony_ciout: 15662306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 15762306a36Sopenharmony_ci return ret; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cibad: 16062306a36Sopenharmony_ci ret = -ERANGE; 16162306a36Sopenharmony_ci goto out; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic int build_request(struct ceph_auth_client *ac, bool add_header, 16562306a36Sopenharmony_ci void *buf, int buf_len) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci void *end = buf + buf_len; 16862306a36Sopenharmony_ci void *p; 16962306a36Sopenharmony_ci int ret; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci p = buf; 17262306a36Sopenharmony_ci if (add_header) { 17362306a36Sopenharmony_ci /* struct ceph_mon_request_header + protocol */ 17462306a36Sopenharmony_ci ceph_encode_64_safe(&p, end, 0, e_range); 17562306a36Sopenharmony_ci ceph_encode_16_safe(&p, end, -1, e_range); 17662306a36Sopenharmony_ci ceph_encode_64_safe(&p, end, 0, e_range); 17762306a36Sopenharmony_ci ceph_encode_32_safe(&p, end, ac->protocol, e_range); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci ceph_encode_need(&p, end, sizeof(u32), e_range); 18162306a36Sopenharmony_ci ret = ac->ops->build_request(ac, p + sizeof(u32), end); 18262306a36Sopenharmony_ci if (ret < 0) { 18362306a36Sopenharmony_ci pr_err("auth protocol '%s' building request failed: %d\n", 18462306a36Sopenharmony_ci ceph_auth_proto_name(ac->protocol), ret); 18562306a36Sopenharmony_ci return ret; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci dout(" built request %d bytes\n", ret); 18862306a36Sopenharmony_ci ceph_encode_32(&p, ret); 18962306a36Sopenharmony_ci return p + ret - buf; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cie_range: 19262306a36Sopenharmony_ci return -ERANGE; 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci/* 19662306a36Sopenharmony_ci * Handle auth message from monitor. 19762306a36Sopenharmony_ci */ 19862306a36Sopenharmony_ciint ceph_handle_auth_reply(struct ceph_auth_client *ac, 19962306a36Sopenharmony_ci void *buf, size_t len, 20062306a36Sopenharmony_ci void *reply_buf, size_t reply_len) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci void *p = buf; 20362306a36Sopenharmony_ci void *end = buf + len; 20462306a36Sopenharmony_ci int protocol; 20562306a36Sopenharmony_ci s32 result; 20662306a36Sopenharmony_ci u64 global_id; 20762306a36Sopenharmony_ci void *payload, *payload_end; 20862306a36Sopenharmony_ci int payload_len; 20962306a36Sopenharmony_ci char *result_msg; 21062306a36Sopenharmony_ci int result_msg_len; 21162306a36Sopenharmony_ci int ret = -EINVAL; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci mutex_lock(&ac->mutex); 21462306a36Sopenharmony_ci dout("handle_auth_reply %p %p\n", p, end); 21562306a36Sopenharmony_ci ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad); 21662306a36Sopenharmony_ci protocol = ceph_decode_32(&p); 21762306a36Sopenharmony_ci result = ceph_decode_32(&p); 21862306a36Sopenharmony_ci global_id = ceph_decode_64(&p); 21962306a36Sopenharmony_ci payload_len = ceph_decode_32(&p); 22062306a36Sopenharmony_ci payload = p; 22162306a36Sopenharmony_ci p += payload_len; 22262306a36Sopenharmony_ci ceph_decode_need(&p, end, sizeof(u32), bad); 22362306a36Sopenharmony_ci result_msg_len = ceph_decode_32(&p); 22462306a36Sopenharmony_ci result_msg = p; 22562306a36Sopenharmony_ci p += result_msg_len; 22662306a36Sopenharmony_ci if (p != end) 22762306a36Sopenharmony_ci goto bad; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len, 23062306a36Sopenharmony_ci result_msg, global_id, payload_len); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci payload_end = payload + payload_len; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (ac->negotiating) { 23562306a36Sopenharmony_ci /* server does not support our protocols? */ 23662306a36Sopenharmony_ci if (!protocol && result < 0) { 23762306a36Sopenharmony_ci ret = result; 23862306a36Sopenharmony_ci goto out; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci /* set up (new) protocol handler? */ 24162306a36Sopenharmony_ci if (ac->protocol && ac->protocol != protocol) { 24262306a36Sopenharmony_ci ac->ops->destroy(ac); 24362306a36Sopenharmony_ci ac->protocol = 0; 24462306a36Sopenharmony_ci ac->ops = NULL; 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci if (ac->protocol != protocol) { 24762306a36Sopenharmony_ci ret = init_protocol(ac, protocol); 24862306a36Sopenharmony_ci if (ret) { 24962306a36Sopenharmony_ci pr_err("auth protocol '%s' init failed: %d\n", 25062306a36Sopenharmony_ci ceph_auth_proto_name(protocol), ret); 25162306a36Sopenharmony_ci goto out; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci ac->negotiating = false; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (result) { 25962306a36Sopenharmony_ci pr_err("auth protocol '%s' mauth authentication failed: %d\n", 26062306a36Sopenharmony_ci ceph_auth_proto_name(ac->protocol), result); 26162306a36Sopenharmony_ci ret = result; 26262306a36Sopenharmony_ci goto out; 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci ret = ac->ops->handle_reply(ac, global_id, payload, payload_end, 26662306a36Sopenharmony_ci NULL, NULL, NULL, NULL); 26762306a36Sopenharmony_ci if (ret == -EAGAIN) { 26862306a36Sopenharmony_ci ret = build_request(ac, true, reply_buf, reply_len); 26962306a36Sopenharmony_ci goto out; 27062306a36Sopenharmony_ci } else if (ret) { 27162306a36Sopenharmony_ci goto out; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ciout: 27562306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 27662306a36Sopenharmony_ci return ret; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cibad: 27962306a36Sopenharmony_ci pr_err("failed to decode auth msg\n"); 28062306a36Sopenharmony_ci ret = -EINVAL; 28162306a36Sopenharmony_ci goto out; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ciint ceph_build_auth(struct ceph_auth_client *ac, 28562306a36Sopenharmony_ci void *msg_buf, size_t msg_len) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci int ret = 0; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci mutex_lock(&ac->mutex); 29062306a36Sopenharmony_ci if (ac->ops->should_authenticate(ac)) 29162306a36Sopenharmony_ci ret = build_request(ac, true, msg_buf, msg_len); 29262306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 29362306a36Sopenharmony_ci return ret; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ciint ceph_auth_is_authenticated(struct ceph_auth_client *ac) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci int ret = 0; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci mutex_lock(&ac->mutex); 30162306a36Sopenharmony_ci if (ac->ops) 30262306a36Sopenharmony_ci ret = ac->ops->is_authenticated(ac); 30362306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 30462306a36Sopenharmony_ci return ret; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_is_authenticated); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ciint __ceph_auth_get_authorizer(struct ceph_auth_client *ac, 30962306a36Sopenharmony_ci struct ceph_auth_handshake *auth, 31062306a36Sopenharmony_ci int peer_type, bool force_new, 31162306a36Sopenharmony_ci int *proto, int *pref_mode, int *fallb_mode) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci int ret; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci mutex_lock(&ac->mutex); 31662306a36Sopenharmony_ci if (force_new && auth->authorizer) { 31762306a36Sopenharmony_ci ceph_auth_destroy_authorizer(auth->authorizer); 31862306a36Sopenharmony_ci auth->authorizer = NULL; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci if (!auth->authorizer) 32162306a36Sopenharmony_ci ret = ac->ops->create_authorizer(ac, peer_type, auth); 32262306a36Sopenharmony_ci else if (ac->ops->update_authorizer) 32362306a36Sopenharmony_ci ret = ac->ops->update_authorizer(ac, peer_type, auth); 32462306a36Sopenharmony_ci else 32562306a36Sopenharmony_ci ret = 0; 32662306a36Sopenharmony_ci if (ret) 32762306a36Sopenharmony_ci goto out; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci *proto = ac->protocol; 33062306a36Sopenharmony_ci if (pref_mode && fallb_mode) { 33162306a36Sopenharmony_ci *pref_mode = ac->preferred_mode; 33262306a36Sopenharmony_ci *fallb_mode = ac->fallback_mode; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ciout: 33662306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 33762306a36Sopenharmony_ci return ret; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ciEXPORT_SYMBOL(__ceph_auth_get_authorizer); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_civoid ceph_auth_destroy_authorizer(struct ceph_authorizer *a) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci a->destroy(a); 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_destroy_authorizer); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ciint ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac, 34862306a36Sopenharmony_ci struct ceph_authorizer *a, 34962306a36Sopenharmony_ci void *challenge_buf, 35062306a36Sopenharmony_ci int challenge_buf_len) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci int ret = 0; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci mutex_lock(&ac->mutex); 35562306a36Sopenharmony_ci if (ac->ops && ac->ops->add_authorizer_challenge) 35662306a36Sopenharmony_ci ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf, 35762306a36Sopenharmony_ci challenge_buf_len); 35862306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 35962306a36Sopenharmony_ci return ret; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_add_authorizer_challenge); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ciint ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac, 36462306a36Sopenharmony_ci struct ceph_authorizer *a, 36562306a36Sopenharmony_ci void *reply, int reply_len, 36662306a36Sopenharmony_ci u8 *session_key, int *session_key_len, 36762306a36Sopenharmony_ci u8 *con_secret, int *con_secret_len) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci int ret = 0; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci mutex_lock(&ac->mutex); 37262306a36Sopenharmony_ci if (ac->ops && ac->ops->verify_authorizer_reply) 37362306a36Sopenharmony_ci ret = ac->ops->verify_authorizer_reply(ac, a, 37462306a36Sopenharmony_ci reply, reply_len, session_key, session_key_len, 37562306a36Sopenharmony_ci con_secret, con_secret_len); 37662306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 37762306a36Sopenharmony_ci return ret; 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_verify_authorizer_reply); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_civoid ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci mutex_lock(&ac->mutex); 38462306a36Sopenharmony_ci if (ac->ops && ac->ops->invalidate_authorizer) 38562306a36Sopenharmony_ci ac->ops->invalidate_authorizer(ac, peer_type); 38662306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_invalidate_authorizer); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci/* 39162306a36Sopenharmony_ci * msgr2 authentication 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic bool contains(const int *arr, int cnt, int val) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci int i; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci for (i = 0; i < cnt; i++) { 39962306a36Sopenharmony_ci if (arr[i] == val) 40062306a36Sopenharmony_ci return true; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci return false; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci WARN_ON(pref_mode == CEPH_CON_MODE_UNKNOWN); 40962306a36Sopenharmony_ci if (fallb_mode != CEPH_CON_MODE_UNKNOWN) { 41062306a36Sopenharmony_ci ceph_encode_32_safe(p, end, 2, e_range); 41162306a36Sopenharmony_ci ceph_encode_32_safe(p, end, pref_mode, e_range); 41262306a36Sopenharmony_ci ceph_encode_32_safe(p, end, fallb_mode, e_range); 41362306a36Sopenharmony_ci } else { 41462306a36Sopenharmony_ci ceph_encode_32_safe(p, end, 1, e_range); 41562306a36Sopenharmony_ci ceph_encode_32_safe(p, end, pref_mode, e_range); 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cie_range: 42162306a36Sopenharmony_ci return -ERANGE; 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci/* 42562306a36Sopenharmony_ci * Similar to ceph_auth_build_hello(). 42662306a36Sopenharmony_ci */ 42762306a36Sopenharmony_ciint ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE; 43062306a36Sopenharmony_ci void *end = buf + buf_len; 43162306a36Sopenharmony_ci void *lenp; 43262306a36Sopenharmony_ci void *p; 43362306a36Sopenharmony_ci int ret; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci mutex_lock(&ac->mutex); 43662306a36Sopenharmony_ci if (ac->protocol == CEPH_AUTH_UNKNOWN) { 43762306a36Sopenharmony_ci ret = init_protocol(ac, proto); 43862306a36Sopenharmony_ci if (ret) { 43962306a36Sopenharmony_ci pr_err("auth protocol '%s' init failed: %d\n", 44062306a36Sopenharmony_ci ceph_auth_proto_name(proto), ret); 44162306a36Sopenharmony_ci goto out; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci } else { 44462306a36Sopenharmony_ci WARN_ON(ac->protocol != proto); 44562306a36Sopenharmony_ci ac->ops->reset(ac); 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci p = buf; 44962306a36Sopenharmony_ci ceph_encode_32_safe(&p, end, ac->protocol, e_range); 45062306a36Sopenharmony_ci ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode); 45162306a36Sopenharmony_ci if (ret) 45262306a36Sopenharmony_ci goto out; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci lenp = p; 45562306a36Sopenharmony_ci p += 4; /* space for len */ 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range); 45862306a36Sopenharmony_ci ret = ceph_auth_entity_name_encode(ac->name, &p, end); 45962306a36Sopenharmony_ci if (ret) 46062306a36Sopenharmony_ci goto out; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci ceph_encode_64_safe(&p, end, ac->global_id, e_range); 46362306a36Sopenharmony_ci ceph_encode_32(&lenp, p - lenp - 4); 46462306a36Sopenharmony_ci ret = p - buf; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ciout: 46762306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 46862306a36Sopenharmony_ci return ret; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cie_range: 47162306a36Sopenharmony_ci ret = -ERANGE; 47262306a36Sopenharmony_ci goto out; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ciint ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply, 47662306a36Sopenharmony_ci int reply_len, void *buf, int buf_len) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci int ret; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci mutex_lock(&ac->mutex); 48162306a36Sopenharmony_ci ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len, 48262306a36Sopenharmony_ci NULL, NULL, NULL, NULL); 48362306a36Sopenharmony_ci if (ret == -EAGAIN) 48462306a36Sopenharmony_ci ret = build_request(ac, false, buf, buf_len); 48562306a36Sopenharmony_ci else 48662306a36Sopenharmony_ci WARN_ON(ret >= 0); 48762306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 48862306a36Sopenharmony_ci return ret; 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ciint ceph_auth_handle_reply_done(struct ceph_auth_client *ac, 49262306a36Sopenharmony_ci u64 global_id, void *reply, int reply_len, 49362306a36Sopenharmony_ci u8 *session_key, int *session_key_len, 49462306a36Sopenharmony_ci u8 *con_secret, int *con_secret_len) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci int ret; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci mutex_lock(&ac->mutex); 49962306a36Sopenharmony_ci ret = ac->ops->handle_reply(ac, global_id, reply, reply + reply_len, 50062306a36Sopenharmony_ci session_key, session_key_len, 50162306a36Sopenharmony_ci con_secret, con_secret_len); 50262306a36Sopenharmony_ci WARN_ON(ret == -EAGAIN || ret > 0); 50362306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 50462306a36Sopenharmony_ci return ret; 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cibool ceph_auth_handle_bad_method(struct ceph_auth_client *ac, 50862306a36Sopenharmony_ci int used_proto, int result, 50962306a36Sopenharmony_ci const int *allowed_protos, int proto_cnt, 51062306a36Sopenharmony_ci const int *allowed_modes, int mode_cnt) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci mutex_lock(&ac->mutex); 51362306a36Sopenharmony_ci WARN_ON(used_proto != ac->protocol); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci if (result == -EOPNOTSUPP) { 51662306a36Sopenharmony_ci if (!contains(allowed_protos, proto_cnt, ac->protocol)) { 51762306a36Sopenharmony_ci pr_err("auth protocol '%s' not allowed\n", 51862306a36Sopenharmony_ci ceph_auth_proto_name(ac->protocol)); 51962306a36Sopenharmony_ci goto not_allowed; 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) && 52262306a36Sopenharmony_ci (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN || 52362306a36Sopenharmony_ci !contains(allowed_modes, mode_cnt, ac->fallback_mode))) { 52462306a36Sopenharmony_ci pr_err("preferred mode '%s' not allowed\n", 52562306a36Sopenharmony_ci ceph_con_mode_name(ac->preferred_mode)); 52662306a36Sopenharmony_ci if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN) 52762306a36Sopenharmony_ci pr_err("no fallback mode\n"); 52862306a36Sopenharmony_ci else 52962306a36Sopenharmony_ci pr_err("fallback mode '%s' not allowed\n", 53062306a36Sopenharmony_ci ceph_con_mode_name(ac->fallback_mode)); 53162306a36Sopenharmony_ci goto not_allowed; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci WARN_ON(result == -EOPNOTSUPP || result >= 0); 53662306a36Sopenharmony_ci pr_err("auth protocol '%s' msgr authentication failed: %d\n", 53762306a36Sopenharmony_ci ceph_auth_proto_name(ac->protocol), result); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 54062306a36Sopenharmony_ci return true; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cinot_allowed: 54362306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 54462306a36Sopenharmony_ci return false; 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ciint ceph_auth_get_authorizer(struct ceph_auth_client *ac, 54862306a36Sopenharmony_ci struct ceph_auth_handshake *auth, 54962306a36Sopenharmony_ci int peer_type, void *buf, int *buf_len) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci void *end = buf + *buf_len; 55262306a36Sopenharmony_ci int pref_mode, fallb_mode; 55362306a36Sopenharmony_ci int proto; 55462306a36Sopenharmony_ci void *p; 55562306a36Sopenharmony_ci int ret; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto, 55862306a36Sopenharmony_ci &pref_mode, &fallb_mode); 55962306a36Sopenharmony_ci if (ret) 56062306a36Sopenharmony_ci return ret; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci p = buf; 56362306a36Sopenharmony_ci ceph_encode_32_safe(&p, end, proto, e_range); 56462306a36Sopenharmony_ci ret = encode_con_modes(&p, end, pref_mode, fallb_mode); 56562306a36Sopenharmony_ci if (ret) 56662306a36Sopenharmony_ci return ret; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 56962306a36Sopenharmony_ci *buf_len = p - buf; 57062306a36Sopenharmony_ci return 0; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cie_range: 57362306a36Sopenharmony_ci return -ERANGE; 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_get_authorizer); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ciint ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac, 57862306a36Sopenharmony_ci struct ceph_auth_handshake *auth, 57962306a36Sopenharmony_ci void *reply, int reply_len, 58062306a36Sopenharmony_ci void *buf, int *buf_len) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci void *end = buf + *buf_len; 58362306a36Sopenharmony_ci void *p; 58462306a36Sopenharmony_ci int ret; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer, 58762306a36Sopenharmony_ci reply, reply_len); 58862306a36Sopenharmony_ci if (ret) 58962306a36Sopenharmony_ci return ret; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci p = buf; 59262306a36Sopenharmony_ci ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 59362306a36Sopenharmony_ci *buf_len = p - buf; 59462306a36Sopenharmony_ci return 0; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_cie_range: 59762306a36Sopenharmony_ci return -ERANGE; 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_handle_svc_reply_more); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ciint ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac, 60262306a36Sopenharmony_ci struct ceph_auth_handshake *auth, 60362306a36Sopenharmony_ci void *reply, int reply_len, 60462306a36Sopenharmony_ci u8 *session_key, int *session_key_len, 60562306a36Sopenharmony_ci u8 *con_secret, int *con_secret_len) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci return ceph_auth_verify_authorizer_reply(ac, auth->authorizer, 60862306a36Sopenharmony_ci reply, reply_len, session_key, session_key_len, 60962306a36Sopenharmony_ci con_secret, con_secret_len); 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_handle_svc_reply_done); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cibool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac, 61462306a36Sopenharmony_ci int peer_type, int used_proto, int result, 61562306a36Sopenharmony_ci const int *allowed_protos, int proto_cnt, 61662306a36Sopenharmony_ci const int *allowed_modes, int mode_cnt) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci mutex_lock(&ac->mutex); 61962306a36Sopenharmony_ci WARN_ON(used_proto != ac->protocol); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (result == -EOPNOTSUPP) { 62262306a36Sopenharmony_ci if (!contains(allowed_protos, proto_cnt, ac->protocol)) { 62362306a36Sopenharmony_ci pr_err("auth protocol '%s' not allowed by %s\n", 62462306a36Sopenharmony_ci ceph_auth_proto_name(ac->protocol), 62562306a36Sopenharmony_ci ceph_entity_type_name(peer_type)); 62662306a36Sopenharmony_ci goto not_allowed; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) && 62962306a36Sopenharmony_ci (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN || 63062306a36Sopenharmony_ci !contains(allowed_modes, mode_cnt, ac->fallback_mode))) { 63162306a36Sopenharmony_ci pr_err("preferred mode '%s' not allowed by %s\n", 63262306a36Sopenharmony_ci ceph_con_mode_name(ac->preferred_mode), 63362306a36Sopenharmony_ci ceph_entity_type_name(peer_type)); 63462306a36Sopenharmony_ci if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN) 63562306a36Sopenharmony_ci pr_err("no fallback mode\n"); 63662306a36Sopenharmony_ci else 63762306a36Sopenharmony_ci pr_err("fallback mode '%s' not allowed by %s\n", 63862306a36Sopenharmony_ci ceph_con_mode_name(ac->fallback_mode), 63962306a36Sopenharmony_ci ceph_entity_type_name(peer_type)); 64062306a36Sopenharmony_ci goto not_allowed; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci WARN_ON(result == -EOPNOTSUPP || result >= 0); 64562306a36Sopenharmony_ci pr_err("auth protocol '%s' authorization to %s failed: %d\n", 64662306a36Sopenharmony_ci ceph_auth_proto_name(ac->protocol), 64762306a36Sopenharmony_ci ceph_entity_type_name(peer_type), result); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci if (ac->ops->invalidate_authorizer) 65062306a36Sopenharmony_ci ac->ops->invalidate_authorizer(ac, peer_type); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 65362306a36Sopenharmony_ci return true; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cinot_allowed: 65662306a36Sopenharmony_ci mutex_unlock(&ac->mutex); 65762306a36Sopenharmony_ci return false; 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_auth_handle_bad_authorizer); 660