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