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