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 != 0) { 268 /* we recognize only 1 currently: CREDS_VALUE */ 269 oa->count = 1; 270 271 oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); 272 if (!oa->data) 273 return -ENOMEM; 274 275 creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); 276 if (!creds) { 277 kfree(oa->data); 278 return -ENOMEM; 279 } 280 281 oa->data[0].option.data = CREDS_VALUE; 282 oa->data[0].option.len = sizeof(CREDS_VALUE); 283 oa->data[0].value.data = (void *)creds; 284 oa->data[0].value.len = 0; 285 } 286 for (i = 0; i < count; i++) { 287 gssx_buffer dummy = { 0, NULL }; 288 u32 length; 289 290 /* option buffer */ 291 p = xdr_inline_decode(xdr, 4); 292 if (unlikely(p == NULL)) 293 return -ENOSPC; 294 295 length = be32_to_cpup(p); 296 p = xdr_inline_decode(xdr, length); 297 if (unlikely(p == NULL)) 298 return -ENOSPC; 299 300 if (length == sizeof(CREDS_VALUE) && 301 memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) { 302 /* We have creds here. parse them */ 303 err = gssx_dec_linux_creds(xdr, creds); 304 if (err) 305 return err; 306 oa->data[0].value.len = 1; /* presence */ 307 } else { 308 /* consume uninteresting buffer */ 309 err = gssx_dec_buffer(xdr, &dummy); 310 if (err) 311 return err; 312 } 313 } 314 return 0; 315 } 316 317 static int gssx_dec_status(struct xdr_stream *xdr, 318 struct gssx_status *status) 319 { 320 __be32 *p; 321 int err; 322 323 /* status->major_status */ 324 p = xdr_inline_decode(xdr, 8); 325 if (unlikely(p == NULL)) 326 return -ENOSPC; 327 p = xdr_decode_hyper(p, &status->major_status); 328 329 /* status->mech */ 330 err = gssx_dec_buffer(xdr, &status->mech); 331 if (err) 332 return err; 333 334 /* status->minor_status */ 335 p = xdr_inline_decode(xdr, 8); 336 if (unlikely(p == NULL)) 337 return -ENOSPC; 338 p = xdr_decode_hyper(p, &status->minor_status); 339 340 /* status->major_status_string */ 341 err = gssx_dec_buffer(xdr, &status->major_status_string); 342 if (err) 343 return err; 344 345 /* status->minor_status_string */ 346 err = gssx_dec_buffer(xdr, &status->minor_status_string); 347 if (err) 348 return err; 349 350 /* status->server_ctx */ 351 err = gssx_dec_buffer(xdr, &status->server_ctx); 352 if (err) 353 return err; 354 355 /* we assume we have no options for now, so simply consume them */ 356 /* status->options */ 357 err = dummy_dec_opt_array(xdr, &status->options); 358 359 return err; 360 } 361 362 static int gssx_enc_call_ctx(struct xdr_stream *xdr, 363 struct gssx_call_ctx *ctx) 364 { 365 struct gssx_option opt; 366 __be32 *p; 367 int err; 368 369 /* ctx->locale */ 370 err = gssx_enc_buffer(xdr, &ctx->locale); 371 if (err) 372 return err; 373 374 /* ctx->server_ctx */ 375 err = gssx_enc_buffer(xdr, &ctx->server_ctx); 376 if (err) 377 return err; 378 379 /* we always want to ask for lucid contexts */ 380 /* ctx->options */ 381 p = xdr_reserve_space(xdr, 4); 382 *p = cpu_to_be32(2); 383 384 /* we want a lucid_v1 context */ 385 opt.option.data = LUCID_OPTION; 386 opt.option.len = sizeof(LUCID_OPTION); 387 opt.value.data = LUCID_VALUE; 388 opt.value.len = sizeof(LUCID_VALUE); 389 err = gssx_enc_option(xdr, &opt); 390 391 /* ..and user creds */ 392 opt.option.data = CREDS_OPTION; 393 opt.option.len = sizeof(CREDS_OPTION); 394 opt.value.data = CREDS_VALUE; 395 opt.value.len = sizeof(CREDS_VALUE); 396 err = gssx_enc_option(xdr, &opt); 397 398 return err; 399 } 400 401 static int gssx_dec_name_attr(struct xdr_stream *xdr, 402 struct gssx_name_attr *attr) 403 { 404 int err; 405 406 /* attr->attr */ 407 err = gssx_dec_buffer(xdr, &attr->attr); 408 if (err) 409 return err; 410 411 /* attr->value */ 412 err = gssx_dec_buffer(xdr, &attr->value); 413 if (err) 414 return err; 415 416 /* attr->extensions */ 417 err = dummy_dec_opt_array(xdr, &attr->extensions); 418 419 return err; 420 } 421 422 static int dummy_enc_nameattr_array(struct xdr_stream *xdr, 423 struct gssx_name_attr_array *naa) 424 { 425 __be32 *p; 426 427 if (naa->count != 0) 428 return -EINVAL; 429 430 p = xdr_reserve_space(xdr, 4); 431 if (!p) 432 return -ENOSPC; 433 *p = 0; 434 435 return 0; 436 } 437 438 static int dummy_dec_nameattr_array(struct xdr_stream *xdr, 439 struct gssx_name_attr_array *naa) 440 { 441 struct gssx_name_attr dummy; 442 u32 count, i; 443 __be32 *p; 444 445 p = xdr_inline_decode(xdr, 4); 446 if (unlikely(p == NULL)) 447 return -ENOSPC; 448 count = be32_to_cpup(p++); 449 for (i = 0; i < count; i++) { 450 gssx_dec_name_attr(xdr, &dummy); 451 } 452 453 naa->count = 0; 454 naa->data = NULL; 455 return 0; 456 } 457 458 static struct xdr_netobj zero_netobj = {}; 459 460 static struct gssx_name_attr_array zero_name_attr_array = {}; 461 462 static struct gssx_option_array zero_option_array = {}; 463 464 static int gssx_enc_name(struct xdr_stream *xdr, 465 struct gssx_name *name) 466 { 467 int err; 468 469 /* name->display_name */ 470 err = gssx_enc_buffer(xdr, &name->display_name); 471 if (err) 472 return err; 473 474 /* name->name_type */ 475 err = gssx_enc_buffer(xdr, &zero_netobj); 476 if (err) 477 return err; 478 479 /* name->exported_name */ 480 err = gssx_enc_buffer(xdr, &zero_netobj); 481 if (err) 482 return err; 483 484 /* name->exported_composite_name */ 485 err = gssx_enc_buffer(xdr, &zero_netobj); 486 if (err) 487 return err; 488 489 /* leave name_attributes empty for now, will add once we have any 490 * to pass up at all */ 491 /* name->name_attributes */ 492 err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array); 493 if (err) 494 return err; 495 496 /* leave options empty for now, will add once we have any options 497 * to pass up at all */ 498 /* name->extensions */ 499 err = dummy_enc_opt_array(xdr, &zero_option_array); 500 501 return err; 502 } 503 504 static int gssx_dec_name(struct xdr_stream *xdr, 505 struct gssx_name *name) 506 { 507 struct xdr_netobj dummy_netobj; 508 struct gssx_name_attr_array dummy_name_attr_array; 509 struct gssx_option_array dummy_option_array; 510 int err; 511 512 /* name->display_name */ 513 err = gssx_dec_buffer(xdr, &name->display_name); 514 if (err) 515 return err; 516 517 /* name->name_type */ 518 err = gssx_dec_buffer(xdr, &dummy_netobj); 519 if (err) 520 return err; 521 522 /* name->exported_name */ 523 err = gssx_dec_buffer(xdr, &dummy_netobj); 524 if (err) 525 return err; 526 527 /* name->exported_composite_name */ 528 err = gssx_dec_buffer(xdr, &dummy_netobj); 529 if (err) 530 return err; 531 532 /* we assume we have no attributes for now, so simply consume them */ 533 /* name->name_attributes */ 534 err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); 535 if (err) 536 return err; 537 538 /* we assume we have no options for now, so simply consume them */ 539 /* name->extensions */ 540 err = dummy_dec_opt_array(xdr, &dummy_option_array); 541 542 return err; 543 } 544 545 static int dummy_enc_credel_array(struct xdr_stream *xdr, 546 struct gssx_cred_element_array *cea) 547 { 548 __be32 *p; 549 550 if (cea->count != 0) 551 return -EINVAL; 552 553 p = xdr_reserve_space(xdr, 4); 554 if (!p) 555 return -ENOSPC; 556 *p = 0; 557 558 return 0; 559 } 560 561 static int gssx_enc_cred(struct xdr_stream *xdr, 562 struct gssx_cred *cred) 563 { 564 int err; 565 566 /* cred->desired_name */ 567 err = gssx_enc_name(xdr, &cred->desired_name); 568 if (err) 569 return err; 570 571 /* cred->elements */ 572 err = dummy_enc_credel_array(xdr, &cred->elements); 573 574 /* cred->cred_handle_reference */ 575 err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); 576 if (err) 577 return err; 578 579 /* cred->needs_release */ 580 err = gssx_enc_bool(xdr, cred->needs_release); 581 582 return err; 583 } 584 585 static int gssx_enc_ctx(struct xdr_stream *xdr, 586 struct gssx_ctx *ctx) 587 { 588 __be32 *p; 589 int err; 590 591 /* ctx->exported_context_token */ 592 err = gssx_enc_buffer(xdr, &ctx->exported_context_token); 593 if (err) 594 return err; 595 596 /* ctx->state */ 597 err = gssx_enc_buffer(xdr, &ctx->state); 598 if (err) 599 return err; 600 601 /* ctx->need_release */ 602 err = gssx_enc_bool(xdr, ctx->need_release); 603 if (err) 604 return err; 605 606 /* ctx->mech */ 607 err = gssx_enc_buffer(xdr, &ctx->mech); 608 if (err) 609 return err; 610 611 /* ctx->src_name */ 612 err = gssx_enc_name(xdr, &ctx->src_name); 613 if (err) 614 return err; 615 616 /* ctx->targ_name */ 617 err = gssx_enc_name(xdr, &ctx->targ_name); 618 if (err) 619 return err; 620 621 /* ctx->lifetime */ 622 p = xdr_reserve_space(xdr, 8+8); 623 if (!p) 624 return -ENOSPC; 625 p = xdr_encode_hyper(p, ctx->lifetime); 626 627 /* ctx->ctx_flags */ 628 p = xdr_encode_hyper(p, ctx->ctx_flags); 629 630 /* ctx->locally_initiated */ 631 err = gssx_enc_bool(xdr, ctx->locally_initiated); 632 if (err) 633 return err; 634 635 /* ctx->open */ 636 err = gssx_enc_bool(xdr, ctx->open); 637 if (err) 638 return err; 639 640 /* leave options empty for now, will add once we have any options 641 * to pass up at all */ 642 /* ctx->options */ 643 err = dummy_enc_opt_array(xdr, &ctx->options); 644 645 return err; 646 } 647 648 static int gssx_dec_ctx(struct xdr_stream *xdr, 649 struct gssx_ctx *ctx) 650 { 651 __be32 *p; 652 int err; 653 654 /* ctx->exported_context_token */ 655 err = gssx_dec_buffer(xdr, &ctx->exported_context_token); 656 if (err) 657 return err; 658 659 /* ctx->state */ 660 err = gssx_dec_buffer(xdr, &ctx->state); 661 if (err) 662 return err; 663 664 /* ctx->need_release */ 665 err = gssx_dec_bool(xdr, &ctx->need_release); 666 if (err) 667 return err; 668 669 /* ctx->mech */ 670 err = gssx_dec_buffer(xdr, &ctx->mech); 671 if (err) 672 return err; 673 674 /* ctx->src_name */ 675 err = gssx_dec_name(xdr, &ctx->src_name); 676 if (err) 677 return err; 678 679 /* ctx->targ_name */ 680 err = gssx_dec_name(xdr, &ctx->targ_name); 681 if (err) 682 return err; 683 684 /* ctx->lifetime */ 685 p = xdr_inline_decode(xdr, 8+8); 686 if (unlikely(p == NULL)) 687 return -ENOSPC; 688 p = xdr_decode_hyper(p, &ctx->lifetime); 689 690 /* ctx->ctx_flags */ 691 p = xdr_decode_hyper(p, &ctx->ctx_flags); 692 693 /* ctx->locally_initiated */ 694 err = gssx_dec_bool(xdr, &ctx->locally_initiated); 695 if (err) 696 return err; 697 698 /* ctx->open */ 699 err = gssx_dec_bool(xdr, &ctx->open); 700 if (err) 701 return err; 702 703 /* we assume we have no options for now, so simply consume them */ 704 /* ctx->options */ 705 err = dummy_dec_opt_array(xdr, &ctx->options); 706 707 return err; 708 } 709 710 static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb) 711 { 712 __be32 *p; 713 int err; 714 715 /* cb->initiator_addrtype */ 716 p = xdr_reserve_space(xdr, 8); 717 if (!p) 718 return -ENOSPC; 719 p = xdr_encode_hyper(p, cb->initiator_addrtype); 720 721 /* cb->initiator_address */ 722 err = gssx_enc_buffer(xdr, &cb->initiator_address); 723 if (err) 724 return err; 725 726 /* cb->acceptor_addrtype */ 727 p = xdr_reserve_space(xdr, 8); 728 if (!p) 729 return -ENOSPC; 730 p = xdr_encode_hyper(p, cb->acceptor_addrtype); 731 732 /* cb->acceptor_address */ 733 err = gssx_enc_buffer(xdr, &cb->acceptor_address); 734 if (err) 735 return err; 736 737 /* cb->application_data */ 738 err = gssx_enc_buffer(xdr, &cb->application_data); 739 740 return err; 741 } 742 743 void gssx_enc_accept_sec_context(struct rpc_rqst *req, 744 struct xdr_stream *xdr, 745 struct gssx_arg_accept_sec_context *arg) 746 { 747 int err; 748 749 err = gssx_enc_call_ctx(xdr, &arg->call_ctx); 750 if (err) 751 goto done; 752 753 /* arg->context_handle */ 754 if (arg->context_handle) { 755 err = gssx_enc_ctx(xdr, arg->context_handle); 756 if (err) 757 goto done; 758 } else { 759 err = gssx_enc_bool(xdr, 0); 760 } 761 762 /* arg->cred_handle */ 763 if (arg->cred_handle) { 764 err = gssx_enc_cred(xdr, arg->cred_handle); 765 if (err) 766 goto done; 767 } else { 768 err = gssx_enc_bool(xdr, 0); 769 } 770 771 /* arg->input_token */ 772 err = gssx_enc_in_token(xdr, &arg->input_token); 773 if (err) 774 goto done; 775 776 /* arg->input_cb */ 777 if (arg->input_cb) { 778 err = gssx_enc_cb(xdr, arg->input_cb); 779 if (err) 780 goto done; 781 } else { 782 err = gssx_enc_bool(xdr, 0); 783 } 784 785 err = gssx_enc_bool(xdr, arg->ret_deleg_cred); 786 if (err) 787 goto done; 788 789 /* leave options empty for now, will add once we have any options 790 * to pass up at all */ 791 /* arg->options */ 792 err = dummy_enc_opt_array(xdr, &arg->options); 793 794 done: 795 if (err) 796 dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); 797 } 798 799 int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, 800 struct xdr_stream *xdr, 801 struct gssx_res_accept_sec_context *res) 802 { 803 int err; 804 805 /* res->status */ 806 err = gssx_dec_status(xdr, &res->status); 807 if (err) 808 return err; 809 810 /* res->context_handle */ 811 if (gssx_check_pointer(xdr)) { 812 err = gssx_dec_ctx(xdr, res->context_handle); 813 if (err) 814 return err; 815 } else { 816 res->context_handle = NULL; 817 } 818 819 /* res->output_token */ 820 if (gssx_check_pointer(xdr)) { 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 if (gssx_check_pointer(xdr)) { 830 /* we do not support upcall servers sending this data. */ 831 return -EINVAL; 832 } 833 834 /* res->options */ 835 err = gssx_dec_option_array(xdr, &res->options); 836 837 return err; 838 } 839