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 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 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 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_s32(void **p, void *max, s32 *res) 170 { 171 void *base = *p; 172 void *next = (void *)((char *)base + sizeof(s32)); 173 if (unlikely(next > max || next < base)) 174 return -EINVAL; 175 memcpy(res, base, sizeof(s32)); 176 *p = next; 177 return 0; 178 } 179 180 static int gssx_dec_linux_creds(struct xdr_stream *xdr, 181 struct svc_cred *creds) 182 { 183 u32 length; 184 __be32 *p; 185 void *q, *end; 186 s32 tmp; 187 int N, i, err; 188 189 p = xdr_inline_decode(xdr, 4); 190 if (unlikely(p == NULL)) 191 return -ENOSPC; 192 193 length = be32_to_cpup(p); 194 195 /* FIXME: we do not want to use the scratch buffer for this one 196 * may need to use functions that allows us to access an io vector 197 * directly */ 198 p = xdr_inline_decode(xdr, length); 199 if (unlikely(p == NULL)) 200 return -ENOSPC; 201 202 q = p; 203 end = q + length; 204 205 /* uid */ 206 err = get_s32(&q, end, &tmp); 207 if (err) 208 return err; 209 creds->cr_uid = make_kuid(&init_user_ns, tmp); 210 211 /* gid */ 212 err = get_s32(&q, end, &tmp); 213 if (err) 214 return err; 215 creds->cr_gid = make_kgid(&init_user_ns, tmp); 216 217 /* number of additional gid's */ 218 err = get_s32(&q, end, &tmp); 219 if (err) 220 return err; 221 N = tmp; 222 creds->cr_group_info = groups_alloc(N); 223 if (creds->cr_group_info == NULL) 224 return -ENOMEM; 225 226 /* gid's */ 227 for (i = 0; i < N; i++) { 228 kgid_t kgid; 229 err = get_s32(&q, end, &tmp); 230 if (err) 231 goto out_free_groups; 232 err = -EINVAL; 233 kgid = make_kgid(&init_user_ns, tmp); 234 if (!gid_valid(kgid)) 235 goto out_free_groups; 236 GROUP_AT(creds->cr_group_info, i) = kgid; 237 } 238 239 return 0; 240 out_free_groups: 241 groups_free(creds->cr_group_info); 242 return err; 243 } 244 245 static int gssx_dec_option_array(struct xdr_stream *xdr, 246 struct gssx_option_array *oa) 247 { 248 struct svc_cred *creds; 249 u32 count, i; 250 __be32 *p; 251 int err; 252 253 p = xdr_inline_decode(xdr, 4); 254 if (unlikely(p == NULL)) 255 return -ENOSPC; 256 count = be32_to_cpup(p++); 257 if (!count) 258 return 0; 259 260 /* we recognize only 1 currently: CREDS_VALUE */ 261 oa->count = 1; 262 263 oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); 264 if (!oa->data) 265 return -ENOMEM; 266 267 creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); 268 if (!creds) { 269 kfree(oa->data); 270 return -ENOMEM; 271 } 272 273 oa->data[0].option.data = CREDS_VALUE; 274 oa->data[0].option.len = sizeof(CREDS_VALUE); 275 oa->data[0].value.data = (void *)creds; 276 oa->data[0].value.len = 0; 277 278 for (i = 0; i < count; i++) { 279 gssx_buffer dummy = { 0, NULL }; 280 u32 length; 281 282 /* option buffer */ 283 p = xdr_inline_decode(xdr, 4); 284 if (unlikely(p == NULL)) 285 return -ENOSPC; 286 287 length = be32_to_cpup(p); 288 p = xdr_inline_decode(xdr, length); 289 if (unlikely(p == NULL)) 290 return -ENOSPC; 291 292 if (length == sizeof(CREDS_VALUE) && 293 memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) { 294 /* We have creds here. parse them */ 295 err = gssx_dec_linux_creds(xdr, creds); 296 if (err) 297 return err; 298 oa->data[0].value.len = 1; /* presence */ 299 } else { 300 /* consume uninteresting buffer */ 301 err = gssx_dec_buffer(xdr, &dummy); 302 if (err) 303 return err; 304 } 305 } 306 return 0; 307 } 308 309 static int gssx_dec_status(struct xdr_stream *xdr, 310 struct gssx_status *status) 311 { 312 __be32 *p; 313 int err; 314 315 /* status->major_status */ 316 p = xdr_inline_decode(xdr, 8); 317 if (unlikely(p == NULL)) 318 return -ENOSPC; 319 p = xdr_decode_hyper(p, &status->major_status); 320 321 /* status->mech */ 322 err = gssx_dec_buffer(xdr, &status->mech); 323 if (err) 324 return err; 325 326 /* status->minor_status */ 327 p = xdr_inline_decode(xdr, 8); 328 if (unlikely(p == NULL)) 329 return -ENOSPC; 330 p = xdr_decode_hyper(p, &status->minor_status); 331 332 /* status->major_status_string */ 333 err = gssx_dec_buffer(xdr, &status->major_status_string); 334 if (err) 335 return err; 336 337 /* status->minor_status_string */ 338 err = gssx_dec_buffer(xdr, &status->minor_status_string); 339 if (err) 340 return err; 341 342 /* status->server_ctx */ 343 err = gssx_dec_buffer(xdr, &status->server_ctx); 344 if (err) 345 return err; 346 347 /* we assume we have no options for now, so simply consume them */ 348 /* status->options */ 349 err = dummy_dec_opt_array(xdr, &status->options); 350 351 return err; 352 } 353 354 static int gssx_enc_call_ctx(struct xdr_stream *xdr, 355 struct gssx_call_ctx *ctx) 356 { 357 struct gssx_option opt; 358 __be32 *p; 359 int err; 360 361 /* ctx->locale */ 362 err = gssx_enc_buffer(xdr, &ctx->locale); 363 if (err) 364 return err; 365 366 /* ctx->server_ctx */ 367 err = gssx_enc_buffer(xdr, &ctx->server_ctx); 368 if (err) 369 return err; 370 371 /* we always want to ask for lucid contexts */ 372 /* ctx->options */ 373 p = xdr_reserve_space(xdr, 4); 374 *p = cpu_to_be32(2); 375 376 /* we want a lucid_v1 context */ 377 opt.option.data = LUCID_OPTION; 378 opt.option.len = sizeof(LUCID_OPTION); 379 opt.value.data = LUCID_VALUE; 380 opt.value.len = sizeof(LUCID_VALUE); 381 err = gssx_enc_option(xdr, &opt); 382 383 /* ..and user creds */ 384 opt.option.data = CREDS_OPTION; 385 opt.option.len = sizeof(CREDS_OPTION); 386 opt.value.data = CREDS_VALUE; 387 opt.value.len = sizeof(CREDS_VALUE); 388 err = gssx_enc_option(xdr, &opt); 389 390 return err; 391 } 392 393 static int gssx_dec_name_attr(struct xdr_stream *xdr, 394 struct gssx_name_attr *attr) 395 { 396 int err; 397 398 /* attr->attr */ 399 err = gssx_dec_buffer(xdr, &attr->attr); 400 if (err) 401 return err; 402 403 /* attr->value */ 404 err = gssx_dec_buffer(xdr, &attr->value); 405 if (err) 406 return err; 407 408 /* attr->extensions */ 409 err = dummy_dec_opt_array(xdr, &attr->extensions); 410 411 return err; 412 } 413 414 static int dummy_enc_nameattr_array(struct xdr_stream *xdr, 415 struct gssx_name_attr_array *naa) 416 { 417 __be32 *p; 418 419 if (naa->count != 0) 420 return -EINVAL; 421 422 p = xdr_reserve_space(xdr, 4); 423 if (!p) 424 return -ENOSPC; 425 *p = 0; 426 427 return 0; 428 } 429 430 static int dummy_dec_nameattr_array(struct xdr_stream *xdr, 431 struct gssx_name_attr_array *naa) 432 { 433 struct gssx_name_attr dummy; 434 u32 count, i; 435 __be32 *p; 436 437 p = xdr_inline_decode(xdr, 4); 438 if (unlikely(p == NULL)) 439 return -ENOSPC; 440 count = be32_to_cpup(p++); 441 for (i = 0; i < count; i++) { 442 gssx_dec_name_attr(xdr, &dummy); 443 } 444 445 naa->count = 0; 446 naa->data = NULL; 447 return 0; 448 } 449 450 static struct xdr_netobj zero_netobj = {}; 451 452 static struct gssx_name_attr_array zero_name_attr_array = {}; 453 454 static struct gssx_option_array zero_option_array = {}; 455 456 static int gssx_enc_name(struct xdr_stream *xdr, 457 struct gssx_name *name) 458 { 459 int err; 460 461 /* name->display_name */ 462 err = gssx_enc_buffer(xdr, &name->display_name); 463 if (err) 464 return err; 465 466 /* name->name_type */ 467 err = gssx_enc_buffer(xdr, &zero_netobj); 468 if (err) 469 return err; 470 471 /* name->exported_name */ 472 err = gssx_enc_buffer(xdr, &zero_netobj); 473 if (err) 474 return err; 475 476 /* name->exported_composite_name */ 477 err = gssx_enc_buffer(xdr, &zero_netobj); 478 if (err) 479 return err; 480 481 /* leave name_attributes empty for now, will add once we have any 482 * to pass up at all */ 483 /* name->name_attributes */ 484 err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array); 485 if (err) 486 return err; 487 488 /* leave options empty for now, will add once we have any options 489 * to pass up at all */ 490 /* name->extensions */ 491 err = dummy_enc_opt_array(xdr, &zero_option_array); 492 493 return err; 494 } 495 496 static int gssx_dec_name(struct xdr_stream *xdr, 497 struct gssx_name *name) 498 { 499 struct xdr_netobj dummy_netobj; 500 struct gssx_name_attr_array dummy_name_attr_array; 501 struct gssx_option_array dummy_option_array; 502 int err; 503 504 /* name->display_name */ 505 err = gssx_dec_buffer(xdr, &name->display_name); 506 if (err) 507 return err; 508 509 /* name->name_type */ 510 err = gssx_dec_buffer(xdr, &dummy_netobj); 511 if (err) 512 return err; 513 514 /* name->exported_name */ 515 err = gssx_dec_buffer(xdr, &dummy_netobj); 516 if (err) 517 return err; 518 519 /* name->exported_composite_name */ 520 err = gssx_dec_buffer(xdr, &dummy_netobj); 521 if (err) 522 return err; 523 524 /* we assume we have no attributes for now, so simply consume them */ 525 /* name->name_attributes */ 526 err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); 527 if (err) 528 return err; 529 530 /* we assume we have no options for now, so simply consume them */ 531 /* name->extensions */ 532 err = dummy_dec_opt_array(xdr, &dummy_option_array); 533 534 return err; 535 } 536 537 static int dummy_enc_credel_array(struct xdr_stream *xdr, 538 struct gssx_cred_element_array *cea) 539 { 540 __be32 *p; 541 542 if (cea->count != 0) 543 return -EINVAL; 544 545 p = xdr_reserve_space(xdr, 4); 546 if (!p) 547 return -ENOSPC; 548 *p = 0; 549 550 return 0; 551 } 552 553 static int gssx_enc_cred(struct xdr_stream *xdr, 554 struct gssx_cred *cred) 555 { 556 int err; 557 558 /* cred->desired_name */ 559 err = gssx_enc_name(xdr, &cred->desired_name); 560 if (err) 561 return err; 562 563 /* cred->elements */ 564 err = dummy_enc_credel_array(xdr, &cred->elements); 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 struct gssx_arg_accept_sec_context *arg) 738 { 739 int err; 740 741 err = gssx_enc_call_ctx(xdr, &arg->call_ctx); 742 if (err) 743 goto done; 744 745 /* arg->context_handle */ 746 if (arg->context_handle) { 747 err = gssx_enc_ctx(xdr, arg->context_handle); 748 if (err) 749 goto done; 750 } else { 751 err = gssx_enc_bool(xdr, 0); 752 } 753 754 /* arg->cred_handle */ 755 if (arg->cred_handle) { 756 err = gssx_enc_cred(xdr, arg->cred_handle); 757 if (err) 758 goto done; 759 } else { 760 err = gssx_enc_bool(xdr, 0); 761 } 762 763 /* arg->input_token */ 764 err = gssx_enc_in_token(xdr, &arg->input_token); 765 if (err) 766 goto done; 767 768 /* arg->input_cb */ 769 if (arg->input_cb) { 770 err = gssx_enc_cb(xdr, arg->input_cb); 771 if (err) 772 goto done; 773 } else { 774 err = gssx_enc_bool(xdr, 0); 775 } 776 777 err = gssx_enc_bool(xdr, arg->ret_deleg_cred); 778 if (err) 779 goto done; 780 781 /* leave options empty for now, will add once we have any options 782 * to pass up at all */ 783 /* arg->options */ 784 err = dummy_enc_opt_array(xdr, &arg->options); 785 786 done: 787 if (err) 788 dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); 789 } 790 791 int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, 792 struct xdr_stream *xdr, 793 struct gssx_res_accept_sec_context *res) 794 { 795 u32 value_follows; 796 int err; 797 798 /* res->status */ 799 err = gssx_dec_status(xdr, &res->status); 800 if (err) 801 return err; 802 803 /* res->context_handle */ 804 err = gssx_dec_bool(xdr, &value_follows); 805 if (err) 806 return err; 807 if (value_follows) { 808 err = gssx_dec_ctx(xdr, res->context_handle); 809 if (err) 810 return err; 811 } else { 812 res->context_handle = NULL; 813 } 814 815 /* res->output_token */ 816 err = gssx_dec_bool(xdr, &value_follows); 817 if (err) 818 return err; 819 if (value_follows) { 820 err = gssx_dec_buffer(xdr, res->output_token); 821 if (err) 822 return err; 823 } else { 824 res->output_token = NULL; 825 } 826 827 /* res->delegated_cred_handle */ 828 err = gssx_dec_bool(xdr, &value_follows); 829 if (err) 830 return err; 831 if (value_follows) { 832 /* we do not support upcall servers sending this data. */ 833 return -EINVAL; 834 } 835 836 /* res->options */ 837 err = gssx_dec_option_array(xdr, &res->options); 838 839 return err; 840 } 841