auth.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/ceph/ceph_debug.h>
  3. #include <linux/module.h>
  4. #include <linux/err.h>
  5. #include <linux/slab.h>
  6. #include <linux/ceph/types.h>
  7. #include <linux/ceph/decode.h>
  8. #include <linux/ceph/libceph.h>
  9. #include <linux/ceph/messenger.h>
  10. #include "auth_none.h"
  11. #include "auth_x.h"
  12. /*
  13. * get protocol handler
  14. */
  15. static u32 supported_protocols[] = {
  16. CEPH_AUTH_NONE,
  17. CEPH_AUTH_CEPHX
  18. };
  19. static int init_protocol(struct ceph_auth_client *ac, int proto)
  20. {
  21. dout("%s proto %d\n", __func__, proto);
  22. switch (proto) {
  23. case CEPH_AUTH_NONE:
  24. return ceph_auth_none_init(ac);
  25. case CEPH_AUTH_CEPHX:
  26. return ceph_x_init(ac);
  27. default:
  28. pr_err("bad auth protocol %d\n", proto);
  29. return -EINVAL;
  30. }
  31. }
  32. void ceph_auth_set_global_id(struct ceph_auth_client *ac, u64 global_id)
  33. {
  34. dout("%s global_id %llu\n", __func__, global_id);
  35. if (!global_id)
  36. pr_err("got zero global_id\n");
  37. if (ac->global_id && global_id != ac->global_id)
  38. pr_err("global_id changed from %llu to %llu\n", ac->global_id,
  39. global_id);
  40. ac->global_id = global_id;
  41. }
  42. /*
  43. * setup, teardown.
  44. */
  45. struct ceph_auth_client *ceph_auth_init(const char *name,
  46. const struct ceph_crypto_key *key,
  47. const int *con_modes)
  48. {
  49. struct ceph_auth_client *ac;
  50. ac = kzalloc(sizeof(*ac), GFP_NOFS);
  51. if (!ac)
  52. return ERR_PTR(-ENOMEM);
  53. mutex_init(&ac->mutex);
  54. ac->negotiating = true;
  55. if (name)
  56. ac->name = name;
  57. else
  58. ac->name = CEPH_AUTH_NAME_DEFAULT;
  59. ac->key = key;
  60. ac->preferred_mode = con_modes[0];
  61. ac->fallback_mode = con_modes[1];
  62. dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__,
  63. ac->name, ac->preferred_mode, ac->fallback_mode);
  64. return ac;
  65. }
  66. void ceph_auth_destroy(struct ceph_auth_client *ac)
  67. {
  68. dout("auth_destroy %p\n", ac);
  69. if (ac->ops)
  70. ac->ops->destroy(ac);
  71. kfree(ac);
  72. }
  73. /*
  74. * Reset occurs when reconnecting to the monitor.
  75. */
  76. void ceph_auth_reset(struct ceph_auth_client *ac)
  77. {
  78. mutex_lock(&ac->mutex);
  79. dout("auth_reset %p\n", ac);
  80. if (ac->ops && !ac->negotiating)
  81. ac->ops->reset(ac);
  82. ac->negotiating = true;
  83. mutex_unlock(&ac->mutex);
  84. }
  85. /*
  86. * EntityName, not to be confused with entity_name_t
  87. */
  88. int ceph_auth_entity_name_encode(const char *name, void **p, void *end)
  89. {
  90. int len = strlen(name);
  91. if (*p + 2*sizeof(u32) + len > end)
  92. return -ERANGE;
  93. ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
  94. ceph_encode_32(p, len);
  95. ceph_encode_copy(p, name, len);
  96. return 0;
  97. }
  98. /*
  99. * Initiate protocol negotiation with monitor. Include entity name
  100. * and list supported protocols.
  101. */
  102. int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
  103. {
  104. struct ceph_mon_request_header *monhdr = buf;
  105. void *p = monhdr + 1, *end = buf + len, *lenp;
  106. int i, num;
  107. int ret;
  108. mutex_lock(&ac->mutex);
  109. dout("auth_build_hello\n");
  110. monhdr->have_version = 0;
  111. monhdr->session_mon = cpu_to_le16(-1);
  112. monhdr->session_mon_tid = 0;
  113. ceph_encode_32(&p, CEPH_AUTH_UNKNOWN); /* no protocol, yet */
  114. lenp = p;
  115. p += sizeof(u32);
  116. ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
  117. ceph_encode_8(&p, 1);
  118. num = ARRAY_SIZE(supported_protocols);
  119. ceph_encode_32(&p, num);
  120. ceph_decode_need(&p, end, num * sizeof(u32), bad);
  121. for (i = 0; i < num; i++)
  122. ceph_encode_32(&p, supported_protocols[i]);
  123. ret = ceph_auth_entity_name_encode(ac->name, &p, end);
  124. if (ret < 0)
  125. goto out;
  126. ceph_decode_need(&p, end, sizeof(u64), bad);
  127. ceph_encode_64(&p, ac->global_id);
  128. ceph_encode_32(&lenp, p - lenp - sizeof(u32));
  129. ret = p - buf;
  130. out:
  131. mutex_unlock(&ac->mutex);
  132. return ret;
  133. bad:
  134. ret = -ERANGE;
  135. goto out;
  136. }
  137. static int build_request(struct ceph_auth_client *ac, bool add_header,
  138. void *buf, int buf_len)
  139. {
  140. void *end = buf + buf_len;
  141. void *p;
  142. int ret;
  143. p = buf;
  144. if (add_header) {
  145. /* struct ceph_mon_request_header + protocol */
  146. ceph_encode_64_safe(&p, end, 0, e_range);
  147. ceph_encode_16_safe(&p, end, -1, e_range);
  148. ceph_encode_64_safe(&p, end, 0, e_range);
  149. ceph_encode_32_safe(&p, end, ac->protocol, e_range);
  150. }
  151. ceph_encode_need(&p, end, sizeof(u32), e_range);
  152. ret = ac->ops->build_request(ac, p + sizeof(u32), end);
  153. if (ret < 0) {
  154. pr_err("auth protocol '%s' building request failed: %d\n",
  155. ceph_auth_proto_name(ac->protocol), ret);
  156. return ret;
  157. }
  158. dout(" built request %d bytes\n", ret);
  159. ceph_encode_32(&p, ret);
  160. return p + ret - buf;
  161. e_range:
  162. return -ERANGE;
  163. }
  164. /*
  165. * Handle auth message from monitor.
  166. */
  167. int ceph_handle_auth_reply(struct ceph_auth_client *ac,
  168. void *buf, size_t len,
  169. void *reply_buf, size_t reply_len)
  170. {
  171. void *p = buf;
  172. void *end = buf + len;
  173. int protocol;
  174. s32 result;
  175. u64 global_id;
  176. void *payload, *payload_end;
  177. int payload_len;
  178. char *result_msg;
  179. int result_msg_len;
  180. int ret = -EINVAL;
  181. mutex_lock(&ac->mutex);
  182. dout("handle_auth_reply %p %p\n", p, end);
  183. ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
  184. protocol = ceph_decode_32(&p);
  185. result = ceph_decode_32(&p);
  186. global_id = ceph_decode_64(&p);
  187. payload_len = ceph_decode_32(&p);
  188. payload = p;
  189. p += payload_len;
  190. ceph_decode_need(&p, end, sizeof(u32), bad);
  191. result_msg_len = ceph_decode_32(&p);
  192. result_msg = p;
  193. p += result_msg_len;
  194. if (p != end)
  195. goto bad;
  196. dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
  197. result_msg, global_id, payload_len);
  198. payload_end = payload + payload_len;
  199. if (ac->negotiating) {
  200. /* server does not support our protocols? */
  201. if (!protocol && result < 0) {
  202. ret = result;
  203. goto out;
  204. }
  205. /* set up (new) protocol handler? */
  206. if (ac->protocol && ac->protocol != protocol) {
  207. ac->ops->destroy(ac);
  208. ac->protocol = 0;
  209. ac->ops = NULL;
  210. }
  211. if (ac->protocol != protocol) {
  212. ret = init_protocol(ac, protocol);
  213. if (ret) {
  214. pr_err("auth protocol '%s' init failed: %d\n",
  215. ceph_auth_proto_name(protocol), ret);
  216. goto out;
  217. }
  218. }
  219. ac->negotiating = false;
  220. }
  221. if (result) {
  222. pr_err("auth protocol '%s' mauth authentication failed: %d\n",
  223. ceph_auth_proto_name(ac->protocol), result);
  224. ret = result;
  225. goto out;
  226. }
  227. ret = ac->ops->handle_reply(ac, global_id, payload, payload_end,
  228. NULL, NULL, NULL, NULL);
  229. if (ret == -EAGAIN) {
  230. ret = build_request(ac, true, reply_buf, reply_len);
  231. goto out;
  232. } else if (ret) {
  233. goto out;
  234. }
  235. out:
  236. mutex_unlock(&ac->mutex);
  237. return ret;
  238. bad:
  239. pr_err("failed to decode auth msg\n");
  240. ret = -EINVAL;
  241. goto out;
  242. }
  243. int ceph_build_auth(struct ceph_auth_client *ac,
  244. void *msg_buf, size_t msg_len)
  245. {
  246. int ret = 0;
  247. mutex_lock(&ac->mutex);
  248. if (ac->ops->should_authenticate(ac))
  249. ret = build_request(ac, true, msg_buf, msg_len);
  250. mutex_unlock(&ac->mutex);
  251. return ret;
  252. }
  253. int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
  254. {
  255. int ret = 0;
  256. mutex_lock(&ac->mutex);
  257. if (ac->ops)
  258. ret = ac->ops->is_authenticated(ac);
  259. mutex_unlock(&ac->mutex);
  260. return ret;
  261. }
  262. EXPORT_SYMBOL(ceph_auth_is_authenticated);
  263. int __ceph_auth_get_authorizer(struct ceph_auth_client *ac,
  264. struct ceph_auth_handshake *auth,
  265. int peer_type, bool force_new,
  266. int *proto, int *pref_mode, int *fallb_mode)
  267. {
  268. int ret;
  269. mutex_lock(&ac->mutex);
  270. if (force_new && auth->authorizer) {
  271. ceph_auth_destroy_authorizer(auth->authorizer);
  272. auth->authorizer = NULL;
  273. }
  274. if (!auth->authorizer)
  275. ret = ac->ops->create_authorizer(ac, peer_type, auth);
  276. else if (ac->ops->update_authorizer)
  277. ret = ac->ops->update_authorizer(ac, peer_type, auth);
  278. else
  279. ret = 0;
  280. if (ret)
  281. goto out;
  282. *proto = ac->protocol;
  283. if (pref_mode && fallb_mode) {
  284. *pref_mode = ac->preferred_mode;
  285. *fallb_mode = ac->fallback_mode;
  286. }
  287. out:
  288. mutex_unlock(&ac->mutex);
  289. return ret;
  290. }
  291. EXPORT_SYMBOL(__ceph_auth_get_authorizer);
  292. void ceph_auth_destroy_authorizer(struct ceph_authorizer *a)
  293. {
  294. a->destroy(a);
  295. }
  296. EXPORT_SYMBOL(ceph_auth_destroy_authorizer);
  297. int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac,
  298. struct ceph_authorizer *a,
  299. void *challenge_buf,
  300. int challenge_buf_len)
  301. {
  302. int ret = 0;
  303. mutex_lock(&ac->mutex);
  304. if (ac->ops && ac->ops->add_authorizer_challenge)
  305. ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf,
  306. challenge_buf_len);
  307. mutex_unlock(&ac->mutex);
  308. return ret;
  309. }
  310. EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge);
  311. int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
  312. struct ceph_authorizer *a,
  313. void *reply, int reply_len,
  314. u8 *session_key, int *session_key_len,
  315. u8 *con_secret, int *con_secret_len)
  316. {
  317. int ret = 0;
  318. mutex_lock(&ac->mutex);
  319. if (ac->ops && ac->ops->verify_authorizer_reply)
  320. ret = ac->ops->verify_authorizer_reply(ac, a,
  321. reply, reply_len, session_key, session_key_len,
  322. con_secret, con_secret_len);
  323. mutex_unlock(&ac->mutex);
  324. return ret;
  325. }
  326. EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply);
  327. void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type)
  328. {
  329. mutex_lock(&ac->mutex);
  330. if (ac->ops && ac->ops->invalidate_authorizer)
  331. ac->ops->invalidate_authorizer(ac, peer_type);
  332. mutex_unlock(&ac->mutex);
  333. }
  334. EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
  335. /*
  336. * msgr2 authentication
  337. */
  338. static bool contains(const int *arr, int cnt, int val)
  339. {
  340. int i;
  341. for (i = 0; i < cnt; i++) {
  342. if (arr[i] == val)
  343. return true;
  344. }
  345. return false;
  346. }
  347. static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode)
  348. {
  349. WARN_ON(pref_mode == CEPH_CON_MODE_UNKNOWN);
  350. if (fallb_mode != CEPH_CON_MODE_UNKNOWN) {
  351. ceph_encode_32_safe(p, end, 2, e_range);
  352. ceph_encode_32_safe(p, end, pref_mode, e_range);
  353. ceph_encode_32_safe(p, end, fallb_mode, e_range);
  354. } else {
  355. ceph_encode_32_safe(p, end, 1, e_range);
  356. ceph_encode_32_safe(p, end, pref_mode, e_range);
  357. }
  358. return 0;
  359. e_range:
  360. return -ERANGE;
  361. }
  362. /*
  363. * Similar to ceph_auth_build_hello().
  364. */
  365. int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len)
  366. {
  367. int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE;
  368. void *end = buf + buf_len;
  369. void *lenp;
  370. void *p;
  371. int ret;
  372. mutex_lock(&ac->mutex);
  373. if (ac->protocol == CEPH_AUTH_UNKNOWN) {
  374. ret = init_protocol(ac, proto);
  375. if (ret) {
  376. pr_err("auth protocol '%s' init failed: %d\n",
  377. ceph_auth_proto_name(proto), ret);
  378. goto out;
  379. }
  380. } else {
  381. WARN_ON(ac->protocol != proto);
  382. ac->ops->reset(ac);
  383. }
  384. p = buf;
  385. ceph_encode_32_safe(&p, end, ac->protocol, e_range);
  386. ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode);
  387. if (ret)
  388. goto out;
  389. lenp = p;
  390. p += 4; /* space for len */
  391. ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range);
  392. ret = ceph_auth_entity_name_encode(ac->name, &p, end);
  393. if (ret)
  394. goto out;
  395. ceph_encode_64_safe(&p, end, ac->global_id, e_range);
  396. ceph_encode_32(&lenp, p - lenp - 4);
  397. ret = p - buf;
  398. out:
  399. mutex_unlock(&ac->mutex);
  400. return ret;
  401. e_range:
  402. ret = -ERANGE;
  403. goto out;
  404. }
  405. int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply,
  406. int reply_len, void *buf, int buf_len)
  407. {
  408. int ret;
  409. mutex_lock(&ac->mutex);
  410. ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len,
  411. NULL, NULL, NULL, NULL);
  412. if (ret == -EAGAIN)
  413. ret = build_request(ac, false, buf, buf_len);
  414. else
  415. WARN_ON(ret >= 0);
  416. mutex_unlock(&ac->mutex);
  417. return ret;
  418. }
  419. int ceph_auth_handle_reply_done(struct ceph_auth_client *ac,
  420. u64 global_id, void *reply, int reply_len,
  421. u8 *session_key, int *session_key_len,
  422. u8 *con_secret, int *con_secret_len)
  423. {
  424. int ret;
  425. mutex_lock(&ac->mutex);
  426. ret = ac->ops->handle_reply(ac, global_id, reply, reply + reply_len,
  427. session_key, session_key_len,
  428. con_secret, con_secret_len);
  429. WARN_ON(ret == -EAGAIN || ret > 0);
  430. mutex_unlock(&ac->mutex);
  431. return ret;
  432. }
  433. bool ceph_auth_handle_bad_method(struct ceph_auth_client *ac,
  434. int used_proto, int result,
  435. const int *allowed_protos, int proto_cnt,
  436. const int *allowed_modes, int mode_cnt)
  437. {
  438. mutex_lock(&ac->mutex);
  439. WARN_ON(used_proto != ac->protocol);
  440. if (result == -EOPNOTSUPP) {
  441. if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
  442. pr_err("auth protocol '%s' not allowed\n",
  443. ceph_auth_proto_name(ac->protocol));
  444. goto not_allowed;
  445. }
  446. if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
  447. (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
  448. !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
  449. pr_err("preferred mode '%s' not allowed\n",
  450. ceph_con_mode_name(ac->preferred_mode));
  451. if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
  452. pr_err("no fallback mode\n");
  453. else
  454. pr_err("fallback mode '%s' not allowed\n",
  455. ceph_con_mode_name(ac->fallback_mode));
  456. goto not_allowed;
  457. }
  458. }
  459. WARN_ON(result == -EOPNOTSUPP || result >= 0);
  460. pr_err("auth protocol '%s' msgr authentication failed: %d\n",
  461. ceph_auth_proto_name(ac->protocol), result);
  462. mutex_unlock(&ac->mutex);
  463. return true;
  464. not_allowed:
  465. mutex_unlock(&ac->mutex);
  466. return false;
  467. }
  468. int ceph_auth_get_authorizer(struct ceph_auth_client *ac,
  469. struct ceph_auth_handshake *auth,
  470. int peer_type, void *buf, int *buf_len)
  471. {
  472. void *end = buf + *buf_len;
  473. int pref_mode, fallb_mode;
  474. int proto;
  475. void *p;
  476. int ret;
  477. ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto,
  478. &pref_mode, &fallb_mode);
  479. if (ret)
  480. return ret;
  481. p = buf;
  482. ceph_encode_32_safe(&p, end, proto, e_range);
  483. ret = encode_con_modes(&p, end, pref_mode, fallb_mode);
  484. if (ret)
  485. return ret;
  486. ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
  487. *buf_len = p - buf;
  488. return 0;
  489. e_range:
  490. return -ERANGE;
  491. }
  492. EXPORT_SYMBOL(ceph_auth_get_authorizer);
  493. int ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac,
  494. struct ceph_auth_handshake *auth,
  495. void *reply, int reply_len,
  496. void *buf, int *buf_len)
  497. {
  498. void *end = buf + *buf_len;
  499. void *p;
  500. int ret;
  501. ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer,
  502. reply, reply_len);
  503. if (ret)
  504. return ret;
  505. p = buf;
  506. ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range);
  507. *buf_len = p - buf;
  508. return 0;
  509. e_range:
  510. return -ERANGE;
  511. }
  512. EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more);
  513. int ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac,
  514. struct ceph_auth_handshake *auth,
  515. void *reply, int reply_len,
  516. u8 *session_key, int *session_key_len,
  517. u8 *con_secret, int *con_secret_len)
  518. {
  519. return ceph_auth_verify_authorizer_reply(ac, auth->authorizer,
  520. reply, reply_len, session_key, session_key_len,
  521. con_secret, con_secret_len);
  522. }
  523. EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done);
  524. bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac,
  525. int peer_type, int used_proto, int result,
  526. const int *allowed_protos, int proto_cnt,
  527. const int *allowed_modes, int mode_cnt)
  528. {
  529. mutex_lock(&ac->mutex);
  530. WARN_ON(used_proto != ac->protocol);
  531. if (result == -EOPNOTSUPP) {
  532. if (!contains(allowed_protos, proto_cnt, ac->protocol)) {
  533. pr_err("auth protocol '%s' not allowed by %s\n",
  534. ceph_auth_proto_name(ac->protocol),
  535. ceph_entity_type_name(peer_type));
  536. goto not_allowed;
  537. }
  538. if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) &&
  539. (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN ||
  540. !contains(allowed_modes, mode_cnt, ac->fallback_mode))) {
  541. pr_err("preferred mode '%s' not allowed by %s\n",
  542. ceph_con_mode_name(ac->preferred_mode),
  543. ceph_entity_type_name(peer_type));
  544. if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN)
  545. pr_err("no fallback mode\n");
  546. else
  547. pr_err("fallback mode '%s' not allowed by %s\n",
  548. ceph_con_mode_name(ac->fallback_mode),
  549. ceph_entity_type_name(peer_type));
  550. goto not_allowed;
  551. }
  552. }
  553. WARN_ON(result == -EOPNOTSUPP || result >= 0);
  554. pr_err("auth protocol '%s' authorization to %s failed: %d\n",
  555. ceph_auth_proto_name(ac->protocol),
  556. ceph_entity_type_name(peer_type), result);
  557. if (ac->ops->invalidate_authorizer)
  558. ac->ops->invalidate_authorizer(ac, peer_type);
  559. mutex_unlock(&ac->mutex);
  560. return true;
  561. not_allowed:
  562. mutex_unlock(&ac->mutex);
  563. return false;
  564. }
  565. EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer);