gss_rpc_xdr.c 17 KB

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