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