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