auth_x.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/ceph/ceph_debug.h>
  3. #include <linux/err.h>
  4. #include <linux/module.h>
  5. #include <linux/random.h>
  6. #include <linux/slab.h>
  7. #include <linux/ceph/decode.h>
  8. #include <linux/ceph/auth.h>
  9. #include <linux/ceph/ceph_features.h>
  10. #include <linux/ceph/libceph.h>
  11. #include <linux/ceph/messenger.h>
  12. #include "crypto.h"
  13. #include "auth_x.h"
  14. #include "auth_x_protocol.h"
  15. static const u32 ticket_key_usages[] = {
  16. CEPHX_KEY_USAGE_TICKET_SESSION_KEY,
  17. CEPHX_KEY_USAGE_TICKET_BLOB,
  18. CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET
  19. };
  20. static const u32 authorizer_key_usages[] = {
  21. CEPHX_KEY_USAGE_AUTHORIZE,
  22. CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE,
  23. CEPHX_KEY_USAGE_AUTHORIZE_REPLY
  24. };
  25. static const u32 client_key_usages[] = {
  26. CEPHX_KEY_USAGE_TICKET_SESSION_KEY
  27. };
  28. static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
  29. static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
  30. {
  31. struct ceph_x_info *xi = ac->private;
  32. int missing;
  33. int need; /* missing + need renewal */
  34. ceph_x_validate_tickets(ac, &need);
  35. missing = ac->want_keys & ~xi->have_keys;
  36. WARN_ON((need & missing) != missing);
  37. dout("%s want 0x%x have 0x%x missing 0x%x -> %d\n", __func__,
  38. ac->want_keys, xi->have_keys, missing, !missing);
  39. return !missing;
  40. }
  41. static int ceph_x_should_authenticate(struct ceph_auth_client *ac)
  42. {
  43. struct ceph_x_info *xi = ac->private;
  44. int need;
  45. ceph_x_validate_tickets(ac, &need);
  46. dout("%s want 0x%x have 0x%x need 0x%x -> %d\n", __func__,
  47. ac->want_keys, xi->have_keys, need, !!need);
  48. return !!need;
  49. }
  50. static int __ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
  51. {
  52. return ceph_crypt_data_offset(key) +
  53. sizeof(struct ceph_x_encrypt_header);
  54. }
  55. static int ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
  56. {
  57. return sizeof(u32) + __ceph_x_encrypt_offset(key);
  58. }
  59. /*
  60. * AES: ciphertext_len | hdr | data... | padding
  61. * AES256KRB5: ciphertext_len | confounder | hdr | data... | hmac
  62. */
  63. static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key,
  64. int data_len)
  65. {
  66. int encrypt_len = sizeof(struct ceph_x_encrypt_header) + data_len;
  67. return sizeof(u32) + ceph_crypt_buflen(key, encrypt_len);
  68. }
  69. static int ceph_x_encrypt(const struct ceph_crypto_key *key, int usage_slot,
  70. void *buf, int buf_len, int plaintext_len)
  71. {
  72. struct ceph_x_encrypt_header *hdr;
  73. int ciphertext_len;
  74. int ret;
  75. hdr = buf + sizeof(u32) + ceph_crypt_data_offset(key);
  76. hdr->struct_v = 1;
  77. hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC);
  78. ret = ceph_crypt(key, usage_slot, true, buf + sizeof(u32),
  79. buf_len - sizeof(u32), plaintext_len + sizeof(*hdr),
  80. &ciphertext_len);
  81. if (ret)
  82. return ret;
  83. ceph_encode_32(&buf, ciphertext_len);
  84. return sizeof(u32) + ciphertext_len;
  85. }
  86. static int __ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot,
  87. void *p, int ciphertext_len)
  88. {
  89. struct ceph_x_encrypt_header *hdr;
  90. int plaintext_len;
  91. int ret;
  92. ret = ceph_crypt(key, usage_slot, false, p, ciphertext_len,
  93. ciphertext_len, &plaintext_len);
  94. if (ret)
  95. return ret;
  96. hdr = p + ceph_crypt_data_offset(key);
  97. if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) {
  98. pr_err("%s bad magic\n", __func__);
  99. return -EINVAL;
  100. }
  101. return plaintext_len - sizeof(*hdr);
  102. }
  103. static int ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot,
  104. void **p, void *end)
  105. {
  106. int ciphertext_len;
  107. int ret;
  108. ceph_decode_32_safe(p, end, ciphertext_len, e_inval);
  109. ceph_decode_need(p, end, ciphertext_len, e_inval);
  110. ret = __ceph_x_decrypt(key, usage_slot, *p, ciphertext_len);
  111. if (ret < 0)
  112. return ret;
  113. *p += ciphertext_len;
  114. return ret;
  115. e_inval:
  116. return -EINVAL;
  117. }
  118. /*
  119. * get existing (or insert new) ticket handler
  120. */
  121. static struct ceph_x_ticket_handler *
  122. get_ticket_handler(struct ceph_auth_client *ac, int service)
  123. {
  124. struct ceph_x_ticket_handler *th;
  125. struct ceph_x_info *xi = ac->private;
  126. struct rb_node *parent = NULL, **p = &xi->ticket_handlers.rb_node;
  127. while (*p) {
  128. parent = *p;
  129. th = rb_entry(parent, struct ceph_x_ticket_handler, node);
  130. if (service < th->service)
  131. p = &(*p)->rb_left;
  132. else if (service > th->service)
  133. p = &(*p)->rb_right;
  134. else
  135. return th;
  136. }
  137. /* add it */
  138. th = kzalloc_obj(*th, GFP_NOFS);
  139. if (!th)
  140. return ERR_PTR(-ENOMEM);
  141. th->service = service;
  142. rb_link_node(&th->node, parent, p);
  143. rb_insert_color(&th->node, &xi->ticket_handlers);
  144. return th;
  145. }
  146. static void remove_ticket_handler(struct ceph_auth_client *ac,
  147. struct ceph_x_ticket_handler *th)
  148. {
  149. struct ceph_x_info *xi = ac->private;
  150. dout("remove_ticket_handler %p %d\n", th, th->service);
  151. rb_erase(&th->node, &xi->ticket_handlers);
  152. ceph_crypto_key_destroy(&th->session_key);
  153. if (th->ticket_blob)
  154. ceph_buffer_put(th->ticket_blob);
  155. kfree(th);
  156. }
  157. static int process_one_ticket(struct ceph_auth_client *ac,
  158. struct ceph_crypto_key *secret,
  159. void **p, void *end)
  160. {
  161. struct ceph_x_info *xi = ac->private;
  162. int type;
  163. u8 tkt_struct_v, blob_struct_v;
  164. struct ceph_x_ticket_handler *th;
  165. void *dp, *dend;
  166. int dlen;
  167. char is_enc;
  168. struct timespec64 validity;
  169. void *tp, *tpend;
  170. void **ptp;
  171. struct ceph_crypto_key new_session_key = { 0 };
  172. struct ceph_buffer *new_ticket_blob;
  173. time64_t new_expires, new_renew_after;
  174. u64 new_secret_id;
  175. int ret;
  176. ceph_decode_need(p, end, sizeof(u32) + 1, bad);
  177. type = ceph_decode_32(p);
  178. dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
  179. tkt_struct_v = ceph_decode_8(p);
  180. if (tkt_struct_v != 1)
  181. goto bad;
  182. th = get_ticket_handler(ac, type);
  183. if (IS_ERR(th)) {
  184. ret = PTR_ERR(th);
  185. goto out;
  186. }
  187. /* blob for me */
  188. dp = *p + ceph_x_encrypt_offset(secret);
  189. ret = ceph_x_decrypt(secret,
  190. 0 /* CEPHX_KEY_USAGE_TICKET_SESSION_KEY */,
  191. p, end);
  192. if (ret < 0)
  193. goto out;
  194. dout(" decrypted %d bytes\n", ret);
  195. dend = dp + ret;
  196. ceph_decode_8_safe(&dp, dend, tkt_struct_v, bad);
  197. if (tkt_struct_v != 1)
  198. goto bad;
  199. ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
  200. if (ret)
  201. goto out;
  202. ret = ceph_crypto_key_prepare(&new_session_key, ticket_key_usages,
  203. ARRAY_SIZE(ticket_key_usages));
  204. if (ret)
  205. goto out;
  206. ceph_decode_need(&dp, dend, sizeof(struct ceph_timespec), bad);
  207. ceph_decode_timespec64(&validity, dp);
  208. dp += sizeof(struct ceph_timespec);
  209. new_expires = ktime_get_real_seconds() + validity.tv_sec;
  210. new_renew_after = new_expires - (validity.tv_sec / 4);
  211. dout(" expires=%llu renew_after=%llu\n", new_expires,
  212. new_renew_after);
  213. /* ticket blob for service */
  214. ceph_decode_8_safe(p, end, is_enc, bad);
  215. if (is_enc) {
  216. /* encrypted */
  217. tp = *p + ceph_x_encrypt_offset(&th->session_key);
  218. ret = ceph_x_decrypt(&th->session_key,
  219. 1 /* CEPHX_KEY_USAGE_TICKET_BLOB */,
  220. p, end);
  221. if (ret < 0)
  222. goto out;
  223. dout(" encrypted ticket, decrypted %d bytes\n", ret);
  224. ptp = &tp;
  225. tpend = tp + ret;
  226. } else {
  227. /* unencrypted */
  228. ptp = p;
  229. tpend = end;
  230. }
  231. ceph_decode_32_safe(ptp, tpend, dlen, bad);
  232. dout(" ticket blob is %d bytes\n", dlen);
  233. ceph_decode_need(ptp, tpend, 1 + sizeof(u64), bad);
  234. blob_struct_v = ceph_decode_8(ptp);
  235. if (blob_struct_v != 1)
  236. goto bad;
  237. new_secret_id = ceph_decode_64(ptp);
  238. ret = ceph_decode_buffer(&new_ticket_blob, ptp, tpend);
  239. if (ret)
  240. goto out;
  241. /* all is well, update our ticket */
  242. ceph_crypto_key_destroy(&th->session_key);
  243. if (th->ticket_blob)
  244. ceph_buffer_put(th->ticket_blob);
  245. th->session_key = new_session_key;
  246. th->ticket_blob = new_ticket_blob;
  247. th->secret_id = new_secret_id;
  248. th->expires = new_expires;
  249. th->renew_after = new_renew_after;
  250. th->have_key = true;
  251. dout(" got ticket service %d (%s) secret_id %lld len %d\n",
  252. type, ceph_entity_type_name(type), th->secret_id,
  253. (int)th->ticket_blob->vec.iov_len);
  254. xi->have_keys |= th->service;
  255. return 0;
  256. bad:
  257. ret = -EINVAL;
  258. out:
  259. ceph_crypto_key_destroy(&new_session_key);
  260. return ret;
  261. }
  262. static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
  263. struct ceph_crypto_key *secret,
  264. void **p, void *end)
  265. {
  266. u8 reply_struct_v;
  267. u32 num;
  268. int ret;
  269. ceph_decode_8_safe(p, end, reply_struct_v, bad);
  270. if (reply_struct_v != 1)
  271. return -EINVAL;
  272. ceph_decode_32_safe(p, end, num, bad);
  273. dout("%d tickets\n", num);
  274. while (num--) {
  275. ret = process_one_ticket(ac, secret, p, end);
  276. if (ret)
  277. return ret;
  278. }
  279. return 0;
  280. bad:
  281. return -EINVAL;
  282. }
  283. /*
  284. * Encode and encrypt the second part (ceph_x_authorize_b) of the
  285. * authorizer. The first part (ceph_x_authorize_a) should already be
  286. * encoded.
  287. */
  288. static int encrypt_authorizer(struct ceph_x_authorizer *au,
  289. u64 *server_challenge)
  290. {
  291. struct ceph_x_authorize_a *msg_a;
  292. struct ceph_x_authorize_b *msg_b;
  293. void *p, *end;
  294. int ret;
  295. msg_a = au->buf->vec.iov_base;
  296. WARN_ON(msg_a->ticket_blob.secret_id != cpu_to_le64(au->secret_id));
  297. p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len);
  298. end = au->buf->vec.iov_base + au->buf->vec.iov_len;
  299. msg_b = p + ceph_x_encrypt_offset(&au->session_key);
  300. msg_b->struct_v = 2;
  301. msg_b->nonce = cpu_to_le64(au->nonce);
  302. if (server_challenge) {
  303. msg_b->have_challenge = 1;
  304. msg_b->server_challenge_plus_one =
  305. cpu_to_le64(*server_challenge + 1);
  306. } else {
  307. msg_b->have_challenge = 0;
  308. msg_b->server_challenge_plus_one = 0;
  309. }
  310. ret = ceph_x_encrypt(&au->session_key,
  311. 0 /* CEPHX_KEY_USAGE_AUTHORIZE */,
  312. p, end - p, sizeof(*msg_b));
  313. if (ret < 0)
  314. return ret;
  315. p += ret;
  316. if (server_challenge) {
  317. WARN_ON(p != end);
  318. } else {
  319. WARN_ON(p > end);
  320. au->buf->vec.iov_len = p - au->buf->vec.iov_base;
  321. }
  322. return 0;
  323. }
  324. static void ceph_x_authorizer_cleanup(struct ceph_x_authorizer *au)
  325. {
  326. ceph_crypto_key_destroy(&au->session_key);
  327. if (au->buf) {
  328. ceph_buffer_put(au->buf);
  329. au->buf = NULL;
  330. }
  331. }
  332. static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
  333. struct ceph_x_ticket_handler *th,
  334. struct ceph_x_authorizer *au)
  335. {
  336. int maxlen;
  337. struct ceph_x_authorize_a *msg_a;
  338. struct ceph_x_authorize_b *msg_b;
  339. int ret;
  340. int ticket_blob_len =
  341. (th->ticket_blob ? th->ticket_blob->vec.iov_len : 0);
  342. dout("build_authorizer for %s %p\n",
  343. ceph_entity_type_name(th->service), au);
  344. ceph_crypto_key_destroy(&au->session_key);
  345. ret = ceph_crypto_key_clone(&au->session_key, &th->session_key);
  346. if (ret)
  347. goto out_au;
  348. ret = ceph_crypto_key_prepare(&au->session_key, authorizer_key_usages,
  349. ARRAY_SIZE(authorizer_key_usages));
  350. if (ret)
  351. goto out_au;
  352. maxlen = sizeof(*msg_a) + ticket_blob_len +
  353. ceph_x_encrypt_buflen(&au->session_key, sizeof(*msg_b));
  354. dout(" need len %d\n", maxlen);
  355. if (au->buf && au->buf->alloc_len < maxlen) {
  356. ceph_buffer_put(au->buf);
  357. au->buf = NULL;
  358. }
  359. if (!au->buf) {
  360. au->buf = ceph_buffer_new(maxlen, GFP_NOFS);
  361. if (!au->buf) {
  362. ret = -ENOMEM;
  363. goto out_au;
  364. }
  365. }
  366. au->service = th->service;
  367. WARN_ON(!th->secret_id);
  368. au->secret_id = th->secret_id;
  369. msg_a = au->buf->vec.iov_base;
  370. msg_a->struct_v = 1;
  371. msg_a->global_id = cpu_to_le64(ac->global_id);
  372. msg_a->service_id = cpu_to_le32(th->service);
  373. msg_a->ticket_blob.struct_v = 1;
  374. msg_a->ticket_blob.secret_id = cpu_to_le64(th->secret_id);
  375. msg_a->ticket_blob.blob_len = cpu_to_le32(ticket_blob_len);
  376. if (ticket_blob_len) {
  377. memcpy(msg_a->ticket_blob.blob, th->ticket_blob->vec.iov_base,
  378. th->ticket_blob->vec.iov_len);
  379. }
  380. dout(" th %p secret_id %lld %lld\n", th, th->secret_id,
  381. le64_to_cpu(msg_a->ticket_blob.secret_id));
  382. get_random_bytes(&au->nonce, sizeof(au->nonce));
  383. ret = encrypt_authorizer(au, NULL);
  384. if (ret) {
  385. pr_err("failed to encrypt authorizer: %d", ret);
  386. goto out_au;
  387. }
  388. dout(" built authorizer nonce %llx len %d\n", au->nonce,
  389. (int)au->buf->vec.iov_len);
  390. return 0;
  391. out_au:
  392. ceph_x_authorizer_cleanup(au);
  393. return ret;
  394. }
  395. static int ceph_x_encode_ticket(struct ceph_x_ticket_handler *th,
  396. void **p, void *end)
  397. {
  398. ceph_decode_need(p, end, 1 + sizeof(u64), bad);
  399. ceph_encode_8(p, 1);
  400. ceph_encode_64(p, th->secret_id);
  401. if (th->ticket_blob) {
  402. const char *buf = th->ticket_blob->vec.iov_base;
  403. u32 len = th->ticket_blob->vec.iov_len;
  404. ceph_encode_32_safe(p, end, len, bad);
  405. ceph_encode_copy_safe(p, end, buf, len, bad);
  406. } else {
  407. ceph_encode_32_safe(p, end, 0, bad);
  408. }
  409. return 0;
  410. bad:
  411. return -ERANGE;
  412. }
  413. static bool need_key(struct ceph_x_ticket_handler *th)
  414. {
  415. if (!th->have_key)
  416. return true;
  417. return ktime_get_real_seconds() >= th->renew_after;
  418. }
  419. static bool have_key(struct ceph_x_ticket_handler *th)
  420. {
  421. if (th->have_key && ktime_get_real_seconds() >= th->expires) {
  422. dout("ticket %d (%s) secret_id %llu expired\n", th->service,
  423. ceph_entity_type_name(th->service), th->secret_id);
  424. th->have_key = false;
  425. }
  426. return th->have_key;
  427. }
  428. static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed)
  429. {
  430. int want = ac->want_keys;
  431. struct ceph_x_info *xi = ac->private;
  432. int service;
  433. *pneed = ac->want_keys & ~(xi->have_keys);
  434. for (service = 1; service <= want; service <<= 1) {
  435. struct ceph_x_ticket_handler *th;
  436. if (!(ac->want_keys & service))
  437. continue;
  438. if (*pneed & service)
  439. continue;
  440. th = get_ticket_handler(ac, service);
  441. if (IS_ERR(th)) {
  442. *pneed |= service;
  443. continue;
  444. }
  445. if (need_key(th))
  446. *pneed |= service;
  447. if (!have_key(th))
  448. xi->have_keys &= ~service;
  449. }
  450. }
  451. static int ceph_x_build_request(struct ceph_auth_client *ac,
  452. void *buf, void *end)
  453. {
  454. struct ceph_x_info *xi = ac->private;
  455. int need;
  456. struct ceph_x_request_header *head = buf;
  457. void *p;
  458. int ret;
  459. struct ceph_x_ticket_handler *th =
  460. get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
  461. if (IS_ERR(th))
  462. return PTR_ERR(th);
  463. ceph_x_validate_tickets(ac, &need);
  464. dout("%s want 0x%x have 0x%x need 0x%x\n", __func__, ac->want_keys,
  465. xi->have_keys, need);
  466. if (need & CEPH_ENTITY_TYPE_AUTH) {
  467. struct ceph_x_authenticate *auth = (void *)(head + 1);
  468. void *enc_buf = xi->auth_authorizer.enc_buf;
  469. struct ceph_x_challenge_blob *blob;
  470. u64 *u;
  471. p = auth + 1;
  472. if (p > end)
  473. return -ERANGE;
  474. dout(" get_auth_session_key\n");
  475. head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY);
  476. if (xi->secret.type == CEPH_CRYPTO_AES) {
  477. blob = enc_buf + ceph_x_encrypt_offset(&xi->secret);
  478. } else {
  479. BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*blob) >
  480. CEPHX_AU_ENC_BUF_LEN);
  481. blob = enc_buf + SHA256_DIGEST_SIZE;
  482. }
  483. get_random_bytes(&auth->client_challenge, sizeof(u64));
  484. blob->client_challenge = auth->client_challenge;
  485. blob->server_challenge = cpu_to_le64(xi->server_challenge);
  486. if (xi->secret.type == CEPH_CRYPTO_AES) {
  487. ret = ceph_x_encrypt(&xi->secret, 0 /* dummy */,
  488. enc_buf, CEPHX_AU_ENC_BUF_LEN,
  489. sizeof(*blob));
  490. if (ret < 0)
  491. return ret;
  492. } else {
  493. ceph_hmac_sha256(&xi->secret, blob, sizeof(*blob),
  494. enc_buf);
  495. ret = SHA256_DIGEST_SIZE;
  496. }
  497. auth->struct_v = 3; /* nautilus+ */
  498. auth->key = 0;
  499. for (u = (u64 *)enc_buf; u + 1 <= (u64 *)(enc_buf + ret); u++)
  500. auth->key ^= *(__le64 *)u;
  501. dout(" server_challenge %llx client_challenge %llx key %llx\n",
  502. xi->server_challenge, le64_to_cpu(auth->client_challenge),
  503. le64_to_cpu(auth->key));
  504. /* now encode the old ticket if exists */
  505. ret = ceph_x_encode_ticket(th, &p, end);
  506. if (ret < 0)
  507. return ret;
  508. /* nautilus+: request service tickets at the same time */
  509. need = ac->want_keys & ~CEPH_ENTITY_TYPE_AUTH;
  510. WARN_ON(!need);
  511. ceph_encode_32_safe(&p, end, need, e_range);
  512. return p - buf;
  513. }
  514. if (need) {
  515. dout(" get_principal_session_key\n");
  516. ret = ceph_x_build_authorizer(ac, th, &xi->auth_authorizer);
  517. if (ret)
  518. return ret;
  519. p = buf;
  520. ceph_encode_16_safe(&p, end, CEPHX_GET_PRINCIPAL_SESSION_KEY,
  521. e_range);
  522. ceph_encode_copy_safe(&p, end,
  523. xi->auth_authorizer.buf->vec.iov_base,
  524. xi->auth_authorizer.buf->vec.iov_len, e_range);
  525. ceph_encode_8_safe(&p, end, 1, e_range);
  526. ceph_encode_32_safe(&p, end, need, e_range);
  527. return p - buf;
  528. }
  529. return 0;
  530. e_range:
  531. return -ERANGE;
  532. }
  533. static int decode_con_secret(void **p, void *end, u8 *con_secret,
  534. int *con_secret_len)
  535. {
  536. int len;
  537. ceph_decode_32_safe(p, end, len, bad);
  538. ceph_decode_need(p, end, len, bad);
  539. dout("%s len %d\n", __func__, len);
  540. if (con_secret) {
  541. if (len > CEPH_MAX_CON_SECRET_LEN) {
  542. pr_err("connection secret too big %d\n", len);
  543. goto bad_memzero;
  544. }
  545. memcpy(con_secret, *p, len);
  546. *con_secret_len = len;
  547. }
  548. memzero_explicit(*p, len);
  549. *p += len;
  550. return 0;
  551. bad_memzero:
  552. memzero_explicit(*p, len);
  553. bad:
  554. pr_err("failed to decode connection secret\n");
  555. return -EINVAL;
  556. }
  557. static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
  558. void **p, void *end,
  559. u8 *session_key, int *session_key_len,
  560. u8 *con_secret, int *con_secret_len)
  561. {
  562. struct ceph_x_info *xi = ac->private;
  563. struct ceph_x_ticket_handler *th;
  564. void *dp, *dend;
  565. int len;
  566. int ret;
  567. /* AUTH ticket */
  568. ret = ceph_x_proc_ticket_reply(ac, &xi->secret, p, end);
  569. if (ret)
  570. return ret;
  571. ceph_auth_set_global_id(ac, global_id);
  572. if (*p == end) {
  573. /* pre-nautilus (or didn't request service tickets!) */
  574. WARN_ON(session_key || con_secret);
  575. return 0;
  576. }
  577. th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
  578. if (IS_ERR(th))
  579. return PTR_ERR(th);
  580. if (session_key) {
  581. memcpy(session_key, th->session_key.key, th->session_key.len);
  582. *session_key_len = th->session_key.len;
  583. }
  584. /* connection secret */
  585. ceph_decode_32_safe(p, end, len, e_inval);
  586. ceph_decode_need(p, end, len, e_inval);
  587. dout("%s connection secret blob len %d\n", __func__, len);
  588. if (len > 0) {
  589. dp = *p + ceph_x_encrypt_offset(&th->session_key);
  590. ret = ceph_x_decrypt(&th->session_key,
  591. 2 /* CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET */,
  592. p, *p + len);
  593. if (ret < 0)
  594. return ret;
  595. dout("%s decrypted %d bytes\n", __func__, ret);
  596. dend = dp + ret;
  597. ret = decode_con_secret(&dp, dend, con_secret, con_secret_len);
  598. if (ret)
  599. return ret;
  600. }
  601. /* service tickets */
  602. ceph_decode_32_safe(p, end, len, e_inval);
  603. ceph_decode_need(p, end, len, e_inval);
  604. dout("%s service tickets blob len %d\n", __func__, len);
  605. if (len > 0) {
  606. ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
  607. p, *p + len);
  608. if (ret)
  609. return ret;
  610. }
  611. return 0;
  612. e_inval:
  613. return -EINVAL;
  614. }
  615. static int ceph_x_handle_reply(struct ceph_auth_client *ac, u64 global_id,
  616. void *buf, void *end,
  617. u8 *session_key, int *session_key_len,
  618. u8 *con_secret, int *con_secret_len)
  619. {
  620. struct ceph_x_info *xi = ac->private;
  621. struct ceph_x_ticket_handler *th;
  622. int len = end - buf;
  623. int result;
  624. void *p;
  625. int op;
  626. int ret;
  627. if (xi->starting) {
  628. /* it's a hello */
  629. struct ceph_x_server_challenge *sc = buf;
  630. if (len != sizeof(*sc))
  631. return -EINVAL;
  632. xi->server_challenge = le64_to_cpu(sc->server_challenge);
  633. dout("handle_reply got server challenge %llx\n",
  634. xi->server_challenge);
  635. xi->starting = false;
  636. xi->have_keys &= ~CEPH_ENTITY_TYPE_AUTH;
  637. return -EAGAIN;
  638. }
  639. p = buf;
  640. ceph_decode_16_safe(&p, end, op, e_inval);
  641. ceph_decode_32_safe(&p, end, result, e_inval);
  642. dout("handle_reply op %d result %d\n", op, result);
  643. switch (op) {
  644. case CEPHX_GET_AUTH_SESSION_KEY:
  645. /* AUTH ticket + [connection secret] + service tickets */
  646. ret = handle_auth_session_key(ac, global_id, &p, end,
  647. session_key, session_key_len,
  648. con_secret, con_secret_len);
  649. break;
  650. case CEPHX_GET_PRINCIPAL_SESSION_KEY:
  651. th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
  652. if (IS_ERR(th))
  653. return PTR_ERR(th);
  654. /* service tickets */
  655. ret = ceph_x_proc_ticket_reply(ac, &th->session_key, &p, end);
  656. break;
  657. default:
  658. return -EINVAL;
  659. }
  660. if (ret)
  661. return ret;
  662. if (ac->want_keys == xi->have_keys)
  663. return 0;
  664. return -EAGAIN;
  665. e_inval:
  666. return -EINVAL;
  667. }
  668. static void ceph_x_destroy_authorizer(struct ceph_authorizer *a)
  669. {
  670. struct ceph_x_authorizer *au = (void *)a;
  671. ceph_x_authorizer_cleanup(au);
  672. kfree(au);
  673. }
  674. static int ceph_x_create_authorizer(
  675. struct ceph_auth_client *ac, int peer_type,
  676. struct ceph_auth_handshake *auth)
  677. {
  678. struct ceph_x_authorizer *au;
  679. struct ceph_x_ticket_handler *th;
  680. int ret;
  681. th = get_ticket_handler(ac, peer_type);
  682. if (IS_ERR(th))
  683. return PTR_ERR(th);
  684. au = kzalloc_obj(*au, GFP_NOFS);
  685. if (!au)
  686. return -ENOMEM;
  687. au->base.destroy = ceph_x_destroy_authorizer;
  688. ret = ceph_x_build_authorizer(ac, th, au);
  689. if (ret) {
  690. kfree(au);
  691. return ret;
  692. }
  693. auth->authorizer = (struct ceph_authorizer *) au;
  694. auth->authorizer_buf = au->buf->vec.iov_base;
  695. auth->authorizer_buf_len = au->buf->vec.iov_len;
  696. auth->authorizer_reply_buf = au->enc_buf;
  697. auth->authorizer_reply_buf_len = CEPHX_AU_ENC_BUF_LEN;
  698. auth->sign_message = ac->ops->sign_message;
  699. auth->check_message_signature = ac->ops->check_message_signature;
  700. return 0;
  701. }
  702. static int ceph_x_update_authorizer(
  703. struct ceph_auth_client *ac, int peer_type,
  704. struct ceph_auth_handshake *auth)
  705. {
  706. struct ceph_x_authorizer *au;
  707. struct ceph_x_ticket_handler *th;
  708. th = get_ticket_handler(ac, peer_type);
  709. if (IS_ERR(th))
  710. return PTR_ERR(th);
  711. au = (struct ceph_x_authorizer *)auth->authorizer;
  712. if (au->secret_id < th->secret_id) {
  713. dout("ceph_x_update_authorizer service %u secret %llu < %llu\n",
  714. au->service, au->secret_id, th->secret_id);
  715. return ceph_x_build_authorizer(ac, th, au);
  716. }
  717. return 0;
  718. }
  719. /*
  720. * CephXAuthorizeChallenge
  721. */
  722. static int decrypt_authorizer_challenge(struct ceph_crypto_key *secret,
  723. void *challenge, int challenge_len,
  724. u64 *server_challenge)
  725. {
  726. void *dp, *dend;
  727. int ret;
  728. /* no leading len */
  729. ret = __ceph_x_decrypt(secret,
  730. 1 /* CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE */,
  731. challenge, challenge_len);
  732. if (ret < 0)
  733. return ret;
  734. dout("%s decrypted %d bytes\n", __func__, ret);
  735. dp = challenge + __ceph_x_encrypt_offset(secret);
  736. dend = dp + ret;
  737. ceph_decode_skip_8(&dp, dend, e_inval); /* struct_v */
  738. ceph_decode_64_safe(&dp, dend, *server_challenge, e_inval);
  739. dout("%s server_challenge %llu\n", __func__, *server_challenge);
  740. return 0;
  741. e_inval:
  742. return -EINVAL;
  743. }
  744. static int ceph_x_add_authorizer_challenge(struct ceph_auth_client *ac,
  745. struct ceph_authorizer *a,
  746. void *challenge, int challenge_len)
  747. {
  748. struct ceph_x_authorizer *au = (void *)a;
  749. u64 server_challenge;
  750. int ret;
  751. ret = decrypt_authorizer_challenge(&au->session_key, challenge,
  752. challenge_len, &server_challenge);
  753. if (ret) {
  754. pr_err("failed to decrypt authorize challenge: %d", ret);
  755. return ret;
  756. }
  757. ret = encrypt_authorizer(au, &server_challenge);
  758. if (ret) {
  759. pr_err("failed to encrypt authorizer w/ challenge: %d", ret);
  760. return ret;
  761. }
  762. return 0;
  763. }
  764. /*
  765. * CephXAuthorizeReply
  766. */
  767. static int decrypt_authorizer_reply(struct ceph_crypto_key *secret,
  768. void **p, void *end, u64 *nonce_plus_one,
  769. u8 *con_secret, int *con_secret_len)
  770. {
  771. void *dp, *dend;
  772. u8 struct_v;
  773. int ret;
  774. dp = *p + ceph_x_encrypt_offset(secret);
  775. ret = ceph_x_decrypt(secret, 2 /* CEPHX_KEY_USAGE_AUTHORIZE_REPLY */,
  776. p, end);
  777. if (ret < 0)
  778. return ret;
  779. dout("%s decrypted %d bytes\n", __func__, ret);
  780. dend = dp + ret;
  781. ceph_decode_8_safe(&dp, dend, struct_v, e_inval);
  782. ceph_decode_64_safe(&dp, dend, *nonce_plus_one, e_inval);
  783. dout("%s nonce_plus_one %llu\n", __func__, *nonce_plus_one);
  784. if (struct_v >= 2) {
  785. ret = decode_con_secret(&dp, dend, con_secret, con_secret_len);
  786. if (ret)
  787. return ret;
  788. }
  789. return 0;
  790. e_inval:
  791. return -EINVAL;
  792. }
  793. static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
  794. struct ceph_authorizer *a,
  795. void *reply, int reply_len,
  796. u8 *session_key, int *session_key_len,
  797. u8 *con_secret, int *con_secret_len)
  798. {
  799. struct ceph_x_authorizer *au = (void *)a;
  800. u64 nonce_plus_one;
  801. int ret;
  802. if (session_key) {
  803. memcpy(session_key, au->session_key.key, au->session_key.len);
  804. *session_key_len = au->session_key.len;
  805. }
  806. ret = decrypt_authorizer_reply(&au->session_key, &reply,
  807. reply + reply_len, &nonce_plus_one,
  808. con_secret, con_secret_len);
  809. if (ret)
  810. return ret;
  811. if (nonce_plus_one != au->nonce + 1) {
  812. pr_err("failed to authenticate server\n");
  813. return -EPERM;
  814. }
  815. return 0;
  816. }
  817. static void ceph_x_reset(struct ceph_auth_client *ac)
  818. {
  819. struct ceph_x_info *xi = ac->private;
  820. dout("reset\n");
  821. xi->starting = true;
  822. xi->server_challenge = 0;
  823. }
  824. static void ceph_x_destroy(struct ceph_auth_client *ac)
  825. {
  826. struct ceph_x_info *xi = ac->private;
  827. struct rb_node *p;
  828. dout("ceph_x_destroy %p\n", ac);
  829. ceph_crypto_key_destroy(&xi->secret);
  830. while ((p = rb_first(&xi->ticket_handlers)) != NULL) {
  831. struct ceph_x_ticket_handler *th =
  832. rb_entry(p, struct ceph_x_ticket_handler, node);
  833. remove_ticket_handler(ac, th);
  834. }
  835. ceph_x_authorizer_cleanup(&xi->auth_authorizer);
  836. kfree(ac->private);
  837. ac->private = NULL;
  838. }
  839. static void invalidate_ticket(struct ceph_auth_client *ac, int peer_type)
  840. {
  841. struct ceph_x_ticket_handler *th;
  842. th = get_ticket_handler(ac, peer_type);
  843. if (IS_ERR(th))
  844. return;
  845. if (th->have_key) {
  846. dout("ticket %d (%s) secret_id %llu invalidated\n",
  847. th->service, ceph_entity_type_name(th->service),
  848. th->secret_id);
  849. th->have_key = false;
  850. }
  851. }
  852. static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
  853. int peer_type)
  854. {
  855. /*
  856. * We are to invalidate a service ticket in the hopes of
  857. * getting a new, hopefully more valid, one. But, we won't get
  858. * it unless our AUTH ticket is good, so invalidate AUTH ticket
  859. * as well, just in case.
  860. */
  861. invalidate_ticket(ac, peer_type);
  862. invalidate_ticket(ac, CEPH_ENTITY_TYPE_AUTH);
  863. }
  864. static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
  865. __le64 *psig)
  866. {
  867. void *enc_buf = au->enc_buf;
  868. int ret;
  869. if (!CEPH_HAVE_FEATURE(msg->con->peer_features, CEPHX_V2)) {
  870. struct {
  871. __le32 len;
  872. __le32 header_crc;
  873. __le32 front_crc;
  874. __le32 middle_crc;
  875. __le32 data_crc;
  876. } __packed *sigblock = enc_buf +
  877. ceph_x_encrypt_offset(&au->session_key);
  878. sigblock->len = cpu_to_le32(4*sizeof(u32));
  879. sigblock->header_crc = msg->hdr.crc;
  880. sigblock->front_crc = msg->footer.front_crc;
  881. sigblock->middle_crc = msg->footer.middle_crc;
  882. sigblock->data_crc = msg->footer.data_crc;
  883. ret = ceph_x_encrypt(&au->session_key, 0 /* dummy */,
  884. enc_buf, CEPHX_AU_ENC_BUF_LEN,
  885. sizeof(*sigblock));
  886. if (ret < 0)
  887. return ret;
  888. *psig = *(__le64 *)(enc_buf + sizeof(u32));
  889. } else {
  890. struct {
  891. __le32 header_crc;
  892. __le32 front_crc;
  893. __le32 front_len;
  894. __le32 middle_crc;
  895. __le32 middle_len;
  896. __le32 data_crc;
  897. __le32 data_len;
  898. __le32 seq_lower_word;
  899. } __packed *sigblock;
  900. struct {
  901. __le64 a, b, c, d;
  902. } __packed *penc = enc_buf;
  903. if (au->session_key.type == CEPH_CRYPTO_AES) {
  904. /* no leading len, no ceph_x_encrypt_header */
  905. sigblock = enc_buf;
  906. } else {
  907. BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*sigblock) >
  908. CEPHX_AU_ENC_BUF_LEN);
  909. sigblock = enc_buf + SHA256_DIGEST_SIZE;
  910. }
  911. sigblock->header_crc = msg->hdr.crc;
  912. sigblock->front_crc = msg->footer.front_crc;
  913. sigblock->front_len = msg->hdr.front_len;
  914. sigblock->middle_crc = msg->footer.middle_crc;
  915. sigblock->middle_len = msg->hdr.middle_len;
  916. sigblock->data_crc = msg->footer.data_crc;
  917. sigblock->data_len = msg->hdr.data_len;
  918. sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq;
  919. if (au->session_key.type == CEPH_CRYPTO_AES) {
  920. int ciphertext_len; /* unused */
  921. ret = ceph_crypt(&au->session_key, 0 /* dummy */,
  922. true, enc_buf, CEPHX_AU_ENC_BUF_LEN,
  923. sizeof(*sigblock), &ciphertext_len);
  924. if (ret)
  925. return ret;
  926. } else {
  927. ceph_hmac_sha256(&au->session_key, sigblock,
  928. sizeof(*sigblock), enc_buf);
  929. }
  930. *psig = penc->a ^ penc->b ^ penc->c ^ penc->d;
  931. }
  932. return 0;
  933. }
  934. static int ceph_x_sign_message(struct ceph_auth_handshake *auth,
  935. struct ceph_msg *msg)
  936. {
  937. __le64 sig;
  938. int ret;
  939. if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN))
  940. return 0;
  941. ret = calc_signature((struct ceph_x_authorizer *)auth->authorizer,
  942. msg, &sig);
  943. if (ret)
  944. return ret;
  945. msg->footer.sig = sig;
  946. msg->footer.flags |= CEPH_MSG_FOOTER_SIGNED;
  947. return 0;
  948. }
  949. static int ceph_x_check_message_signature(struct ceph_auth_handshake *auth,
  950. struct ceph_msg *msg)
  951. {
  952. __le64 sig_check;
  953. int ret;
  954. if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN))
  955. return 0;
  956. ret = calc_signature((struct ceph_x_authorizer *)auth->authorizer,
  957. msg, &sig_check);
  958. if (ret)
  959. return ret;
  960. if (sig_check == msg->footer.sig)
  961. return 0;
  962. if (msg->footer.flags & CEPH_MSG_FOOTER_SIGNED)
  963. dout("ceph_x_check_message_signature %p has signature %llx "
  964. "expect %llx\n", msg, msg->footer.sig, sig_check);
  965. else
  966. dout("ceph_x_check_message_signature %p sender did not set "
  967. "CEPH_MSG_FOOTER_SIGNED\n", msg);
  968. return -EBADMSG;
  969. }
  970. static const struct ceph_auth_client_ops ceph_x_ops = {
  971. .is_authenticated = ceph_x_is_authenticated,
  972. .should_authenticate = ceph_x_should_authenticate,
  973. .build_request = ceph_x_build_request,
  974. .handle_reply = ceph_x_handle_reply,
  975. .create_authorizer = ceph_x_create_authorizer,
  976. .update_authorizer = ceph_x_update_authorizer,
  977. .add_authorizer_challenge = ceph_x_add_authorizer_challenge,
  978. .verify_authorizer_reply = ceph_x_verify_authorizer_reply,
  979. .invalidate_authorizer = ceph_x_invalidate_authorizer,
  980. .reset = ceph_x_reset,
  981. .destroy = ceph_x_destroy,
  982. .sign_message = ceph_x_sign_message,
  983. .check_message_signature = ceph_x_check_message_signature,
  984. };
  985. int ceph_x_init(struct ceph_auth_client *ac)
  986. {
  987. struct ceph_x_info *xi;
  988. int ret;
  989. dout("ceph_x_init %p\n", ac);
  990. xi = kzalloc_obj(*xi, GFP_NOFS);
  991. if (!xi)
  992. return -ENOMEM;
  993. ret = -EINVAL;
  994. if (!ac->key) {
  995. pr_err("no secret set (for auth_x protocol)\n");
  996. goto err_xi;
  997. }
  998. ret = ceph_crypto_key_clone(&xi->secret, ac->key);
  999. if (ret < 0) {
  1000. pr_err("cannot clone key: %d\n", ret);
  1001. goto err_xi;
  1002. }
  1003. ret = ceph_crypto_key_prepare(&xi->secret, client_key_usages,
  1004. ARRAY_SIZE(client_key_usages));
  1005. if (ret) {
  1006. pr_err("cannot prepare key: %d\n", ret);
  1007. goto err_secret;
  1008. }
  1009. xi->starting = true;
  1010. xi->ticket_handlers = RB_ROOT;
  1011. ac->protocol = CEPH_AUTH_CEPHX;
  1012. ac->private = xi;
  1013. ac->ops = &ceph_x_ops;
  1014. return 0;
  1015. err_secret:
  1016. ceph_crypto_key_destroy(&xi->secret);
  1017. err_xi:
  1018. kfree(xi);
  1019. return ret;
  1020. }