gss_rpc_xdr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * GSS Proxy upcall module
  4. *
  5. * Copyright (C) 2012 Simo Sorce <simo@redhat.com>
  6. */
  7. #include <linux/sunrpc/svcauth.h>
  8. #include "gss_rpc_xdr.h"
  9. static int gssx_enc_bool(struct xdr_stream *xdr, int v)
  10. {
  11. __be32 *p;
  12. p = xdr_reserve_space(xdr, 4);
  13. if (unlikely(p == NULL))
  14. return -ENOSPC;
  15. *p = v ? xdr_one : xdr_zero;
  16. return 0;
  17. }
  18. static int gssx_dec_bool(struct xdr_stream *xdr, u32 *v)
  19. {
  20. __be32 *p;
  21. p = xdr_inline_decode(xdr, 4);
  22. if (unlikely(p == NULL))
  23. return -ENOSPC;
  24. *v = be32_to_cpu(*p);
  25. return 0;
  26. }
  27. static int gssx_enc_buffer(struct xdr_stream *xdr,
  28. const gssx_buffer *buf)
  29. {
  30. __be32 *p;
  31. p = xdr_reserve_space(xdr, sizeof(u32) + buf->len);
  32. if (!p)
  33. return -ENOSPC;
  34. xdr_encode_opaque(p, buf->data, buf->len);
  35. return 0;
  36. }
  37. static int gssx_enc_in_token(struct xdr_stream *xdr,
  38. const struct gssp_in_token *in)
  39. {
  40. __be32 *p;
  41. p = xdr_reserve_space(xdr, 4);
  42. if (!p)
  43. return -ENOSPC;
  44. *p = cpu_to_be32(in->page_len);
  45. /* all we need to do is to write pages */
  46. xdr_write_pages(xdr, in->pages, in->page_base, in->page_len);
  47. return 0;
  48. }
  49. static int gssx_dec_buffer(struct xdr_stream *xdr,
  50. gssx_buffer *buf)
  51. {
  52. u32 length;
  53. __be32 *p;
  54. p = xdr_inline_decode(xdr, 4);
  55. if (unlikely(p == NULL))
  56. return -ENOSPC;
  57. length = be32_to_cpup(p);
  58. p = xdr_inline_decode(xdr, length);
  59. if (unlikely(p == NULL))
  60. return -ENOSPC;
  61. if (buf->len == 0) {
  62. /* we intentionally are not interested in this buffer */
  63. return 0;
  64. }
  65. if (length > buf->len)
  66. return -ENOSPC;
  67. if (!buf->data) {
  68. buf->data = kmemdup(p, length, GFP_KERNEL);
  69. if (!buf->data)
  70. return -ENOMEM;
  71. } else {
  72. memcpy(buf->data, p, length);
  73. }
  74. buf->len = length;
  75. return 0;
  76. }
  77. static int gssx_enc_option(struct xdr_stream *xdr,
  78. struct gssx_option *opt)
  79. {
  80. int err;
  81. err = gssx_enc_buffer(xdr, &opt->option);
  82. if (err)
  83. return err;
  84. err = gssx_enc_buffer(xdr, &opt->value);
  85. return err;
  86. }
  87. static int gssx_dec_option(struct xdr_stream *xdr,
  88. struct gssx_option *opt)
  89. {
  90. int err;
  91. err = gssx_dec_buffer(xdr, &opt->option);
  92. if (err)
  93. return err;
  94. err = gssx_dec_buffer(xdr, &opt->value);
  95. return err;
  96. }
  97. static int dummy_enc_opt_array(struct xdr_stream *xdr,
  98. const struct gssx_option_array *oa)
  99. {
  100. __be32 *p;
  101. if (oa->count != 0)
  102. return -EINVAL;
  103. p = xdr_reserve_space(xdr, 4);
  104. if (!p)
  105. return -ENOSPC;
  106. *p = 0;
  107. return 0;
  108. }
  109. static int dummy_dec_opt_array(struct xdr_stream *xdr,
  110. struct gssx_option_array *oa)
  111. {
  112. struct gssx_option dummy;
  113. u32 count, i;
  114. __be32 *p;
  115. p = xdr_inline_decode(xdr, 4);
  116. if (unlikely(p == NULL))
  117. return -ENOSPC;
  118. count = be32_to_cpup(p++);
  119. memset(&dummy, 0, sizeof(dummy));
  120. for (i = 0; i < count; i++) {
  121. gssx_dec_option(xdr, &dummy);
  122. }
  123. oa->count = 0;
  124. oa->data = NULL;
  125. return 0;
  126. }
  127. static int get_host_u32(struct xdr_stream *xdr, u32 *res)
  128. {
  129. __be32 *p;
  130. p = xdr_inline_decode(xdr, 4);
  131. if (!p)
  132. return -EINVAL;
  133. /* Contents of linux creds are all host-endian: */
  134. memcpy(res, p, sizeof(u32));
  135. return 0;
  136. }
  137. static int gssx_dec_linux_creds(struct xdr_stream *xdr,
  138. struct svc_cred *creds)
  139. {
  140. u32 length;
  141. __be32 *p;
  142. u32 tmp;
  143. u32 N;
  144. int i, err;
  145. p = xdr_inline_decode(xdr, 4);
  146. if (unlikely(p == NULL))
  147. return -ENOSPC;
  148. length = be32_to_cpup(p);
  149. if (length > (3 + NGROUPS_MAX) * sizeof(u32))
  150. return -ENOSPC;
  151. /* uid */
  152. err = get_host_u32(xdr, &tmp);
  153. if (err)
  154. return err;
  155. creds->cr_uid = make_kuid(&init_user_ns, tmp);
  156. /* gid */
  157. err = get_host_u32(xdr, &tmp);
  158. if (err)
  159. return err;
  160. creds->cr_gid = make_kgid(&init_user_ns, tmp);
  161. /* number of additional gid's */
  162. err = get_host_u32(xdr, &tmp);
  163. if (err)
  164. return err;
  165. N = tmp;
  166. if ((3 + N) * sizeof(u32) != length)
  167. return -EINVAL;
  168. creds->cr_group_info = groups_alloc(N);
  169. if (creds->cr_group_info == NULL)
  170. return -ENOMEM;
  171. /* gid's */
  172. for (i = 0; i < N; i++) {
  173. kgid_t kgid;
  174. err = get_host_u32(xdr, &tmp);
  175. if (err)
  176. goto out_free_groups;
  177. err = -EINVAL;
  178. kgid = make_kgid(&init_user_ns, tmp);
  179. if (!gid_valid(kgid))
  180. goto out_free_groups;
  181. creds->cr_group_info->gid[i] = kgid;
  182. }
  183. groups_sort(creds->cr_group_info);
  184. return 0;
  185. out_free_groups:
  186. groups_free(creds->cr_group_info);
  187. return err;
  188. }
  189. static int gssx_dec_option_array(struct xdr_stream *xdr,
  190. struct gssx_option_array *oa)
  191. {
  192. struct svc_cred *creds;
  193. u32 count, i;
  194. __be32 *p;
  195. int err;
  196. p = xdr_inline_decode(xdr, 4);
  197. if (unlikely(p == NULL))
  198. return -ENOSPC;
  199. count = be32_to_cpup(p++);
  200. if (!count)
  201. return 0;
  202. /* we recognize only 1 currently: CREDS_VALUE */
  203. oa->count = 1;
  204. oa->data = kmalloc_obj(struct gssx_option);
  205. if (!oa->data)
  206. return -ENOMEM;
  207. creds = kzalloc_obj(struct svc_cred);
  208. if (!creds) {
  209. err = -ENOMEM;
  210. goto free_oa;
  211. }
  212. oa->data[0].option.data = CREDS_VALUE;
  213. oa->data[0].option.len = sizeof(CREDS_VALUE);
  214. oa->data[0].value.data = (void *)creds;
  215. oa->data[0].value.len = 0;
  216. for (i = 0; i < count; i++) {
  217. gssx_buffer dummy = { 0, NULL };
  218. u32 length;
  219. /* option buffer */
  220. p = xdr_inline_decode(xdr, 4);
  221. if (unlikely(p == NULL)) {
  222. err = -ENOSPC;
  223. goto free_creds;
  224. }
  225. length = be32_to_cpup(p);
  226. p = xdr_inline_decode(xdr, length);
  227. if (unlikely(p == NULL)) {
  228. err = -ENOSPC;
  229. goto free_creds;
  230. }
  231. if (length == sizeof(CREDS_VALUE) &&
  232. memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) {
  233. /* We have creds here. parse them */
  234. err = gssx_dec_linux_creds(xdr, creds);
  235. if (err)
  236. goto free_creds;
  237. oa->data[0].value.len = 1; /* presence */
  238. } else {
  239. /* consume uninteresting buffer */
  240. err = gssx_dec_buffer(xdr, &dummy);
  241. if (err)
  242. goto free_creds;
  243. }
  244. }
  245. return 0;
  246. free_creds:
  247. kfree(creds);
  248. free_oa:
  249. kfree(oa->data);
  250. oa->data = NULL;
  251. return err;
  252. }
  253. static int gssx_dec_status(struct xdr_stream *xdr,
  254. struct gssx_status *status)
  255. {
  256. __be32 *p;
  257. int err;
  258. /* status->major_status */
  259. p = xdr_inline_decode(xdr, 8);
  260. if (unlikely(p == NULL))
  261. return -ENOSPC;
  262. p = xdr_decode_hyper(p, &status->major_status);
  263. /* status->mech */
  264. err = gssx_dec_buffer(xdr, &status->mech);
  265. if (err)
  266. return err;
  267. /* status->minor_status */
  268. p = xdr_inline_decode(xdr, 8);
  269. if (unlikely(p == NULL)) {
  270. err = -ENOSPC;
  271. goto out_free_mech;
  272. }
  273. p = xdr_decode_hyper(p, &status->minor_status);
  274. /* status->major_status_string */
  275. err = gssx_dec_buffer(xdr, &status->major_status_string);
  276. if (err)
  277. goto out_free_mech;
  278. /* status->minor_status_string */
  279. err = gssx_dec_buffer(xdr, &status->minor_status_string);
  280. if (err)
  281. goto out_free_major_status_string;
  282. /* status->server_ctx */
  283. err = gssx_dec_buffer(xdr, &status->server_ctx);
  284. if (err)
  285. goto out_free_minor_status_string;
  286. /* we assume we have no options for now, so simply consume them */
  287. /* status->options */
  288. err = dummy_dec_opt_array(xdr, &status->options);
  289. if (err)
  290. goto out_free_server_ctx;
  291. return 0;
  292. out_free_server_ctx:
  293. kfree(status->server_ctx.data);
  294. status->server_ctx.data = NULL;
  295. out_free_minor_status_string:
  296. kfree(status->minor_status_string.data);
  297. status->minor_status_string.data = NULL;
  298. out_free_major_status_string:
  299. kfree(status->major_status_string.data);
  300. status->major_status_string.data = NULL;
  301. out_free_mech:
  302. kfree(status->mech.data);
  303. status->mech.data = NULL;
  304. return err;
  305. }
  306. static int gssx_enc_call_ctx(struct xdr_stream *xdr,
  307. const struct gssx_call_ctx *ctx)
  308. {
  309. struct gssx_option opt;
  310. __be32 *p;
  311. int err;
  312. /* ctx->locale */
  313. err = gssx_enc_buffer(xdr, &ctx->locale);
  314. if (err)
  315. return err;
  316. /* ctx->server_ctx */
  317. err = gssx_enc_buffer(xdr, &ctx->server_ctx);
  318. if (err)
  319. return err;
  320. /* we always want to ask for lucid contexts */
  321. /* ctx->options */
  322. p = xdr_reserve_space(xdr, 4);
  323. *p = cpu_to_be32(2);
  324. /* we want a lucid_v1 context */
  325. opt.option.data = LUCID_OPTION;
  326. opt.option.len = sizeof(LUCID_OPTION);
  327. opt.value.data = LUCID_VALUE;
  328. opt.value.len = sizeof(LUCID_VALUE);
  329. err = gssx_enc_option(xdr, &opt);
  330. /* ..and user creds */
  331. opt.option.data = CREDS_OPTION;
  332. opt.option.len = sizeof(CREDS_OPTION);
  333. opt.value.data = CREDS_VALUE;
  334. opt.value.len = sizeof(CREDS_VALUE);
  335. err = gssx_enc_option(xdr, &opt);
  336. return err;
  337. }
  338. static int gssx_dec_name_attr(struct xdr_stream *xdr,
  339. struct gssx_name_attr *attr)
  340. {
  341. int err;
  342. /* attr->attr */
  343. err = gssx_dec_buffer(xdr, &attr->attr);
  344. if (err)
  345. return err;
  346. /* attr->value */
  347. err = gssx_dec_buffer(xdr, &attr->value);
  348. if (err)
  349. return err;
  350. /* attr->extensions */
  351. err = dummy_dec_opt_array(xdr, &attr->extensions);
  352. return err;
  353. }
  354. static int dummy_enc_nameattr_array(struct xdr_stream *xdr,
  355. struct gssx_name_attr_array *naa)
  356. {
  357. __be32 *p;
  358. if (naa->count != 0)
  359. return -EINVAL;
  360. p = xdr_reserve_space(xdr, 4);
  361. if (!p)
  362. return -ENOSPC;
  363. *p = 0;
  364. return 0;
  365. }
  366. static int dummy_dec_nameattr_array(struct xdr_stream *xdr,
  367. struct gssx_name_attr_array *naa)
  368. {
  369. struct gssx_name_attr dummy = { .attr = {.len = 0} };
  370. u32 count, i;
  371. __be32 *p;
  372. p = xdr_inline_decode(xdr, 4);
  373. if (unlikely(p == NULL))
  374. return -ENOSPC;
  375. count = be32_to_cpup(p++);
  376. for (i = 0; i < count; i++) {
  377. gssx_dec_name_attr(xdr, &dummy);
  378. }
  379. naa->count = 0;
  380. naa->data = NULL;
  381. return 0;
  382. }
  383. static struct xdr_netobj zero_netobj = {};
  384. static struct gssx_name_attr_array zero_name_attr_array = {};
  385. static struct gssx_option_array zero_option_array = {};
  386. static int gssx_enc_name(struct xdr_stream *xdr,
  387. struct gssx_name *name)
  388. {
  389. int err;
  390. /* name->display_name */
  391. err = gssx_enc_buffer(xdr, &name->display_name);
  392. if (err)
  393. return err;
  394. /* name->name_type */
  395. err = gssx_enc_buffer(xdr, &zero_netobj);
  396. if (err)
  397. return err;
  398. /* name->exported_name */
  399. err = gssx_enc_buffer(xdr, &zero_netobj);
  400. if (err)
  401. return err;
  402. /* name->exported_composite_name */
  403. err = gssx_enc_buffer(xdr, &zero_netobj);
  404. if (err)
  405. return err;
  406. /* leave name_attributes empty for now, will add once we have any
  407. * to pass up at all */
  408. /* name->name_attributes */
  409. err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array);
  410. if (err)
  411. return err;
  412. /* leave options empty for now, will add once we have any options
  413. * to pass up at all */
  414. /* name->extensions */
  415. err = dummy_enc_opt_array(xdr, &zero_option_array);
  416. return err;
  417. }
  418. static int gssx_dec_name(struct xdr_stream *xdr,
  419. struct gssx_name *name)
  420. {
  421. struct xdr_netobj dummy_netobj = { .len = 0 };
  422. struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 };
  423. struct gssx_option_array dummy_option_array = { .count = 0 };
  424. int err;
  425. /* name->display_name */
  426. err = gssx_dec_buffer(xdr, &name->display_name);
  427. if (err)
  428. return err;
  429. /* name->name_type */
  430. err = gssx_dec_buffer(xdr, &dummy_netobj);
  431. if (err)
  432. goto out_free_display_name;
  433. /* name->exported_name */
  434. err = gssx_dec_buffer(xdr, &dummy_netobj);
  435. if (err)
  436. goto out_free_display_name;
  437. /* name->exported_composite_name */
  438. err = gssx_dec_buffer(xdr, &dummy_netobj);
  439. if (err)
  440. goto out_free_display_name;
  441. /* we assume we have no attributes for now, so simply consume them */
  442. /* name->name_attributes */
  443. err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array);
  444. if (err)
  445. goto out_free_display_name;
  446. /* we assume we have no options for now, so simply consume them */
  447. /* name->extensions */
  448. err = dummy_dec_opt_array(xdr, &dummy_option_array);
  449. if (err)
  450. goto out_free_display_name;
  451. return 0;
  452. out_free_display_name:
  453. kfree(name->display_name.data);
  454. name->display_name.data = NULL;
  455. return err;
  456. }
  457. static int dummy_enc_credel_array(struct xdr_stream *xdr,
  458. struct gssx_cred_element_array *cea)
  459. {
  460. __be32 *p;
  461. if (cea->count != 0)
  462. return -EINVAL;
  463. p = xdr_reserve_space(xdr, 4);
  464. if (!p)
  465. return -ENOSPC;
  466. *p = 0;
  467. return 0;
  468. }
  469. static int gssx_enc_cred(struct xdr_stream *xdr,
  470. struct gssx_cred *cred)
  471. {
  472. int err;
  473. /* cred->desired_name */
  474. err = gssx_enc_name(xdr, &cred->desired_name);
  475. if (err)
  476. return err;
  477. /* cred->elements */
  478. err = dummy_enc_credel_array(xdr, &cred->elements);
  479. if (err)
  480. return err;
  481. /* cred->cred_handle_reference */
  482. err = gssx_enc_buffer(xdr, &cred->cred_handle_reference);
  483. if (err)
  484. return err;
  485. /* cred->needs_release */
  486. err = gssx_enc_bool(xdr, cred->needs_release);
  487. return err;
  488. }
  489. static int gssx_enc_ctx(struct xdr_stream *xdr,
  490. struct gssx_ctx *ctx)
  491. {
  492. __be32 *p;
  493. int err;
  494. /* ctx->exported_context_token */
  495. err = gssx_enc_buffer(xdr, &ctx->exported_context_token);
  496. if (err)
  497. return err;
  498. /* ctx->state */
  499. err = gssx_enc_buffer(xdr, &ctx->state);
  500. if (err)
  501. return err;
  502. /* ctx->need_release */
  503. err = gssx_enc_bool(xdr, ctx->need_release);
  504. if (err)
  505. return err;
  506. /* ctx->mech */
  507. err = gssx_enc_buffer(xdr, &ctx->mech);
  508. if (err)
  509. return err;
  510. /* ctx->src_name */
  511. err = gssx_enc_name(xdr, &ctx->src_name);
  512. if (err)
  513. return err;
  514. /* ctx->targ_name */
  515. err = gssx_enc_name(xdr, &ctx->targ_name);
  516. if (err)
  517. return err;
  518. /* ctx->lifetime */
  519. p = xdr_reserve_space(xdr, 8+8);
  520. if (!p)
  521. return -ENOSPC;
  522. p = xdr_encode_hyper(p, ctx->lifetime);
  523. /* ctx->ctx_flags */
  524. p = xdr_encode_hyper(p, ctx->ctx_flags);
  525. /* ctx->locally_initiated */
  526. err = gssx_enc_bool(xdr, ctx->locally_initiated);
  527. if (err)
  528. return err;
  529. /* ctx->open */
  530. err = gssx_enc_bool(xdr, ctx->open);
  531. if (err)
  532. return err;
  533. /* leave options empty for now, will add once we have any options
  534. * to pass up at all */
  535. /* ctx->options */
  536. err = dummy_enc_opt_array(xdr, &ctx->options);
  537. return err;
  538. }
  539. static int gssx_dec_ctx(struct xdr_stream *xdr,
  540. struct gssx_ctx *ctx)
  541. {
  542. __be32 *p;
  543. int err;
  544. /* ctx->exported_context_token */
  545. err = gssx_dec_buffer(xdr, &ctx->exported_context_token);
  546. if (err)
  547. return err;
  548. /* ctx->state */
  549. err = gssx_dec_buffer(xdr, &ctx->state);
  550. if (err)
  551. goto out_free_exported_context_token;
  552. /* ctx->need_release */
  553. err = gssx_dec_bool(xdr, &ctx->need_release);
  554. if (err)
  555. goto out_free_state;
  556. /* ctx->mech */
  557. err = gssx_dec_buffer(xdr, &ctx->mech);
  558. if (err)
  559. goto out_free_state;
  560. /* ctx->src_name */
  561. err = gssx_dec_name(xdr, &ctx->src_name);
  562. if (err)
  563. goto out_free_mech;
  564. /* ctx->targ_name */
  565. err = gssx_dec_name(xdr, &ctx->targ_name);
  566. if (err)
  567. goto out_free_src_name;
  568. /* ctx->lifetime */
  569. p = xdr_inline_decode(xdr, 8+8);
  570. if (unlikely(p == NULL)) {
  571. err = -ENOSPC;
  572. goto out_free_targ_name;
  573. }
  574. p = xdr_decode_hyper(p, &ctx->lifetime);
  575. /* ctx->ctx_flags */
  576. p = xdr_decode_hyper(p, &ctx->ctx_flags);
  577. /* ctx->locally_initiated */
  578. err = gssx_dec_bool(xdr, &ctx->locally_initiated);
  579. if (err)
  580. goto out_free_targ_name;
  581. /* ctx->open */
  582. err = gssx_dec_bool(xdr, &ctx->open);
  583. if (err)
  584. goto out_free_targ_name;
  585. /* we assume we have no options for now, so simply consume them */
  586. /* ctx->options */
  587. err = dummy_dec_opt_array(xdr, &ctx->options);
  588. if (err)
  589. goto out_free_targ_name;
  590. return 0;
  591. out_free_targ_name:
  592. kfree(ctx->targ_name.display_name.data);
  593. ctx->targ_name.display_name.data = NULL;
  594. out_free_src_name:
  595. kfree(ctx->src_name.display_name.data);
  596. ctx->src_name.display_name.data = NULL;
  597. out_free_mech:
  598. kfree(ctx->mech.data);
  599. ctx->mech.data = NULL;
  600. out_free_state:
  601. kfree(ctx->state.data);
  602. ctx->state.data = NULL;
  603. out_free_exported_context_token:
  604. kfree(ctx->exported_context_token.data);
  605. ctx->exported_context_token.data = NULL;
  606. return err;
  607. }
  608. static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb)
  609. {
  610. __be32 *p;
  611. int err;
  612. /* cb->initiator_addrtype */
  613. p = xdr_reserve_space(xdr, 8);
  614. if (!p)
  615. return -ENOSPC;
  616. p = xdr_encode_hyper(p, cb->initiator_addrtype);
  617. /* cb->initiator_address */
  618. err = gssx_enc_buffer(xdr, &cb->initiator_address);
  619. if (err)
  620. return err;
  621. /* cb->acceptor_addrtype */
  622. p = xdr_reserve_space(xdr, 8);
  623. if (!p)
  624. return -ENOSPC;
  625. p = xdr_encode_hyper(p, cb->acceptor_addrtype);
  626. /* cb->acceptor_address */
  627. err = gssx_enc_buffer(xdr, &cb->acceptor_address);
  628. if (err)
  629. return err;
  630. /* cb->application_data */
  631. err = gssx_enc_buffer(xdr, &cb->application_data);
  632. return err;
  633. }
  634. void gssx_enc_accept_sec_context(struct rpc_rqst *req,
  635. struct xdr_stream *xdr,
  636. const void *data)
  637. {
  638. const struct gssx_arg_accept_sec_context *arg = data;
  639. int err;
  640. err = gssx_enc_call_ctx(xdr, &arg->call_ctx);
  641. if (err)
  642. goto done;
  643. /* arg->context_handle */
  644. if (arg->context_handle)
  645. err = gssx_enc_ctx(xdr, arg->context_handle);
  646. else
  647. err = gssx_enc_bool(xdr, 0);
  648. if (err)
  649. goto done;
  650. /* arg->cred_handle */
  651. if (arg->cred_handle)
  652. err = gssx_enc_cred(xdr, arg->cred_handle);
  653. else
  654. err = gssx_enc_bool(xdr, 0);
  655. if (err)
  656. goto done;
  657. /* arg->input_token */
  658. err = gssx_enc_in_token(xdr, &arg->input_token);
  659. if (err)
  660. goto done;
  661. /* arg->input_cb */
  662. if (arg->input_cb)
  663. err = gssx_enc_cb(xdr, arg->input_cb);
  664. else
  665. err = gssx_enc_bool(xdr, 0);
  666. if (err)
  667. goto done;
  668. err = gssx_enc_bool(xdr, arg->ret_deleg_cred);
  669. if (err)
  670. goto done;
  671. /* leave options empty for now, will add once we have any options
  672. * to pass up at all */
  673. /* arg->options */
  674. err = dummy_enc_opt_array(xdr, &arg->options);
  675. xdr_inline_pages(&req->rq_rcv_buf,
  676. PAGE_SIZE/2 /* pretty arbitrary */,
  677. arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
  678. done:
  679. if (err)
  680. dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
  681. }
  682. int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
  683. struct xdr_stream *xdr,
  684. void *data)
  685. {
  686. struct gssx_res_accept_sec_context *res = data;
  687. u32 value_follows;
  688. int err;
  689. struct folio *scratch;
  690. scratch = folio_alloc(GFP_KERNEL, 0);
  691. if (!scratch)
  692. return -ENOMEM;
  693. xdr_set_scratch_folio(xdr, scratch);
  694. /* res->status */
  695. err = gssx_dec_status(xdr, &res->status);
  696. if (err)
  697. goto out_free;
  698. /* res->context_handle */
  699. err = gssx_dec_bool(xdr, &value_follows);
  700. if (err)
  701. goto out_free;
  702. if (value_follows) {
  703. err = gssx_dec_ctx(xdr, res->context_handle);
  704. if (err)
  705. goto out_free;
  706. } else {
  707. res->context_handle = NULL;
  708. }
  709. /* res->output_token */
  710. err = gssx_dec_bool(xdr, &value_follows);
  711. if (err)
  712. goto out_free;
  713. if (value_follows) {
  714. err = gssx_dec_buffer(xdr, res->output_token);
  715. if (err)
  716. goto out_free;
  717. } else {
  718. res->output_token = NULL;
  719. }
  720. /* res->delegated_cred_handle */
  721. err = gssx_dec_bool(xdr, &value_follows);
  722. if (err)
  723. goto out_free;
  724. if (value_follows) {
  725. /* we do not support upcall servers sending this data. */
  726. err = -EINVAL;
  727. goto out_free;
  728. }
  729. /* res->options */
  730. err = gssx_dec_option_array(xdr, &res->options);
  731. out_free:
  732. folio_put(scratch);
  733. return err;
  734. }