gss_rpc_xdr.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  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_s32(void **p, void *max, s32 *res)
  141. {
  142. void *base = *p;
  143. void *next = (void *)((char *)base + sizeof(s32));
  144. if (unlikely(next > max || next < base))
  145. return -EINVAL;
  146. memcpy(res, base, sizeof(s32));
  147. *p = next;
  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. void *q, *end;
  156. s32 tmp;
  157. int N, i, err;
  158. p = xdr_inline_decode(xdr, 4);
  159. if (unlikely(p == NULL))
  160. return -ENOSPC;
  161. length = be32_to_cpup(p);
  162. /* FIXME: we do not want to use the scratch buffer for this one
  163. * may need to use functions that allows us to access an io vector
  164. * directly */
  165. p = xdr_inline_decode(xdr, length);
  166. if (unlikely(p == NULL))
  167. return -ENOSPC;
  168. q = p;
  169. end = q + length;
  170. /* uid */
  171. err = get_s32(&q, end, &tmp);
  172. if (err)
  173. return err;
  174. creds->cr_uid = make_kuid(&init_user_ns, tmp);
  175. /* gid */
  176. err = get_s32(&q, end, &tmp);
  177. if (err)
  178. return err;
  179. creds->cr_gid = make_kgid(&init_user_ns, tmp);
  180. /* number of additional gid's */
  181. err = get_s32(&q, end, &tmp);
  182. if (err)
  183. return err;
  184. N = tmp;
  185. creds->cr_group_info = groups_alloc(N);
  186. if (creds->cr_group_info == NULL)
  187. return -ENOMEM;
  188. /* gid's */
  189. for (i = 0; i < N; i++) {
  190. kgid_t kgid;
  191. err = get_s32(&q, end, &tmp);
  192. if (err)
  193. goto out_free_groups;
  194. err = -EINVAL;
  195. kgid = make_kgid(&init_user_ns, tmp);
  196. if (!gid_valid(kgid))
  197. goto out_free_groups;
  198. GROUP_AT(creds->cr_group_info, i) = kgid;
  199. }
  200. return 0;
  201. out_free_groups:
  202. groups_free(creds->cr_group_info);
  203. return err;
  204. }
  205. static int gssx_dec_option_array(struct xdr_stream *xdr,
  206. struct gssx_option_array *oa)
  207. {
  208. struct svc_cred *creds;
  209. u32 count, i;
  210. __be32 *p;
  211. int err;
  212. p = xdr_inline_decode(xdr, 4);
  213. if (unlikely(p == NULL))
  214. return -ENOSPC;
  215. count = be32_to_cpup(p++);
  216. if (!count)
  217. return 0;
  218. /* we recognize only 1 currently: CREDS_VALUE */
  219. oa->count = 1;
  220. oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL);
  221. if (!oa->data)
  222. return -ENOMEM;
  223. creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL);
  224. if (!creds) {
  225. kfree(oa->data);
  226. return -ENOMEM;
  227. }
  228. oa->data[0].option.data = CREDS_VALUE;
  229. oa->data[0].option.len = sizeof(CREDS_VALUE);
  230. oa->data[0].value.data = (void *)creds;
  231. oa->data[0].value.len = 0;
  232. for (i = 0; i < count; i++) {
  233. gssx_buffer dummy = { 0, NULL };
  234. u32 length;
  235. /* option buffer */
  236. p = xdr_inline_decode(xdr, 4);
  237. if (unlikely(p == NULL))
  238. return -ENOSPC;
  239. length = be32_to_cpup(p);
  240. p = xdr_inline_decode(xdr, length);
  241. if (unlikely(p == NULL))
  242. return -ENOSPC;
  243. if (length == sizeof(CREDS_VALUE) &&
  244. memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) {
  245. /* We have creds here. parse them */
  246. err = gssx_dec_linux_creds(xdr, creds);
  247. if (err)
  248. return err;
  249. oa->data[0].value.len = 1; /* presence */
  250. } else {
  251. /* consume uninteresting buffer */
  252. err = gssx_dec_buffer(xdr, &dummy);
  253. if (err)
  254. return err;
  255. }
  256. }
  257. return 0;
  258. }
  259. static int gssx_dec_status(struct xdr_stream *xdr,
  260. struct gssx_status *status)
  261. {
  262. __be32 *p;
  263. int err;
  264. /* status->major_status */
  265. p = xdr_inline_decode(xdr, 8);
  266. if (unlikely(p == NULL))
  267. return -ENOSPC;
  268. p = xdr_decode_hyper(p, &status->major_status);
  269. /* status->mech */
  270. err = gssx_dec_buffer(xdr, &status->mech);
  271. if (err)
  272. return err;
  273. /* status->minor_status */
  274. p = xdr_inline_decode(xdr, 8);
  275. if (unlikely(p == NULL))
  276. return -ENOSPC;
  277. p = xdr_decode_hyper(p, &status->minor_status);
  278. /* status->major_status_string */
  279. err = gssx_dec_buffer(xdr, &status->major_status_string);
  280. if (err)
  281. return err;
  282. /* status->minor_status_string */
  283. err = gssx_dec_buffer(xdr, &status->minor_status_string);
  284. if (err)
  285. return err;
  286. /* status->server_ctx */
  287. err = gssx_dec_buffer(xdr, &status->server_ctx);
  288. if (err)
  289. return err;
  290. /* we assume we have no options for now, so simply consume them */
  291. /* status->options */
  292. err = dummy_dec_opt_array(xdr, &status->options);
  293. return err;
  294. }
  295. static int gssx_enc_call_ctx(struct xdr_stream *xdr,
  296. struct gssx_call_ctx *ctx)
  297. {
  298. struct gssx_option opt;
  299. __be32 *p;
  300. int err;
  301. /* ctx->locale */
  302. err = gssx_enc_buffer(xdr, &ctx->locale);
  303. if (err)
  304. return err;
  305. /* ctx->server_ctx */
  306. err = gssx_enc_buffer(xdr, &ctx->server_ctx);
  307. if (err)
  308. return err;
  309. /* we always want to ask for lucid contexts */
  310. /* ctx->options */
  311. p = xdr_reserve_space(xdr, 4);
  312. *p = cpu_to_be32(2);
  313. /* we want a lucid_v1 context */
  314. opt.option.data = LUCID_OPTION;
  315. opt.option.len = sizeof(LUCID_OPTION);
  316. opt.value.data = LUCID_VALUE;
  317. opt.value.len = sizeof(LUCID_VALUE);
  318. err = gssx_enc_option(xdr, &opt);
  319. /* ..and user creds */
  320. opt.option.data = CREDS_OPTION;
  321. opt.option.len = sizeof(CREDS_OPTION);
  322. opt.value.data = CREDS_VALUE;
  323. opt.value.len = sizeof(CREDS_VALUE);
  324. err = gssx_enc_option(xdr, &opt);
  325. return err;
  326. }
  327. static int gssx_dec_name_attr(struct xdr_stream *xdr,
  328. struct gssx_name_attr *attr)
  329. {
  330. int err;
  331. /* attr->attr */
  332. err = gssx_dec_buffer(xdr, &attr->attr);
  333. if (err)
  334. return err;
  335. /* attr->value */
  336. err = gssx_dec_buffer(xdr, &attr->value);
  337. if (err)
  338. return err;
  339. /* attr->extensions */
  340. err = dummy_dec_opt_array(xdr, &attr->extensions);
  341. return err;
  342. }
  343. static int dummy_enc_nameattr_array(struct xdr_stream *xdr,
  344. struct gssx_name_attr_array *naa)
  345. {
  346. __be32 *p;
  347. if (naa->count != 0)
  348. return -EINVAL;
  349. p = xdr_reserve_space(xdr, 4);
  350. if (!p)
  351. return -ENOSPC;
  352. *p = 0;
  353. return 0;
  354. }
  355. static int dummy_dec_nameattr_array(struct xdr_stream *xdr,
  356. struct gssx_name_attr_array *naa)
  357. {
  358. struct gssx_name_attr dummy;
  359. u32 count, i;
  360. __be32 *p;
  361. p = xdr_inline_decode(xdr, 4);
  362. if (unlikely(p == NULL))
  363. return -ENOSPC;
  364. count = be32_to_cpup(p++);
  365. for (i = 0; i < count; i++) {
  366. gssx_dec_name_attr(xdr, &dummy);
  367. }
  368. naa->count = 0;
  369. naa->data = NULL;
  370. return 0;
  371. }
  372. static struct xdr_netobj zero_netobj = {};
  373. static struct gssx_name_attr_array zero_name_attr_array = {};
  374. static struct gssx_option_array zero_option_array = {};
  375. static int gssx_enc_name(struct xdr_stream *xdr,
  376. struct gssx_name *name)
  377. {
  378. int err;
  379. /* name->display_name */
  380. err = gssx_enc_buffer(xdr, &name->display_name);
  381. if (err)
  382. return err;
  383. /* name->name_type */
  384. err = gssx_enc_buffer(xdr, &zero_netobj);
  385. if (err)
  386. return err;
  387. /* name->exported_name */
  388. err = gssx_enc_buffer(xdr, &zero_netobj);
  389. if (err)
  390. return err;
  391. /* name->exported_composite_name */
  392. err = gssx_enc_buffer(xdr, &zero_netobj);
  393. if (err)
  394. return err;
  395. /* leave name_attributes empty for now, will add once we have any
  396. * to pass up at all */
  397. /* name->name_attributes */
  398. err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array);
  399. if (err)
  400. return err;
  401. /* leave options empty for now, will add once we have any options
  402. * to pass up at all */
  403. /* name->extensions */
  404. err = dummy_enc_opt_array(xdr, &zero_option_array);
  405. return err;
  406. }
  407. static int gssx_dec_name(struct xdr_stream *xdr,
  408. struct gssx_name *name)
  409. {
  410. struct xdr_netobj dummy_netobj;
  411. struct gssx_name_attr_array dummy_name_attr_array;
  412. struct gssx_option_array dummy_option_array;
  413. int err;
  414. /* name->display_name */
  415. err = gssx_dec_buffer(xdr, &name->display_name);
  416. if (err)
  417. return err;
  418. /* name->name_type */
  419. err = gssx_dec_buffer(xdr, &dummy_netobj);
  420. if (err)
  421. return err;
  422. /* name->exported_name */
  423. err = gssx_dec_buffer(xdr, &dummy_netobj);
  424. if (err)
  425. return err;
  426. /* name->exported_composite_name */
  427. err = gssx_dec_buffer(xdr, &dummy_netobj);
  428. if (err)
  429. return err;
  430. /* we assume we have no attributes for now, so simply consume them */
  431. /* name->name_attributes */
  432. err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array);
  433. if (err)
  434. return err;
  435. /* we assume we have no options for now, so simply consume them */
  436. /* name->extensions */
  437. err = dummy_dec_opt_array(xdr, &dummy_option_array);
  438. return err;
  439. }
  440. static int dummy_enc_credel_array(struct xdr_stream *xdr,
  441. struct gssx_cred_element_array *cea)
  442. {
  443. __be32 *p;
  444. if (cea->count != 0)
  445. return -EINVAL;
  446. p = xdr_reserve_space(xdr, 4);
  447. if (!p)
  448. return -ENOSPC;
  449. *p = 0;
  450. return 0;
  451. }
  452. static int gssx_enc_cred(struct xdr_stream *xdr,
  453. struct gssx_cred *cred)
  454. {
  455. int err;
  456. /* cred->desired_name */
  457. err = gssx_enc_name(xdr, &cred->desired_name);
  458. if (err)
  459. return err;
  460. /* cred->elements */
  461. err = dummy_enc_credel_array(xdr, &cred->elements);
  462. /* cred->cred_handle_reference */
  463. err = gssx_enc_buffer(xdr, &cred->cred_handle_reference);
  464. if (err)
  465. return err;
  466. /* cred->needs_release */
  467. err = gssx_enc_bool(xdr, cred->needs_release);
  468. return err;
  469. }
  470. static int gssx_enc_ctx(struct xdr_stream *xdr,
  471. struct gssx_ctx *ctx)
  472. {
  473. __be32 *p;
  474. int err;
  475. /* ctx->exported_context_token */
  476. err = gssx_enc_buffer(xdr, &ctx->exported_context_token);
  477. if (err)
  478. return err;
  479. /* ctx->state */
  480. err = gssx_enc_buffer(xdr, &ctx->state);
  481. if (err)
  482. return err;
  483. /* ctx->need_release */
  484. err = gssx_enc_bool(xdr, ctx->need_release);
  485. if (err)
  486. return err;
  487. /* ctx->mech */
  488. err = gssx_enc_buffer(xdr, &ctx->mech);
  489. if (err)
  490. return err;
  491. /* ctx->src_name */
  492. err = gssx_enc_name(xdr, &ctx->src_name);
  493. if (err)
  494. return err;
  495. /* ctx->targ_name */
  496. err = gssx_enc_name(xdr, &ctx->targ_name);
  497. if (err)
  498. return err;
  499. /* ctx->lifetime */
  500. p = xdr_reserve_space(xdr, 8+8);
  501. if (!p)
  502. return -ENOSPC;
  503. p = xdr_encode_hyper(p, ctx->lifetime);
  504. /* ctx->ctx_flags */
  505. p = xdr_encode_hyper(p, ctx->ctx_flags);
  506. /* ctx->locally_initiated */
  507. err = gssx_enc_bool(xdr, ctx->locally_initiated);
  508. if (err)
  509. return err;
  510. /* ctx->open */
  511. err = gssx_enc_bool(xdr, ctx->open);
  512. if (err)
  513. return err;
  514. /* leave options empty for now, will add once we have any options
  515. * to pass up at all */
  516. /* ctx->options */
  517. err = dummy_enc_opt_array(xdr, &ctx->options);
  518. return err;
  519. }
  520. static int gssx_dec_ctx(struct xdr_stream *xdr,
  521. struct gssx_ctx *ctx)
  522. {
  523. __be32 *p;
  524. int err;
  525. /* ctx->exported_context_token */
  526. err = gssx_dec_buffer(xdr, &ctx->exported_context_token);
  527. if (err)
  528. return err;
  529. /* ctx->state */
  530. err = gssx_dec_buffer(xdr, &ctx->state);
  531. if (err)
  532. return err;
  533. /* ctx->need_release */
  534. err = gssx_dec_bool(xdr, &ctx->need_release);
  535. if (err)
  536. return err;
  537. /* ctx->mech */
  538. err = gssx_dec_buffer(xdr, &ctx->mech);
  539. if (err)
  540. return err;
  541. /* ctx->src_name */
  542. err = gssx_dec_name(xdr, &ctx->src_name);
  543. if (err)
  544. return err;
  545. /* ctx->targ_name */
  546. err = gssx_dec_name(xdr, &ctx->targ_name);
  547. if (err)
  548. return err;
  549. /* ctx->lifetime */
  550. p = xdr_inline_decode(xdr, 8+8);
  551. if (unlikely(p == NULL))
  552. return -ENOSPC;
  553. p = xdr_decode_hyper(p, &ctx->lifetime);
  554. /* ctx->ctx_flags */
  555. p = xdr_decode_hyper(p, &ctx->ctx_flags);
  556. /* ctx->locally_initiated */
  557. err = gssx_dec_bool(xdr, &ctx->locally_initiated);
  558. if (err)
  559. return err;
  560. /* ctx->open */
  561. err = gssx_dec_bool(xdr, &ctx->open);
  562. if (err)
  563. return err;
  564. /* we assume we have no options for now, so simply consume them */
  565. /* ctx->options */
  566. err = dummy_dec_opt_array(xdr, &ctx->options);
  567. return err;
  568. }
  569. static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb)
  570. {
  571. __be32 *p;
  572. int err;
  573. /* cb->initiator_addrtype */
  574. p = xdr_reserve_space(xdr, 8);
  575. if (!p)
  576. return -ENOSPC;
  577. p = xdr_encode_hyper(p, cb->initiator_addrtype);
  578. /* cb->initiator_address */
  579. err = gssx_enc_buffer(xdr, &cb->initiator_address);
  580. if (err)
  581. return err;
  582. /* cb->acceptor_addrtype */
  583. p = xdr_reserve_space(xdr, 8);
  584. if (!p)
  585. return -ENOSPC;
  586. p = xdr_encode_hyper(p, cb->acceptor_addrtype);
  587. /* cb->acceptor_address */
  588. err = gssx_enc_buffer(xdr, &cb->acceptor_address);
  589. if (err)
  590. return err;
  591. /* cb->application_data */
  592. err = gssx_enc_buffer(xdr, &cb->application_data);
  593. return err;
  594. }
  595. void gssx_enc_accept_sec_context(struct rpc_rqst *req,
  596. struct xdr_stream *xdr,
  597. struct gssx_arg_accept_sec_context *arg)
  598. {
  599. int err;
  600. err = gssx_enc_call_ctx(xdr, &arg->call_ctx);
  601. if (err)
  602. goto done;
  603. /* arg->context_handle */
  604. if (arg->context_handle) {
  605. err = gssx_enc_ctx(xdr, arg->context_handle);
  606. if (err)
  607. goto done;
  608. } else {
  609. err = gssx_enc_bool(xdr, 0);
  610. }
  611. /* arg->cred_handle */
  612. if (arg->cred_handle) {
  613. err = gssx_enc_cred(xdr, arg->cred_handle);
  614. if (err)
  615. goto done;
  616. } else {
  617. err = gssx_enc_bool(xdr, 0);
  618. }
  619. /* arg->input_token */
  620. err = gssx_enc_in_token(xdr, &arg->input_token);
  621. if (err)
  622. goto done;
  623. /* arg->input_cb */
  624. if (arg->input_cb) {
  625. err = gssx_enc_cb(xdr, arg->input_cb);
  626. if (err)
  627. goto done;
  628. } else {
  629. err = gssx_enc_bool(xdr, 0);
  630. }
  631. err = gssx_enc_bool(xdr, arg->ret_deleg_cred);
  632. if (err)
  633. goto done;
  634. /* leave options empty for now, will add once we have any options
  635. * to pass up at all */
  636. /* arg->options */
  637. err = dummy_enc_opt_array(xdr, &arg->options);
  638. done:
  639. if (err)
  640. dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
  641. }
  642. int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
  643. struct xdr_stream *xdr,
  644. struct gssx_res_accept_sec_context *res)
  645. {
  646. u32 value_follows;
  647. int err;
  648. /* res->status */
  649. err = gssx_dec_status(xdr, &res->status);
  650. if (err)
  651. return err;
  652. /* res->context_handle */
  653. err = gssx_dec_bool(xdr, &value_follows);
  654. if (err)
  655. return err;
  656. if (value_follows) {
  657. err = gssx_dec_ctx(xdr, res->context_handle);
  658. if (err)
  659. return err;
  660. } else {
  661. res->context_handle = NULL;
  662. }
  663. /* res->output_token */
  664. err = gssx_dec_bool(xdr, &value_follows);
  665. if (err)
  666. return err;
  667. if (value_follows) {
  668. err = gssx_dec_buffer(xdr, res->output_token);
  669. if (err)
  670. return err;
  671. } else {
  672. res->output_token = NULL;
  673. }
  674. /* res->delegated_cred_handle */
  675. err = gssx_dec_bool(xdr, &value_follows);
  676. if (err)
  677. return err;
  678. if (value_follows) {
  679. /* we do not support upcall servers sending this data. */
  680. return -EINVAL;
  681. }
  682. /* res->options */
  683. err = gssx_dec_option_array(xdr, &res->options);
  684. return err;
  685. }