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 = { .attr = {.len = 0} }; 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 497 static int gssx_dec_name(struct xdr_stream *xdr, 498 struct gssx_name *name) 499 { 500 struct xdr_netobj dummy_netobj = { .len = 0 }; 501 struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 }; 502 struct gssx_option_array dummy_option_array = { .count = 0 }; 503 int err; 504 505 /* name->display_name */ 506 err = gssx_dec_buffer(xdr, &name->display_name); 507 if (err) 508 return err; 509 510 /* name->name_type */ 511 err = gssx_dec_buffer(xdr, &dummy_netobj); 512 if (err) 513 return err; 514 515 /* name->exported_name */ 516 err = gssx_dec_buffer(xdr, &dummy_netobj); 517 if (err) 518 return err; 519 520 /* name->exported_composite_name */ 521 err = gssx_dec_buffer(xdr, &dummy_netobj); 522 if (err) 523 return err; 524 525 /* we assume we have no attributes for now, so simply consume them */ 526 /* name->name_attributes */ 527 err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); 528 if (err) 529 return err; 530 531 /* we assume we have no options for now, so simply consume them */ 532 /* name->extensions */ 533 err = dummy_dec_opt_array(xdr, &dummy_option_array); 534 535 return err; 536 } 537 538 static int dummy_enc_credel_array(struct xdr_stream *xdr, 539 struct gssx_cred_element_array *cea) 540 { 541 __be32 *p; 542 543 if (cea->count != 0) 544 return -EINVAL; 545 546 p = xdr_reserve_space(xdr, 4); 547 if (!p) 548 return -ENOSPC; 549 *p = 0; 550 551 return 0; 552 } 553 554 static int gssx_enc_cred(struct xdr_stream *xdr, 555 struct gssx_cred *cred) 556 { 557 int err; 558 559 /* cred->desired_name */ 560 err = gssx_enc_name(xdr, &cred->desired_name); 561 if (err) 562 return err; 563 564 /* cred->elements */ 565 err = dummy_enc_credel_array(xdr, &cred->elements); 566 567 /* cred->cred_handle_reference */ 568 err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); 569 if (err) 570 return err; 571 572 /* cred->needs_release */ 573 err = gssx_enc_bool(xdr, cred->needs_release); 574 575 return err; 576 } 577 578 static int gssx_enc_ctx(struct xdr_stream *xdr, 579 struct gssx_ctx *ctx) 580 { 581 __be32 *p; 582 int err; 583 584 /* ctx->exported_context_token */ 585 err = gssx_enc_buffer(xdr, &ctx->exported_context_token); 586 if (err) 587 return err; 588 589 /* ctx->state */ 590 err = gssx_enc_buffer(xdr, &ctx->state); 591 if (err) 592 return err; 593 594 /* ctx->need_release */ 595 err = gssx_enc_bool(xdr, ctx->need_release); 596 if (err) 597 return err; 598 599 /* ctx->mech */ 600 err = gssx_enc_buffer(xdr, &ctx->mech); 601 if (err) 602 return err; 603 604 /* ctx->src_name */ 605 err = gssx_enc_name(xdr, &ctx->src_name); 606 if (err) 607 return err; 608 609 /* ctx->targ_name */ 610 err = gssx_enc_name(xdr, &ctx->targ_name); 611 if (err) 612 return err; 613 614 /* ctx->lifetime */ 615 p = xdr_reserve_space(xdr, 8+8); 616 if (!p) 617 return -ENOSPC; 618 p = xdr_encode_hyper(p, ctx->lifetime); 619 620 /* ctx->ctx_flags */ 621 p = xdr_encode_hyper(p, ctx->ctx_flags); 622 623 /* ctx->locally_initiated */ 624 err = gssx_enc_bool(xdr, ctx->locally_initiated); 625 if (err) 626 return err; 627 628 /* ctx->open */ 629 err = gssx_enc_bool(xdr, ctx->open); 630 if (err) 631 return err; 632 633 /* leave options empty for now, will add once we have any options 634 * to pass up at all */ 635 /* ctx->options */ 636 err = dummy_enc_opt_array(xdr, &ctx->options); 637 638 return err; 639 } 640 641 static int gssx_dec_ctx(struct xdr_stream *xdr, 642 struct gssx_ctx *ctx) 643 { 644 __be32 *p; 645 int err; 646 647 /* ctx->exported_context_token */ 648 err = gssx_dec_buffer(xdr, &ctx->exported_context_token); 649 if (err) 650 return err; 651 652 /* ctx->state */ 653 err = gssx_dec_buffer(xdr, &ctx->state); 654 if (err) 655 return err; 656 657 /* ctx->need_release */ 658 err = gssx_dec_bool(xdr, &ctx->need_release); 659 if (err) 660 return err; 661 662 /* ctx->mech */ 663 err = gssx_dec_buffer(xdr, &ctx->mech); 664 if (err) 665 return err; 666 667 /* ctx->src_name */ 668 err = gssx_dec_name(xdr, &ctx->src_name); 669 if (err) 670 return err; 671 672 /* ctx->targ_name */ 673 err = gssx_dec_name(xdr, &ctx->targ_name); 674 if (err) 675 return err; 676 677 /* ctx->lifetime */ 678 p = xdr_inline_decode(xdr, 8+8); 679 if (unlikely(p == NULL)) 680 return -ENOSPC; 681 p = xdr_decode_hyper(p, &ctx->lifetime); 682 683 /* ctx->ctx_flags */ 684 p = xdr_decode_hyper(p, &ctx->ctx_flags); 685 686 /* ctx->locally_initiated */ 687 err = gssx_dec_bool(xdr, &ctx->locally_initiated); 688 if (err) 689 return err; 690 691 /* ctx->open */ 692 err = gssx_dec_bool(xdr, &ctx->open); 693 if (err) 694 return err; 695 696 /* we assume we have no options for now, so simply consume them */ 697 /* ctx->options */ 698 err = dummy_dec_opt_array(xdr, &ctx->options); 699 700 return err; 701 } 702 703 static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb) 704 { 705 __be32 *p; 706 int err; 707 708 /* cb->initiator_addrtype */ 709 p = xdr_reserve_space(xdr, 8); 710 if (!p) 711 return -ENOSPC; 712 p = xdr_encode_hyper(p, cb->initiator_addrtype); 713 714 /* cb->initiator_address */ 715 err = gssx_enc_buffer(xdr, &cb->initiator_address); 716 if (err) 717 return err; 718 719 /* cb->acceptor_addrtype */ 720 p = xdr_reserve_space(xdr, 8); 721 if (!p) 722 return -ENOSPC; 723 p = xdr_encode_hyper(p, cb->acceptor_addrtype); 724 725 /* cb->acceptor_address */ 726 err = gssx_enc_buffer(xdr, &cb->acceptor_address); 727 if (err) 728 return err; 729 730 /* cb->application_data */ 731 err = gssx_enc_buffer(xdr, &cb->application_data); 732 733 return err; 734 } 735 736 void gssx_enc_accept_sec_context(struct rpc_rqst *req, 737 struct xdr_stream *xdr, 738 struct gssx_arg_accept_sec_context *arg) 739 { 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 if (err) 750 goto done; 751 } else { 752 err = gssx_enc_bool(xdr, 0); 753 } 754 755 /* arg->cred_handle */ 756 if (arg->cred_handle) { 757 err = gssx_enc_cred(xdr, arg->cred_handle); 758 if (err) 759 goto done; 760 } else { 761 err = gssx_enc_bool(xdr, 0); 762 } 763 764 /* arg->input_token */ 765 err = gssx_enc_in_token(xdr, &arg->input_token); 766 if (err) 767 goto done; 768 769 /* arg->input_cb */ 770 if (arg->input_cb) { 771 err = gssx_enc_cb(xdr, arg->input_cb); 772 if (err) 773 goto done; 774 } else { 775 err = gssx_enc_bool(xdr, 0); 776 } 777 778 err = gssx_enc_bool(xdr, arg->ret_deleg_cred); 779 if (err) 780 goto done; 781 782 /* leave options empty for now, will add once we have any options 783 * to pass up at all */ 784 /* arg->options */ 785 err = dummy_enc_opt_array(xdr, &arg->options); 786 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 struct gssx_res_accept_sec_context *res) 795 { 796 u32 value_follows; 797 int err; 798 799 /* res->status */ 800 err = gssx_dec_status(xdr, &res->status); 801 if (err) 802 return err; 803 804 /* res->context_handle */ 805 err = gssx_dec_bool(xdr, &value_follows); 806 if (err) 807 return err; 808 if (value_follows) { 809 err = gssx_dec_ctx(xdr, res->context_handle); 810 if (err) 811 return err; 812 } else { 813 res->context_handle = NULL; 814 } 815 816 /* res->output_token */ 817 err = gssx_dec_bool(xdr, &value_follows); 818 if (err) 819 return err; 820 if (value_follows) { 821 err = gssx_dec_buffer(xdr, res->output_token); 822 if (err) 823 return err; 824 } else { 825 res->output_token = NULL; 826 } 827 828 /* res->delegated_cred_handle */ 829 err = gssx_dec_bool(xdr, &value_follows); 830 if (err) 831 return err; 832 if (value_follows) { 833 /* we do not support upcall servers sending this data. */ 834 return -EINVAL; 835 } 836 837 /* res->options */ 838 err = gssx_dec_option_array(xdr, &res->options); 839 840 return err; 841 } 842