root/net/sunrpc/auth_gss/gss_rpc_xdr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gssx_enc_bool
  2. gssx_dec_bool
  3. gssx_enc_buffer
  4. gssx_enc_in_token
  5. gssx_dec_buffer
  6. gssx_enc_option
  7. gssx_dec_option
  8. dummy_enc_opt_array
  9. dummy_dec_opt_array
  10. get_host_u32
  11. gssx_dec_linux_creds
  12. gssx_dec_option_array
  13. gssx_dec_status
  14. gssx_enc_call_ctx
  15. gssx_dec_name_attr
  16. dummy_enc_nameattr_array
  17. dummy_dec_nameattr_array
  18. gssx_enc_name
  19. gssx_dec_name
  20. dummy_enc_credel_array
  21. gssx_enc_cred
  22. gssx_enc_ctx
  23. gssx_dec_ctx
  24. gssx_enc_cb
  25. gssx_enc_accept_sec_context
  26. gssx_dec_accept_sec_context

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

/* [<][>][^][v][top][bottom][index][help] */