xref: /openbmc/linux/net/ceph/auth.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
23d14c5d2SYehuda Sadeh #include <linux/ceph/ceph_debug.h>
33d14c5d2SYehuda Sadeh 
43d14c5d2SYehuda Sadeh #include <linux/module.h>
53d14c5d2SYehuda Sadeh #include <linux/err.h>
63d14c5d2SYehuda Sadeh #include <linux/slab.h>
73d14c5d2SYehuda Sadeh 
83d14c5d2SYehuda Sadeh #include <linux/ceph/types.h>
93d14c5d2SYehuda Sadeh #include <linux/ceph/decode.h>
103d14c5d2SYehuda Sadeh #include <linux/ceph/libceph.h>
113d14c5d2SYehuda Sadeh #include <linux/ceph/messenger.h>
123d14c5d2SYehuda Sadeh #include "auth_none.h"
133d14c5d2SYehuda Sadeh #include "auth_x.h"
143d14c5d2SYehuda Sadeh 
153d14c5d2SYehuda Sadeh 
163d14c5d2SYehuda Sadeh /*
173d14c5d2SYehuda Sadeh  * get protocol handler
183d14c5d2SYehuda Sadeh  */
193d14c5d2SYehuda Sadeh static u32 supported_protocols[] = {
203d14c5d2SYehuda Sadeh 	CEPH_AUTH_NONE,
213d14c5d2SYehuda Sadeh 	CEPH_AUTH_CEPHX
223d14c5d2SYehuda Sadeh };
233d14c5d2SYehuda Sadeh 
init_protocol(struct ceph_auth_client * ac,int proto)2459711f9eSIlya Dryomov static int init_protocol(struct ceph_auth_client *ac, int proto)
253d14c5d2SYehuda Sadeh {
2659711f9eSIlya Dryomov 	dout("%s proto %d\n", __func__, proto);
2759711f9eSIlya Dryomov 
2859711f9eSIlya Dryomov 	switch (proto) {
293d14c5d2SYehuda Sadeh 	case CEPH_AUTH_NONE:
303d14c5d2SYehuda Sadeh 		return ceph_auth_none_init(ac);
313d14c5d2SYehuda Sadeh 	case CEPH_AUTH_CEPHX:
323d14c5d2SYehuda Sadeh 		return ceph_x_init(ac);
333d14c5d2SYehuda Sadeh 	default:
3459711f9eSIlya Dryomov 		pr_err("bad auth protocol %d\n", proto);
3559711f9eSIlya Dryomov 		return -EINVAL;
363d14c5d2SYehuda Sadeh 	}
373d14c5d2SYehuda Sadeh }
383d14c5d2SYehuda Sadeh 
ceph_auth_set_global_id(struct ceph_auth_client * ac,u64 global_id)3903af4c7bSIlya Dryomov void ceph_auth_set_global_id(struct ceph_auth_client *ac, u64 global_id)
4061ca49a9SIlya Dryomov {
4161ca49a9SIlya Dryomov 	dout("%s global_id %llu\n", __func__, global_id);
4261ca49a9SIlya Dryomov 
4361ca49a9SIlya Dryomov 	if (!global_id)
4461ca49a9SIlya Dryomov 		pr_err("got zero global_id\n");
4561ca49a9SIlya Dryomov 
4661ca49a9SIlya Dryomov 	if (ac->global_id && global_id != ac->global_id)
4761ca49a9SIlya Dryomov 		pr_err("global_id changed from %llu to %llu\n", ac->global_id,
4861ca49a9SIlya Dryomov 		       global_id);
4961ca49a9SIlya Dryomov 
5061ca49a9SIlya Dryomov 	ac->global_id = global_id;
5161ca49a9SIlya Dryomov }
5261ca49a9SIlya Dryomov 
533d14c5d2SYehuda Sadeh /*
543d14c5d2SYehuda Sadeh  * setup, teardown.
553d14c5d2SYehuda Sadeh  */
ceph_auth_init(const char * name,const struct ceph_crypto_key * key,const int * con_modes)5600498b99SIlya Dryomov struct ceph_auth_client *ceph_auth_init(const char *name,
5700498b99SIlya Dryomov 					const struct ceph_crypto_key *key,
5800498b99SIlya Dryomov 					const int *con_modes)
593d14c5d2SYehuda Sadeh {
603d14c5d2SYehuda Sadeh 	struct ceph_auth_client *ac;
613d14c5d2SYehuda Sadeh 
623d14c5d2SYehuda Sadeh 	ac = kzalloc(sizeof(*ac), GFP_NOFS);
633d14c5d2SYehuda Sadeh 	if (!ac)
64*da6ebb4dSzuoqilin 		return ERR_PTR(-ENOMEM);
653d14c5d2SYehuda Sadeh 
66e9966076SSage Weil 	mutex_init(&ac->mutex);
673d14c5d2SYehuda Sadeh 	ac->negotiating = true;
683d14c5d2SYehuda Sadeh 	if (name)
693d14c5d2SYehuda Sadeh 		ac->name = name;
703d14c5d2SYehuda Sadeh 	else
713d14c5d2SYehuda Sadeh 		ac->name = CEPH_AUTH_NAME_DEFAULT;
728323c3aaSTommi Virtanen 	ac->key = key;
7300498b99SIlya Dryomov 	ac->preferred_mode = con_modes[0];
7400498b99SIlya Dryomov 	ac->fallback_mode = con_modes[1];
7500498b99SIlya Dryomov 
7600498b99SIlya Dryomov 	dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__,
7700498b99SIlya Dryomov 	     ac->name, ac->preferred_mode, ac->fallback_mode);
783d14c5d2SYehuda Sadeh 	return ac;
793d14c5d2SYehuda Sadeh }
803d14c5d2SYehuda Sadeh 
ceph_auth_destroy(struct ceph_auth_client * ac)813d14c5d2SYehuda Sadeh void ceph_auth_destroy(struct ceph_auth_client *ac)
823d14c5d2SYehuda Sadeh {
833d14c5d2SYehuda Sadeh 	dout("auth_destroy %p\n", ac);
843d14c5d2SYehuda Sadeh 	if (ac->ops)
853d14c5d2SYehuda Sadeh 		ac->ops->destroy(ac);
863d14c5d2SYehuda Sadeh 	kfree(ac);
873d14c5d2SYehuda Sadeh }
883d14c5d2SYehuda Sadeh 
893d14c5d2SYehuda Sadeh /*
903d14c5d2SYehuda Sadeh  * Reset occurs when reconnecting to the monitor.
913d14c5d2SYehuda Sadeh  */
ceph_auth_reset(struct ceph_auth_client * ac)923d14c5d2SYehuda Sadeh void ceph_auth_reset(struct ceph_auth_client *ac)
933d14c5d2SYehuda Sadeh {
94e9966076SSage Weil 	mutex_lock(&ac->mutex);
953d14c5d2SYehuda Sadeh 	dout("auth_reset %p\n", ac);
963d14c5d2SYehuda Sadeh 	if (ac->ops && !ac->negotiating)
973d14c5d2SYehuda Sadeh 		ac->ops->reset(ac);
983d14c5d2SYehuda Sadeh 	ac->negotiating = true;
99e9966076SSage Weil 	mutex_unlock(&ac->mutex);
1003d14c5d2SYehuda Sadeh }
1013d14c5d2SYehuda Sadeh 
102f01d5cb2SIlya Dryomov /*
103f01d5cb2SIlya Dryomov  * EntityName, not to be confused with entity_name_t
104f01d5cb2SIlya Dryomov  */
ceph_auth_entity_name_encode(const char * name,void ** p,void * end)105f01d5cb2SIlya Dryomov int ceph_auth_entity_name_encode(const char *name, void **p, void *end)
1063d14c5d2SYehuda Sadeh {
1073d14c5d2SYehuda Sadeh 	int len = strlen(name);
1083d14c5d2SYehuda Sadeh 
1093d14c5d2SYehuda Sadeh 	if (*p + 2*sizeof(u32) + len > end)
1103d14c5d2SYehuda Sadeh 		return -ERANGE;
1113d14c5d2SYehuda Sadeh 	ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
1123d14c5d2SYehuda Sadeh 	ceph_encode_32(p, len);
1133d14c5d2SYehuda Sadeh 	ceph_encode_copy(p, name, len);
1143d14c5d2SYehuda Sadeh 	return 0;
1153d14c5d2SYehuda Sadeh }
1163d14c5d2SYehuda Sadeh 
1173d14c5d2SYehuda Sadeh /*
1183d14c5d2SYehuda Sadeh  * Initiate protocol negotiation with monitor.  Include entity name
1193d14c5d2SYehuda Sadeh  * and list supported protocols.
1203d14c5d2SYehuda Sadeh  */
ceph_auth_build_hello(struct ceph_auth_client * ac,void * buf,size_t len)1213d14c5d2SYehuda Sadeh int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
1223d14c5d2SYehuda Sadeh {
1233d14c5d2SYehuda Sadeh 	struct ceph_mon_request_header *monhdr = buf;
1243d14c5d2SYehuda Sadeh 	void *p = monhdr + 1, *end = buf + len, *lenp;
1253d14c5d2SYehuda Sadeh 	int i, num;
1263d14c5d2SYehuda Sadeh 	int ret;
1273d14c5d2SYehuda Sadeh 
128e9966076SSage Weil 	mutex_lock(&ac->mutex);
1293d14c5d2SYehuda Sadeh 	dout("auth_build_hello\n");
1303d14c5d2SYehuda Sadeh 	monhdr->have_version = 0;
1313d14c5d2SYehuda Sadeh 	monhdr->session_mon = cpu_to_le16(-1);
1323d14c5d2SYehuda Sadeh 	monhdr->session_mon_tid = 0;
1333d14c5d2SYehuda Sadeh 
134fdc723e7SIlya Dryomov 	ceph_encode_32(&p, CEPH_AUTH_UNKNOWN);  /* no protocol, yet */
1353d14c5d2SYehuda Sadeh 
1363d14c5d2SYehuda Sadeh 	lenp = p;
1373d14c5d2SYehuda Sadeh 	p += sizeof(u32);
1383d14c5d2SYehuda Sadeh 
1393d14c5d2SYehuda Sadeh 	ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
1403d14c5d2SYehuda Sadeh 	ceph_encode_8(&p, 1);
1413d14c5d2SYehuda Sadeh 	num = ARRAY_SIZE(supported_protocols);
1423d14c5d2SYehuda Sadeh 	ceph_encode_32(&p, num);
1433d14c5d2SYehuda Sadeh 	ceph_decode_need(&p, end, num * sizeof(u32), bad);
1443d14c5d2SYehuda Sadeh 	for (i = 0; i < num; i++)
1453d14c5d2SYehuda Sadeh 		ceph_encode_32(&p, supported_protocols[i]);
1463d14c5d2SYehuda Sadeh 
147f01d5cb2SIlya Dryomov 	ret = ceph_auth_entity_name_encode(ac->name, &p, end);
1483d14c5d2SYehuda Sadeh 	if (ret < 0)
149e9966076SSage Weil 		goto out;
1503d14c5d2SYehuda Sadeh 	ceph_decode_need(&p, end, sizeof(u64), bad);
1513d14c5d2SYehuda Sadeh 	ceph_encode_64(&p, ac->global_id);
1523d14c5d2SYehuda Sadeh 
1533d14c5d2SYehuda Sadeh 	ceph_encode_32(&lenp, p - lenp - sizeof(u32));
154e9966076SSage Weil 	ret = p - buf;
155e9966076SSage Weil out:
156e9966076SSage Weil 	mutex_unlock(&ac->mutex);
157e9966076SSage Weil 	return ret;
1583d14c5d2SYehuda Sadeh 
1593d14c5d2SYehuda Sadeh bad:
160e9966076SSage Weil 	ret = -ERANGE;
161e9966076SSage Weil 	goto out;
1623d14c5d2SYehuda Sadeh }
1633d14c5d2SYehuda Sadeh 
build_request(struct ceph_auth_client * ac,bool add_header,void * buf,int buf_len)16459711f9eSIlya Dryomov static int build_request(struct ceph_auth_client *ac, bool add_header,
16559711f9eSIlya Dryomov 			 void *buf, int buf_len)
1663d14c5d2SYehuda Sadeh {
16759711f9eSIlya Dryomov 	void *end = buf + buf_len;
16859711f9eSIlya Dryomov 	void *p;
1693d14c5d2SYehuda Sadeh 	int ret;
1703d14c5d2SYehuda Sadeh 
17159711f9eSIlya Dryomov 	p = buf;
17259711f9eSIlya Dryomov 	if (add_header) {
17359711f9eSIlya Dryomov 		/* struct ceph_mon_request_header + protocol */
17459711f9eSIlya Dryomov 		ceph_encode_64_safe(&p, end, 0, e_range);
17559711f9eSIlya Dryomov 		ceph_encode_16_safe(&p, end, -1, e_range);
17659711f9eSIlya Dryomov 		ceph_encode_64_safe(&p, end, 0, e_range);
17759711f9eSIlya Dryomov 		ceph_encode_32_safe(&p, end, ac->protocol, e_range);
17859711f9eSIlya Dryomov 	}
1793d14c5d2SYehuda Sadeh 
18059711f9eSIlya Dryomov 	ceph_encode_need(&p, end, sizeof(u32), e_range);
1813d14c5d2SYehuda Sadeh 	ret = ac->ops->build_request(ac, p + sizeof(u32), end);
1823d14c5d2SYehuda Sadeh 	if (ret < 0) {
18359711f9eSIlya Dryomov 		pr_err("auth protocol '%s' building request failed: %d\n",
18459711f9eSIlya Dryomov 		       ceph_auth_proto_name(ac->protocol), ret);
18559711f9eSIlya Dryomov 		return ret;
1863d14c5d2SYehuda Sadeh 	}
1873d14c5d2SYehuda Sadeh 	dout(" built request %d bytes\n", ret);
1883d14c5d2SYehuda Sadeh 	ceph_encode_32(&p, ret);
18959711f9eSIlya Dryomov 	return p + ret - buf;
19059711f9eSIlya Dryomov 
19159711f9eSIlya Dryomov e_range:
19259711f9eSIlya Dryomov 	return -ERANGE;
1933d14c5d2SYehuda Sadeh }
1943d14c5d2SYehuda Sadeh 
1953d14c5d2SYehuda Sadeh /*
1963d14c5d2SYehuda Sadeh  * Handle auth message from monitor.
1973d14c5d2SYehuda Sadeh  */
ceph_handle_auth_reply(struct ceph_auth_client * ac,void * buf,size_t len,void * reply_buf,size_t reply_len)1983d14c5d2SYehuda Sadeh int ceph_handle_auth_reply(struct ceph_auth_client *ac,
1993d14c5d2SYehuda Sadeh 			   void *buf, size_t len,
2003d14c5d2SYehuda Sadeh 			   void *reply_buf, size_t reply_len)
2013d14c5d2SYehuda Sadeh {
2023d14c5d2SYehuda Sadeh 	void *p = buf;
2033d14c5d2SYehuda Sadeh 	void *end = buf + len;
2043d14c5d2SYehuda Sadeh 	int protocol;
2053d14c5d2SYehuda Sadeh 	s32 result;
2063d14c5d2SYehuda Sadeh 	u64 global_id;
2073d14c5d2SYehuda Sadeh 	void *payload, *payload_end;
2083d14c5d2SYehuda Sadeh 	int payload_len;
2093d14c5d2SYehuda Sadeh 	char *result_msg;
2103d14c5d2SYehuda Sadeh 	int result_msg_len;
2113d14c5d2SYehuda Sadeh 	int ret = -EINVAL;
2123d14c5d2SYehuda Sadeh 
213e9966076SSage Weil 	mutex_lock(&ac->mutex);
2143d14c5d2SYehuda Sadeh 	dout("handle_auth_reply %p %p\n", p, end);
2153d14c5d2SYehuda Sadeh 	ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
2163d14c5d2SYehuda Sadeh 	protocol = ceph_decode_32(&p);
2173d14c5d2SYehuda Sadeh 	result = ceph_decode_32(&p);
2183d14c5d2SYehuda Sadeh 	global_id = ceph_decode_64(&p);
2193d14c5d2SYehuda Sadeh 	payload_len = ceph_decode_32(&p);
2203d14c5d2SYehuda Sadeh 	payload = p;
2213d14c5d2SYehuda Sadeh 	p += payload_len;
2223d14c5d2SYehuda Sadeh 	ceph_decode_need(&p, end, sizeof(u32), bad);
2233d14c5d2SYehuda Sadeh 	result_msg_len = ceph_decode_32(&p);
2243d14c5d2SYehuda Sadeh 	result_msg = p;
2253d14c5d2SYehuda Sadeh 	p += result_msg_len;
2263d14c5d2SYehuda Sadeh 	if (p != end)
2273d14c5d2SYehuda Sadeh 		goto bad;
2283d14c5d2SYehuda Sadeh 
2293d14c5d2SYehuda Sadeh 	dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
2303d14c5d2SYehuda Sadeh 	     result_msg, global_id, payload_len);
2313d14c5d2SYehuda Sadeh 
2323d14c5d2SYehuda Sadeh 	payload_end = payload + payload_len;
2333d14c5d2SYehuda Sadeh 
2343d14c5d2SYehuda Sadeh 	if (ac->negotiating) {
2353d14c5d2SYehuda Sadeh 		/* server does not support our protocols? */
2363d14c5d2SYehuda Sadeh 		if (!protocol && result < 0) {
2373d14c5d2SYehuda Sadeh 			ret = result;
2383d14c5d2SYehuda Sadeh 			goto out;
2393d14c5d2SYehuda Sadeh 		}
2403d14c5d2SYehuda Sadeh 		/* set up (new) protocol handler? */
2413d14c5d2SYehuda Sadeh 		if (ac->protocol && ac->protocol != protocol) {
2423d14c5d2SYehuda Sadeh 			ac->ops->destroy(ac);
2433d14c5d2SYehuda Sadeh 			ac->protocol = 0;
2443d14c5d2SYehuda Sadeh 			ac->ops = NULL;
2453d14c5d2SYehuda Sadeh 		}
2463d14c5d2SYehuda Sadeh 		if (ac->protocol != protocol) {
24759711f9eSIlya Dryomov 			ret = init_protocol(ac, protocol);
2483d14c5d2SYehuda Sadeh 			if (ret) {
24959711f9eSIlya Dryomov 				pr_err("auth protocol '%s' init failed: %d\n",
25059711f9eSIlya Dryomov 				       ceph_auth_proto_name(protocol), ret);
2513d14c5d2SYehuda Sadeh 				goto out;
2523d14c5d2SYehuda Sadeh 			}
2533d14c5d2SYehuda Sadeh 		}
2543d14c5d2SYehuda Sadeh 
2553d14c5d2SYehuda Sadeh 		ac->negotiating = false;
2563d14c5d2SYehuda Sadeh 	}
2573d14c5d2SYehuda Sadeh 
2583c0d0894SIlya Dryomov 	if (result) {
2593c0d0894SIlya Dryomov 		pr_err("auth protocol '%s' mauth authentication failed: %d\n",
2603c0d0894SIlya Dryomov 		       ceph_auth_proto_name(ac->protocol), result);
2613c0d0894SIlya Dryomov 		ret = result;
2623c0d0894SIlya Dryomov 		goto out;
2633c0d0894SIlya Dryomov 	}
2643c0d0894SIlya Dryomov 
26503af4c7bSIlya Dryomov 	ret = ac->ops->handle_reply(ac, global_id, payload, payload_end,
266285ea34fSIlya Dryomov 				    NULL, NULL, NULL, NULL);
26761ca49a9SIlya Dryomov 	if (ret == -EAGAIN) {
26859711f9eSIlya Dryomov 		ret = build_request(ac, true, reply_buf, reply_len);
26961ca49a9SIlya Dryomov 		goto out;
27061ca49a9SIlya Dryomov 	} else if (ret) {
27161ca49a9SIlya Dryomov 		goto out;
27261ca49a9SIlya Dryomov 	}
27361ca49a9SIlya Dryomov 
274e9966076SSage Weil out:
275e9966076SSage Weil 	mutex_unlock(&ac->mutex);
276e9966076SSage Weil 	return ret;
2773d14c5d2SYehuda Sadeh 
2783d14c5d2SYehuda Sadeh bad:
2793d14c5d2SYehuda Sadeh 	pr_err("failed to decode auth msg\n");
280e9966076SSage Weil 	ret = -EINVAL;
281e9966076SSage Weil 	goto out;
2823d14c5d2SYehuda Sadeh }
2833d14c5d2SYehuda Sadeh 
ceph_build_auth(struct ceph_auth_client * ac,void * msg_buf,size_t msg_len)2843d14c5d2SYehuda Sadeh int ceph_build_auth(struct ceph_auth_client *ac,
2853d14c5d2SYehuda Sadeh 		    void *msg_buf, size_t msg_len)
2863d14c5d2SYehuda Sadeh {
287e9966076SSage Weil 	int ret = 0;
288e9966076SSage Weil 
289e9966076SSage Weil 	mutex_lock(&ac->mutex);
290464691bdSIlya Dryomov 	if (ac->ops->should_authenticate(ac))
29159711f9eSIlya Dryomov 		ret = build_request(ac, true, msg_buf, msg_len);
292e9966076SSage Weil 	mutex_unlock(&ac->mutex);
293e9966076SSage Weil 	return ret;
2943d14c5d2SYehuda Sadeh }
2953d14c5d2SYehuda Sadeh 
ceph_auth_is_authenticated(struct ceph_auth_client * ac)2963d14c5d2SYehuda Sadeh int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
2973d14c5d2SYehuda Sadeh {
298e9966076SSage Weil 	int ret = 0;
299e9966076SSage Weil 
300e9966076SSage Weil 	mutex_lock(&ac->mutex);
301e9966076SSage Weil 	if (ac->ops)
302e9966076SSage Weil 		ret = ac->ops->is_authenticated(ac);
303e9966076SSage Weil 	mutex_unlock(&ac->mutex);
304e9966076SSage Weil 	return ret;
3053d14c5d2SYehuda Sadeh }
30627859f97SSage Weil EXPORT_SYMBOL(ceph_auth_is_authenticated);
30727859f97SSage Weil 
__ceph_auth_get_authorizer(struct ceph_auth_client * ac,struct ceph_auth_handshake * auth,int peer_type,bool force_new,int * proto,int * pref_mode,int * fallb_mode)308cd1a677cSIlya Dryomov int __ceph_auth_get_authorizer(struct ceph_auth_client *ac,
309cd1a677cSIlya Dryomov 			       struct ceph_auth_handshake *auth,
310cd1a677cSIlya Dryomov 			       int peer_type, bool force_new,
311cd1a677cSIlya Dryomov 			       int *proto, int *pref_mode, int *fallb_mode)
312cd1a677cSIlya Dryomov {
313cd1a677cSIlya Dryomov 	int ret;
314cd1a677cSIlya Dryomov 
315cd1a677cSIlya Dryomov 	mutex_lock(&ac->mutex);
316cd1a677cSIlya Dryomov 	if (force_new && auth->authorizer) {
317cd1a677cSIlya Dryomov 		ceph_auth_destroy_authorizer(auth->authorizer);
318cd1a677cSIlya Dryomov 		auth->authorizer = NULL;
319cd1a677cSIlya Dryomov 	}
320cd1a677cSIlya Dryomov 	if (!auth->authorizer)
321cd1a677cSIlya Dryomov 		ret = ac->ops->create_authorizer(ac, peer_type, auth);
322cd1a677cSIlya Dryomov 	else if (ac->ops->update_authorizer)
323cd1a677cSIlya Dryomov 		ret = ac->ops->update_authorizer(ac, peer_type, auth);
324cd1a677cSIlya Dryomov 	else
325cd1a677cSIlya Dryomov 		ret = 0;
326cd1a677cSIlya Dryomov 	if (ret)
327cd1a677cSIlya Dryomov 		goto out;
328cd1a677cSIlya Dryomov 
329cd1a677cSIlya Dryomov 	*proto = ac->protocol;
330cd1a677cSIlya Dryomov 	if (pref_mode && fallb_mode) {
331cd1a677cSIlya Dryomov 		*pref_mode = ac->preferred_mode;
332cd1a677cSIlya Dryomov 		*fallb_mode = ac->fallback_mode;
333cd1a677cSIlya Dryomov 	}
334cd1a677cSIlya Dryomov 
335cd1a677cSIlya Dryomov out:
336cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
337cd1a677cSIlya Dryomov 	return ret;
338cd1a677cSIlya Dryomov }
339cd1a677cSIlya Dryomov EXPORT_SYMBOL(__ceph_auth_get_authorizer);
340cd1a677cSIlya Dryomov 
ceph_auth_destroy_authorizer(struct ceph_authorizer * a)3416c1ea260SIlya Dryomov void ceph_auth_destroy_authorizer(struct ceph_authorizer *a)
34227859f97SSage Weil {
3436c1ea260SIlya Dryomov 	a->destroy(a);
34427859f97SSage Weil }
34527859f97SSage Weil EXPORT_SYMBOL(ceph_auth_destroy_authorizer);
34627859f97SSage Weil 
ceph_auth_add_authorizer_challenge(struct ceph_auth_client * ac,struct ceph_authorizer * a,void * challenge_buf,int challenge_buf_len)3476daca13dSIlya Dryomov int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac,
3486daca13dSIlya Dryomov 				       struct ceph_authorizer *a,
3496daca13dSIlya Dryomov 				       void *challenge_buf,
3506daca13dSIlya Dryomov 				       int challenge_buf_len)
3516daca13dSIlya Dryomov {
3526daca13dSIlya Dryomov 	int ret = 0;
3536daca13dSIlya Dryomov 
3546daca13dSIlya Dryomov 	mutex_lock(&ac->mutex);
3556daca13dSIlya Dryomov 	if (ac->ops && ac->ops->add_authorizer_challenge)
3566daca13dSIlya Dryomov 		ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf,
3576daca13dSIlya Dryomov 							challenge_buf_len);
3586daca13dSIlya Dryomov 	mutex_unlock(&ac->mutex);
3596daca13dSIlya Dryomov 	return ret;
3606daca13dSIlya Dryomov }
3616daca13dSIlya Dryomov EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge);
3626daca13dSIlya Dryomov 
ceph_auth_verify_authorizer_reply(struct ceph_auth_client * ac,struct ceph_authorizer * a,void * reply,int reply_len,u8 * session_key,int * session_key_len,u8 * con_secret,int * con_secret_len)36327859f97SSage Weil int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
364285ea34fSIlya Dryomov 				      struct ceph_authorizer *a,
365285ea34fSIlya Dryomov 				      void *reply, int reply_len,
366285ea34fSIlya Dryomov 				      u8 *session_key, int *session_key_len,
367285ea34fSIlya Dryomov 				      u8 *con_secret, int *con_secret_len)
36827859f97SSage Weil {
369e9966076SSage Weil 	int ret = 0;
370e9966076SSage Weil 
371e9966076SSage Weil 	mutex_lock(&ac->mutex);
37227859f97SSage Weil 	if (ac->ops && ac->ops->verify_authorizer_reply)
373285ea34fSIlya Dryomov 		ret = ac->ops->verify_authorizer_reply(ac, a,
374285ea34fSIlya Dryomov 			reply, reply_len, session_key, session_key_len,
375285ea34fSIlya Dryomov 			con_secret, con_secret_len);
376e9966076SSage Weil 	mutex_unlock(&ac->mutex);
377e9966076SSage Weil 	return ret;
37827859f97SSage Weil }
37927859f97SSage Weil EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply);
38027859f97SSage Weil 
ceph_auth_invalidate_authorizer(struct ceph_auth_client * ac,int peer_type)38127859f97SSage Weil void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type)
38227859f97SSage Weil {
383e9966076SSage Weil 	mutex_lock(&ac->mutex);
38427859f97SSage Weil 	if (ac->ops && ac->ops->invalidate_authorizer)
38527859f97SSage Weil 		ac->ops->invalidate_authorizer(ac, peer_type);
386e9966076SSage Weil 	mutex_unlock(&ac->mutex);
38727859f97SSage Weil }
38827859f97SSage Weil EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
389cd1a677cSIlya Dryomov 
390cd1a677cSIlya Dryomov /*
391cd1a677cSIlya Dryomov  * msgr2 authentication
392cd1a677cSIlya Dryomov  */
393cd1a677cSIlya Dryomov 
contains(const int * arr,int cnt,int val)394cd1a677cSIlya Dryomov static bool contains(const int *arr, int cnt, int val)
395cd1a677cSIlya Dryomov {
396cd1a677cSIlya Dryomov 	int i;
397cd1a677cSIlya Dryomov 
398cd1a677cSIlya Dryomov 	for (i = 0; i < cnt; i++) {
399cd1a677cSIlya Dryomov 		if (arr[i] == val)
400cd1a677cSIlya Dryomov 			return true;
401cd1a677cSIlya Dryomov 	}
402cd1a677cSIlya Dryomov 
403cd1a677cSIlya Dryomov 	return false;
404cd1a677cSIlya Dryomov }
405cd1a677cSIlya Dryomov 
encode_con_modes(void ** p,void * end,int pref_mode,int fallb_mode)406cd1a677cSIlya Dryomov static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode)
407cd1a677cSIlya Dryomov {
408cd1a677cSIlya Dryomov 	WARN_ON(pref_mode == CEPH_CON_MODE_UNKNOWN);
409cd1a677cSIlya Dryomov 	if (fallb_mode != CEPH_CON_MODE_UNKNOWN) {
410cd1a677cSIlya Dryomov 		ceph_encode_32_safe(p, end, 2, e_range);
411cd1a677cSIlya Dryomov 		ceph_encode_32_safe(p, end, pref_mode, e_range);
412cd1a677cSIlya Dryomov 		ceph_encode_32_safe(p, end, fallb_mode, e_range);
413cd1a677cSIlya Dryomov 	} else {
414cd1a677cSIlya Dryomov 		ceph_encode_32_safe(p, end, 1, e_range);
415cd1a677cSIlya Dryomov 		ceph_encode_32_safe(p, end, pref_mode, e_range);
416cd1a677cSIlya Dryomov 	}
417cd1a677cSIlya Dryomov 
418cd1a677cSIlya Dryomov 	return 0;
419cd1a677cSIlya Dryomov 
420cd1a677cSIlya Dryomov e_range:
421cd1a677cSIlya Dryomov 	return -ERANGE;
422cd1a677cSIlya Dryomov }
423cd1a677cSIlya Dryomov 
424cd1a677cSIlya Dryomov /*
425cd1a677cSIlya Dryomov  * Similar to ceph_auth_build_hello().
426cd1a677cSIlya Dryomov  */
ceph_auth_get_request(struct ceph_auth_client * ac,void * buf,int buf_len)427cd1a677cSIlya Dryomov int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len)
428cd1a677cSIlya Dryomov {
429cd1a677cSIlya Dryomov 	int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE;
430cd1a677cSIlya Dryomov 	void *end = buf + buf_len;
431cd1a677cSIlya Dryomov 	void *lenp;
432cd1a677cSIlya Dryomov 	void *p;
433cd1a677cSIlya Dryomov 	int ret;
434cd1a677cSIlya Dryomov 
435cd1a677cSIlya Dryomov 	mutex_lock(&ac->mutex);
436cd1a677cSIlya Dryomov 	if (ac->protocol == CEPH_AUTH_UNKNOWN) {
437cd1a677cSIlya Dryomov 		ret = init_protocol(ac, proto);
438cd1a677cSIlya Dryomov 		if (ret) {
439cd1a677cSIlya Dryomov 			pr_err("auth protocol '%s' init failed: %d\n",
440cd1a677cSIlya Dryomov 			       ceph_auth_proto_name(proto), ret);
441cd1a677cSIlya Dryomov 			goto out;
442cd1a677cSIlya Dryomov 		}
443cd1a677cSIlya Dryomov 	} else {
444cd1a677cSIlya Dryomov 		WARN_ON(ac->protocol != proto);
445cd1a677cSIlya Dryomov 		ac->ops->reset(ac);
446cd1a677cSIlya Dryomov 	}
447cd1a677cSIlya Dryomov 
448cd1a677cSIlya Dryomov 	p = buf;
449cd1a677cSIlya Dryomov 	ceph_encode_32_safe(&p, end, ac->protocol, e_range);
450cd1a677cSIlya Dryomov 	ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode);
451cd1a677cSIlya Dryomov 	if (ret)
452cd1a677cSIlya Dryomov 		goto out;
453cd1a677cSIlya Dryomov 
454cd1a677cSIlya Dryomov 	lenp = p;
455cd1a677cSIlya Dryomov 	p += 4;  /* space for len */
456cd1a677cSIlya Dryomov 
457cd1a677cSIlya Dryomov 	ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range);
458cd1a677cSIlya Dryomov 	ret = ceph_auth_entity_name_encode(ac->name, &p, end);
459cd1a677cSIlya Dryomov 	if (ret)
460cd1a677cSIlya Dryomov 		goto out;
461cd1a677cSIlya Dryomov 
462cd1a677cSIlya Dryomov 	ceph_encode_64_safe(&p, end, ac->global_id, e_range);
463cd1a677cSIlya Dryomov 	ceph_encode_32(&lenp, p - lenp - 4);
464cd1a677cSIlya Dryomov 	ret = p - buf;
465cd1a677cSIlya Dryomov 
466cd1a677cSIlya Dryomov out:
467cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
468cd1a677cSIlya Dryomov 	return ret;
469cd1a677cSIlya Dryomov 
470cd1a677cSIlya Dryomov e_range:
471cd1a677cSIlya Dryomov 	ret = -ERANGE;
472cd1a677cSIlya Dryomov 	goto out;
473cd1a677cSIlya Dryomov }
474cd1a677cSIlya Dryomov 
ceph_auth_handle_reply_more(struct ceph_auth_client * ac,void * reply,int reply_len,void * buf,int buf_len)475cd1a677cSIlya Dryomov int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply,
476cd1a677cSIlya Dryomov 				int reply_len, void *buf, int buf_len)
477cd1a677cSIlya Dryomov {
478cd1a677cSIlya Dryomov 	int ret;
479cd1a677cSIlya Dryomov 
480cd1a677cSIlya Dryomov 	mutex_lock(&ac->mutex);
48103af4c7bSIlya Dryomov 	ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len,
482cd1a677cSIlya Dryomov 				    NULL, NULL, NULL, NULL);
483cd1a677cSIlya Dryomov 	if (ret == -EAGAIN)
484cd1a677cSIlya Dryomov 		ret = build_request(ac, false, buf, buf_len);
485cd1a677cSIlya Dryomov 	else
486cd1a677cSIlya Dryomov 		WARN_ON(ret >= 0);
487cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
488cd1a677cSIlya Dryomov 	return ret;
489cd1a677cSIlya Dryomov }
490cd1a677cSIlya Dryomov 
ceph_auth_handle_reply_done(struct ceph_auth_client * ac,u64 global_id,void * reply,int reply_len,u8 * session_key,int * session_key_len,u8 * con_secret,int * con_secret_len)491cd1a677cSIlya Dryomov int ceph_auth_handle_reply_done(struct ceph_auth_client *ac,
492cd1a677cSIlya Dryomov 				u64 global_id, void *reply, int reply_len,
493cd1a677cSIlya Dryomov 				u8 *session_key, int *session_key_len,
494cd1a677cSIlya Dryomov 				u8 *con_secret, int *con_secret_len)
495cd1a677cSIlya Dryomov {
496cd1a677cSIlya Dryomov 	int ret;
497cd1a677cSIlya Dryomov 
498cd1a677cSIlya Dryomov 	mutex_lock(&ac->mutex);
49903af4c7bSIlya Dryomov 	ret = ac->ops->handle_reply(ac, global_id, reply, reply + reply_len,
500cd1a677cSIlya Dryomov 				    session_key, session_key_len,
501cd1a677cSIlya Dryomov 				    con_secret, con_secret_len);
50203af4c7bSIlya Dryomov 	WARN_ON(ret == -EAGAIN || ret > 0);
503cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
504cd1a677cSIlya Dryomov 	return ret;
505cd1a677cSIlya Dryomov }
506cd1a677cSIlya Dryomov 
ceph_auth_handle_bad_method(struct ceph_auth_client * ac,int used_proto,int result,const int * allowed_protos,int proto_cnt,const int * allowed_modes,int mode_cnt)507cd1a677cSIlya Dryomov bool ceph_auth_handle_bad_method(struct ceph_auth_client *ac,
508cd1a677cSIlya Dryomov 				 int used_proto, int result,
509cd1a677cSIlya Dryomov 				 const int *allowed_protos, int proto_cnt,
510cd1a677cSIlya Dryomov 				 const int *allowed_modes, int mode_cnt)
511cd1a677cSIlya Dryomov {
512cd1a677cSIlya Dryomov 	mutex_lock(&ac->mutex);
513cd1a677cSIlya Dryomov 	WARN_ON(used_proto != ac->protocol);
514cd1a677cSIlya Dryomov 
515cd1a677cSIlya Dryomov 	if (result == -EOPNOTSUPP) {
516cd1a677cSIlya Dryomov 		if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
517cd1a677cSIlya Dryomov 			pr_err("auth protocol '%s' not allowed\n",
518cd1a677cSIlya Dryomov 			       ceph_auth_proto_name(ac->protocol));
519cd1a677cSIlya Dryomov 			goto not_allowed;
520cd1a677cSIlya Dryomov 		}
521cd1a677cSIlya Dryomov 		if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
522cd1a677cSIlya Dryomov 		    (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
523cd1a677cSIlya Dryomov 		     !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
524cd1a677cSIlya Dryomov 			pr_err("preferred mode '%s' not allowed\n",
525cd1a677cSIlya Dryomov 			       ceph_con_mode_name(ac->preferred_mode));
526cd1a677cSIlya Dryomov 			if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
527cd1a677cSIlya Dryomov 				pr_err("no fallback mode\n");
528cd1a677cSIlya Dryomov 			else
529cd1a677cSIlya Dryomov 				pr_err("fallback mode '%s' not allowed\n",
530cd1a677cSIlya Dryomov 				       ceph_con_mode_name(ac->fallback_mode));
531cd1a677cSIlya Dryomov 			goto not_allowed;
532cd1a677cSIlya Dryomov 		}
533cd1a677cSIlya Dryomov 	}
534cd1a677cSIlya Dryomov 
535cd1a677cSIlya Dryomov 	WARN_ON(result == -EOPNOTSUPP || result >= 0);
536cd1a677cSIlya Dryomov 	pr_err("auth protocol '%s' msgr authentication failed: %d\n",
537cd1a677cSIlya Dryomov 	       ceph_auth_proto_name(ac->protocol), result);
538cd1a677cSIlya Dryomov 
539cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
540cd1a677cSIlya Dryomov 	return true;
541cd1a677cSIlya Dryomov 
542cd1a677cSIlya Dryomov not_allowed:
543cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
544cd1a677cSIlya Dryomov 	return false;
545cd1a677cSIlya Dryomov }
546cd1a677cSIlya Dryomov 
ceph_auth_get_authorizer(struct ceph_auth_client * ac,struct ceph_auth_handshake * auth,int peer_type,void * buf,int * buf_len)547cd1a677cSIlya Dryomov int ceph_auth_get_authorizer(struct ceph_auth_client *ac,
548cd1a677cSIlya Dryomov 			     struct ceph_auth_handshake *auth,
549cd1a677cSIlya Dryomov 			     int peer_type, void *buf, int *buf_len)
550cd1a677cSIlya Dryomov {
551cd1a677cSIlya Dryomov 	void *end = buf + *buf_len;
552cd1a677cSIlya Dryomov 	int pref_mode, fallb_mode;
553cd1a677cSIlya Dryomov 	int proto;
554cd1a677cSIlya Dryomov 	void *p;
555cd1a677cSIlya Dryomov 	int ret;
556cd1a677cSIlya Dryomov 
557cd1a677cSIlya Dryomov 	ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto,
558cd1a677cSIlya Dryomov 					 &pref_mode, &fallb_mode);
559cd1a677cSIlya Dryomov 	if (ret)
560cd1a677cSIlya Dryomov 		return ret;
561cd1a677cSIlya Dryomov 
562cd1a677cSIlya Dryomov 	p = buf;
563cd1a677cSIlya Dryomov 	ceph_encode_32_safe(&p, end, proto, e_range);
564cd1a677cSIlya Dryomov 	ret = encode_con_modes(&p, end, pref_mode, fallb_mode);
565cd1a677cSIlya Dryomov 	if (ret)
566cd1a677cSIlya Dryomov 		return ret;
567cd1a677cSIlya Dryomov 
568cd1a677cSIlya Dryomov 	ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
569cd1a677cSIlya Dryomov 	*buf_len = p - buf;
570cd1a677cSIlya Dryomov 	return 0;
571cd1a677cSIlya Dryomov 
572cd1a677cSIlya Dryomov e_range:
573cd1a677cSIlya Dryomov 	return -ERANGE;
574cd1a677cSIlya Dryomov }
575cd1a677cSIlya Dryomov EXPORT_SYMBOL(ceph_auth_get_authorizer);
576cd1a677cSIlya Dryomov 
ceph_auth_handle_svc_reply_more(struct ceph_auth_client * ac,struct ceph_auth_handshake * auth,void * reply,int reply_len,void * buf,int * buf_len)577cd1a677cSIlya Dryomov int ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac,
578cd1a677cSIlya Dryomov 				    struct ceph_auth_handshake *auth,
579cd1a677cSIlya Dryomov 				    void *reply, int reply_len,
580cd1a677cSIlya Dryomov 				    void *buf, int *buf_len)
581cd1a677cSIlya Dryomov {
582cd1a677cSIlya Dryomov 	void *end = buf + *buf_len;
583cd1a677cSIlya Dryomov 	void *p;
584cd1a677cSIlya Dryomov 	int ret;
585cd1a677cSIlya Dryomov 
586cd1a677cSIlya Dryomov 	ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer,
587cd1a677cSIlya Dryomov 						 reply, reply_len);
588cd1a677cSIlya Dryomov 	if (ret)
589cd1a677cSIlya Dryomov 		return ret;
590cd1a677cSIlya Dryomov 
591cd1a677cSIlya Dryomov 	p = buf;
592cd1a677cSIlya Dryomov 	ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
593cd1a677cSIlya Dryomov 	*buf_len = p - buf;
594cd1a677cSIlya Dryomov 	return 0;
595cd1a677cSIlya Dryomov 
596cd1a677cSIlya Dryomov e_range:
597cd1a677cSIlya Dryomov 	return -ERANGE;
598cd1a677cSIlya Dryomov }
599cd1a677cSIlya Dryomov EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more);
600cd1a677cSIlya Dryomov 
ceph_auth_handle_svc_reply_done(struct ceph_auth_client * ac,struct ceph_auth_handshake * auth,void * reply,int reply_len,u8 * session_key,int * session_key_len,u8 * con_secret,int * con_secret_len)601cd1a677cSIlya Dryomov int ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac,
602cd1a677cSIlya Dryomov 				    struct ceph_auth_handshake *auth,
603cd1a677cSIlya Dryomov 				    void *reply, int reply_len,
604cd1a677cSIlya Dryomov 				    u8 *session_key, int *session_key_len,
605cd1a677cSIlya Dryomov 				    u8 *con_secret, int *con_secret_len)
606cd1a677cSIlya Dryomov {
607cd1a677cSIlya Dryomov 	return ceph_auth_verify_authorizer_reply(ac, auth->authorizer,
608cd1a677cSIlya Dryomov 		reply, reply_len, session_key, session_key_len,
609cd1a677cSIlya Dryomov 		con_secret, con_secret_len);
610cd1a677cSIlya Dryomov }
611cd1a677cSIlya Dryomov EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done);
612cd1a677cSIlya Dryomov 
ceph_auth_handle_bad_authorizer(struct ceph_auth_client * ac,int peer_type,int used_proto,int result,const int * allowed_protos,int proto_cnt,const int * allowed_modes,int mode_cnt)613cd1a677cSIlya Dryomov bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac,
614cd1a677cSIlya Dryomov 				     int peer_type, int used_proto, int result,
615cd1a677cSIlya Dryomov 				     const int *allowed_protos, int proto_cnt,
616cd1a677cSIlya Dryomov 				     const int *allowed_modes, int mode_cnt)
617cd1a677cSIlya Dryomov {
618cd1a677cSIlya Dryomov 	mutex_lock(&ac->mutex);
619cd1a677cSIlya Dryomov 	WARN_ON(used_proto != ac->protocol);
620cd1a677cSIlya Dryomov 
621cd1a677cSIlya Dryomov 	if (result == -EOPNOTSUPP) {
622cd1a677cSIlya Dryomov 		if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
623cd1a677cSIlya Dryomov 			pr_err("auth protocol '%s' not allowed by %s\n",
624cd1a677cSIlya Dryomov 			       ceph_auth_proto_name(ac->protocol),
625cd1a677cSIlya Dryomov 			       ceph_entity_type_name(peer_type));
626cd1a677cSIlya Dryomov 			goto not_allowed;
627cd1a677cSIlya Dryomov 		}
628cd1a677cSIlya Dryomov 		if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
629cd1a677cSIlya Dryomov 		    (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
630cd1a677cSIlya Dryomov 		     !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
631cd1a677cSIlya Dryomov 			pr_err("preferred mode '%s' not allowed by %s\n",
632cd1a677cSIlya Dryomov 			       ceph_con_mode_name(ac->preferred_mode),
633cd1a677cSIlya Dryomov 			       ceph_entity_type_name(peer_type));
634cd1a677cSIlya Dryomov 			if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
635cd1a677cSIlya Dryomov 				pr_err("no fallback mode\n");
636cd1a677cSIlya Dryomov 			else
637cd1a677cSIlya Dryomov 				pr_err("fallback mode '%s' not allowed by %s\n",
638cd1a677cSIlya Dryomov 				       ceph_con_mode_name(ac->fallback_mode),
639cd1a677cSIlya Dryomov 				       ceph_entity_type_name(peer_type));
640cd1a677cSIlya Dryomov 			goto not_allowed;
641cd1a677cSIlya Dryomov 		}
642cd1a677cSIlya Dryomov 	}
643cd1a677cSIlya Dryomov 
644cd1a677cSIlya Dryomov 	WARN_ON(result == -EOPNOTSUPP || result >= 0);
645cd1a677cSIlya Dryomov 	pr_err("auth protocol '%s' authorization to %s failed: %d\n",
646cd1a677cSIlya Dryomov 	       ceph_auth_proto_name(ac->protocol),
647cd1a677cSIlya Dryomov 	       ceph_entity_type_name(peer_type), result);
648cd1a677cSIlya Dryomov 
649cd1a677cSIlya Dryomov 	if (ac->ops->invalidate_authorizer)
650cd1a677cSIlya Dryomov 		ac->ops->invalidate_authorizer(ac, peer_type);
651cd1a677cSIlya Dryomov 
652cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
653cd1a677cSIlya Dryomov 	return true;
654cd1a677cSIlya Dryomov 
655cd1a677cSIlya Dryomov not_allowed:
656cd1a677cSIlya Dryomov 	mutex_unlock(&ac->mutex);
657cd1a677cSIlya Dryomov 	return false;
658cd1a677cSIlya Dryomov }
659cd1a677cSIlya Dryomov EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer);
660