11d658336SSimo Sorce /* 21d658336SSimo Sorce * GSS Proxy upcall module 31d658336SSimo Sorce * 41d658336SSimo Sorce * Copyright (C) 2012 Simo Sorce <simo@redhat.com> 51d658336SSimo Sorce * 61d658336SSimo Sorce * This program is free software; you can redistribute it and/or modify 71d658336SSimo Sorce * it under the terms of the GNU General Public License as published by 81d658336SSimo Sorce * the Free Software Foundation; either version 2 of the License, or 91d658336SSimo Sorce * (at your option) any later version. 101d658336SSimo Sorce * 111d658336SSimo Sorce * This program is distributed in the hope that it will be useful, 121d658336SSimo Sorce * but WITHOUT ANY WARRANTY; without even the implied warranty of 131d658336SSimo Sorce * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141d658336SSimo Sorce * GNU General Public License for more details. 151d658336SSimo Sorce * 161d658336SSimo Sorce * You should have received a copy of the GNU General Public License 171d658336SSimo Sorce * along with this program; if not, write to the Free Software 181d658336SSimo Sorce * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 191d658336SSimo Sorce */ 201d658336SSimo Sorce 211d658336SSimo Sorce #include <linux/sunrpc/svcauth.h> 221d658336SSimo Sorce #include "gss_rpc_xdr.h" 231d658336SSimo Sorce 241d658336SSimo Sorce static int gssx_enc_bool(struct xdr_stream *xdr, int v) 251d658336SSimo Sorce { 261d658336SSimo Sorce __be32 *p; 271d658336SSimo Sorce 281d658336SSimo Sorce p = xdr_reserve_space(xdr, 4); 291d658336SSimo Sorce if (unlikely(p == NULL)) 301d658336SSimo Sorce return -ENOSPC; 311d658336SSimo Sorce *p = v ? xdr_one : xdr_zero; 321d658336SSimo Sorce return 0; 331d658336SSimo Sorce } 341d658336SSimo Sorce 351d658336SSimo Sorce static int gssx_dec_bool(struct xdr_stream *xdr, u32 *v) 361d658336SSimo Sorce { 371d658336SSimo Sorce __be32 *p; 381d658336SSimo Sorce 391d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 401d658336SSimo Sorce if (unlikely(p == NULL)) 411d658336SSimo Sorce return -ENOSPC; 421d658336SSimo Sorce *v = be32_to_cpu(*p); 431d658336SSimo Sorce return 0; 441d658336SSimo Sorce } 451d658336SSimo Sorce 461d658336SSimo Sorce static int gssx_enc_buffer(struct xdr_stream *xdr, 471d658336SSimo Sorce gssx_buffer *buf) 481d658336SSimo Sorce { 491d658336SSimo Sorce __be32 *p; 501d658336SSimo Sorce 511d658336SSimo Sorce p = xdr_reserve_space(xdr, sizeof(u32) + buf->len); 521d658336SSimo Sorce if (!p) 531d658336SSimo Sorce return -ENOSPC; 541d658336SSimo Sorce xdr_encode_opaque(p, buf->data, buf->len); 551d658336SSimo Sorce return 0; 561d658336SSimo Sorce } 571d658336SSimo Sorce 581d658336SSimo Sorce static int gssx_enc_in_token(struct xdr_stream *xdr, 591d658336SSimo Sorce struct gssp_in_token *in) 601d658336SSimo Sorce { 611d658336SSimo Sorce __be32 *p; 621d658336SSimo Sorce 631d658336SSimo Sorce p = xdr_reserve_space(xdr, 4); 641d658336SSimo Sorce if (!p) 651d658336SSimo Sorce return -ENOSPC; 661d658336SSimo Sorce *p = cpu_to_be32(in->page_len); 671d658336SSimo Sorce 681d658336SSimo Sorce /* all we need to do is to write pages */ 691d658336SSimo Sorce xdr_write_pages(xdr, in->pages, in->page_base, in->page_len); 701d658336SSimo Sorce 711d658336SSimo Sorce return 0; 721d658336SSimo Sorce } 731d658336SSimo Sorce 741d658336SSimo Sorce 751d658336SSimo Sorce static int gssx_dec_buffer(struct xdr_stream *xdr, 761d658336SSimo Sorce gssx_buffer *buf) 771d658336SSimo Sorce { 781d658336SSimo Sorce u32 length; 791d658336SSimo Sorce __be32 *p; 801d658336SSimo Sorce 811d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 821d658336SSimo Sorce if (unlikely(p == NULL)) 831d658336SSimo Sorce return -ENOSPC; 841d658336SSimo Sorce 851d658336SSimo Sorce length = be32_to_cpup(p); 861d658336SSimo Sorce p = xdr_inline_decode(xdr, length); 871d658336SSimo Sorce if (unlikely(p == NULL)) 881d658336SSimo Sorce return -ENOSPC; 891d658336SSimo Sorce 901d658336SSimo Sorce if (buf->len == 0) { 911d658336SSimo Sorce /* we intentionally are not interested in this buffer */ 921d658336SSimo Sorce return 0; 931d658336SSimo Sorce } 941d658336SSimo Sorce if (length > buf->len) 951d658336SSimo Sorce return -ENOSPC; 961d658336SSimo Sorce 971d658336SSimo Sorce if (!buf->data) { 981d658336SSimo Sorce buf->data = kmemdup(p, length, GFP_KERNEL); 991d658336SSimo Sorce if (!buf->data) 1001d658336SSimo Sorce return -ENOMEM; 1011d658336SSimo Sorce } else { 1021d658336SSimo Sorce memcpy(buf->data, p, length); 1031d658336SSimo Sorce } 1041d658336SSimo Sorce buf->len = length; 1051d658336SSimo Sorce return 0; 1061d658336SSimo Sorce } 1071d658336SSimo Sorce 1081d658336SSimo Sorce static int gssx_enc_option(struct xdr_stream *xdr, 1091d658336SSimo Sorce struct gssx_option *opt) 1101d658336SSimo Sorce { 1111d658336SSimo Sorce int err; 1121d658336SSimo Sorce 1131d658336SSimo Sorce err = gssx_enc_buffer(xdr, &opt->option); 1141d658336SSimo Sorce if (err) 1151d658336SSimo Sorce return err; 1161d658336SSimo Sorce err = gssx_enc_buffer(xdr, &opt->value); 1171d658336SSimo Sorce return err; 1181d658336SSimo Sorce } 1191d658336SSimo Sorce 1201d658336SSimo Sorce static int gssx_dec_option(struct xdr_stream *xdr, 1211d658336SSimo Sorce struct gssx_option *opt) 1221d658336SSimo Sorce { 1231d658336SSimo Sorce int err; 1241d658336SSimo Sorce 1251d658336SSimo Sorce err = gssx_dec_buffer(xdr, &opt->option); 1261d658336SSimo Sorce if (err) 1271d658336SSimo Sorce return err; 1281d658336SSimo Sorce err = gssx_dec_buffer(xdr, &opt->value); 1291d658336SSimo Sorce return err; 1301d658336SSimo Sorce } 1311d658336SSimo Sorce 1321d658336SSimo Sorce static int dummy_enc_opt_array(struct xdr_stream *xdr, 1331d658336SSimo Sorce struct gssx_option_array *oa) 1341d658336SSimo Sorce { 1351d658336SSimo Sorce __be32 *p; 1361d658336SSimo Sorce 1371d658336SSimo Sorce if (oa->count != 0) 1381d658336SSimo Sorce return -EINVAL; 1391d658336SSimo Sorce 1401d658336SSimo Sorce p = xdr_reserve_space(xdr, 4); 1411d658336SSimo Sorce if (!p) 1421d658336SSimo Sorce return -ENOSPC; 1431d658336SSimo Sorce *p = 0; 1441d658336SSimo Sorce 1451d658336SSimo Sorce return 0; 1461d658336SSimo Sorce } 1471d658336SSimo Sorce 1481d658336SSimo Sorce static int dummy_dec_opt_array(struct xdr_stream *xdr, 1491d658336SSimo Sorce struct gssx_option_array *oa) 1501d658336SSimo Sorce { 1511d658336SSimo Sorce struct gssx_option dummy; 1521d658336SSimo Sorce u32 count, i; 1531d658336SSimo Sorce __be32 *p; 1541d658336SSimo Sorce 1551d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 1561d658336SSimo Sorce if (unlikely(p == NULL)) 1571d658336SSimo Sorce return -ENOSPC; 1581d658336SSimo Sorce count = be32_to_cpup(p++); 1591d658336SSimo Sorce memset(&dummy, 0, sizeof(dummy)); 1601d658336SSimo Sorce for (i = 0; i < count; i++) { 1611d658336SSimo Sorce gssx_dec_option(xdr, &dummy); 1621d658336SSimo Sorce } 1631d658336SSimo Sorce 1641d658336SSimo Sorce oa->count = 0; 1651d658336SSimo Sorce oa->data = NULL; 1661d658336SSimo Sorce return 0; 1671d658336SSimo Sorce } 1681d658336SSimo Sorce 169778e512bSJ. Bruce Fields static int get_s32(struct xdr_stream *xdr, s32 *res) 1701d658336SSimo Sorce { 171778e512bSJ. Bruce Fields __be32 *p; 172778e512bSJ. Bruce Fields 173778e512bSJ. Bruce Fields p = xdr_inline_decode(xdr, 4); 174778e512bSJ. Bruce Fields if (!p) 1751d658336SSimo Sorce return -EINVAL; 176778e512bSJ. Bruce Fields memcpy(res, p, sizeof(s32)); 1771d658336SSimo Sorce return 0; 1781d658336SSimo Sorce } 1791d658336SSimo Sorce 1801d658336SSimo Sorce static int gssx_dec_linux_creds(struct xdr_stream *xdr, 1811d658336SSimo Sorce struct svc_cred *creds) 1821d658336SSimo Sorce { 1831d658336SSimo Sorce u32 length; 1841d658336SSimo Sorce __be32 *p; 1851d658336SSimo Sorce s32 tmp; 1861d658336SSimo Sorce int N, i, err; 1871d658336SSimo Sorce 1881d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 1891d658336SSimo Sorce if (unlikely(p == NULL)) 1901d658336SSimo Sorce return -ENOSPC; 1911d658336SSimo Sorce 1921d658336SSimo Sorce length = be32_to_cpup(p); 1931d658336SSimo Sorce 194778e512bSJ. Bruce Fields if (length > (3 + NGROUPS_MAX) * sizeof(u32)) 1951d658336SSimo Sorce return -ENOSPC; 1961d658336SSimo Sorce 1971d658336SSimo Sorce /* uid */ 198778e512bSJ. Bruce Fields err = get_s32(xdr, &tmp); 1991d658336SSimo Sorce if (err) 2001d658336SSimo Sorce return err; 201d28fcc83SJ. Bruce Fields creds->cr_uid = make_kuid(&init_user_ns, tmp); 2021d658336SSimo Sorce 2031d658336SSimo Sorce /* gid */ 204778e512bSJ. Bruce Fields err = get_s32(xdr, &tmp); 2051d658336SSimo Sorce if (err) 2061d658336SSimo Sorce return err; 207d28fcc83SJ. Bruce Fields creds->cr_gid = make_kgid(&init_user_ns, tmp); 2081d658336SSimo Sorce 2091d658336SSimo Sorce /* number of additional gid's */ 210778e512bSJ. Bruce Fields err = get_s32(xdr, &tmp); 2111d658336SSimo Sorce if (err) 2121d658336SSimo Sorce return err; 2131d658336SSimo Sorce N = tmp; 214778e512bSJ. Bruce Fields if ((3 + N) * sizeof(u32) != length) 215778e512bSJ. Bruce Fields return -EINVAL; 2161d658336SSimo Sorce creds->cr_group_info = groups_alloc(N); 2171d658336SSimo Sorce if (creds->cr_group_info == NULL) 2181d658336SSimo Sorce return -ENOMEM; 2191d658336SSimo Sorce 2201d658336SSimo Sorce /* gid's */ 2211d658336SSimo Sorce for (i = 0; i < N; i++) { 222d28fcc83SJ. Bruce Fields kgid_t kgid; 223778e512bSJ. Bruce Fields err = get_s32(xdr, &tmp); 224d28fcc83SJ. Bruce Fields if (err) 225d28fcc83SJ. Bruce Fields goto out_free_groups; 226d28fcc83SJ. Bruce Fields err = -EINVAL; 227d28fcc83SJ. Bruce Fields kgid = make_kgid(&init_user_ns, tmp); 228d28fcc83SJ. Bruce Fields if (!gid_valid(kgid)) 229d28fcc83SJ. Bruce Fields goto out_free_groups; 230d28fcc83SJ. Bruce Fields GROUP_AT(creds->cr_group_info, i) = kgid; 2311d658336SSimo Sorce } 2321d658336SSimo Sorce 2331d658336SSimo Sorce return 0; 234d28fcc83SJ. Bruce Fields out_free_groups: 235d28fcc83SJ. Bruce Fields groups_free(creds->cr_group_info); 236d28fcc83SJ. Bruce Fields return err; 2371d658336SSimo Sorce } 2381d658336SSimo Sorce 2391d658336SSimo Sorce static int gssx_dec_option_array(struct xdr_stream *xdr, 2401d658336SSimo Sorce struct gssx_option_array *oa) 2411d658336SSimo Sorce { 2421d658336SSimo Sorce struct svc_cred *creds; 2431d658336SSimo Sorce u32 count, i; 2441d658336SSimo Sorce __be32 *p; 2451d658336SSimo Sorce int err; 2461d658336SSimo Sorce 2471d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 2481d658336SSimo Sorce if (unlikely(p == NULL)) 2491d658336SSimo Sorce return -ENOSPC; 2501d658336SSimo Sorce count = be32_to_cpup(p++); 2519fd40c5aSGeert Uytterhoeven if (!count) 2529fd40c5aSGeert Uytterhoeven return 0; 2539fd40c5aSGeert Uytterhoeven 2541d658336SSimo Sorce /* we recognize only 1 currently: CREDS_VALUE */ 2551d658336SSimo Sorce oa->count = 1; 2561d658336SSimo Sorce 2571d658336SSimo Sorce oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); 2581d658336SSimo Sorce if (!oa->data) 2591d658336SSimo Sorce return -ENOMEM; 2601d658336SSimo Sorce 2611d658336SSimo Sorce creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); 2621d658336SSimo Sorce if (!creds) { 2631d658336SSimo Sorce kfree(oa->data); 2641d658336SSimo Sorce return -ENOMEM; 2651d658336SSimo Sorce } 2661d658336SSimo Sorce 2671d658336SSimo Sorce oa->data[0].option.data = CREDS_VALUE; 2681d658336SSimo Sorce oa->data[0].option.len = sizeof(CREDS_VALUE); 2691d658336SSimo Sorce oa->data[0].value.data = (void *)creds; 2701d658336SSimo Sorce oa->data[0].value.len = 0; 2719fd40c5aSGeert Uytterhoeven 2721d658336SSimo Sorce for (i = 0; i < count; i++) { 2731d658336SSimo Sorce gssx_buffer dummy = { 0, NULL }; 2741d658336SSimo Sorce u32 length; 2751d658336SSimo Sorce 2761d658336SSimo Sorce /* option buffer */ 2771d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 2781d658336SSimo Sorce if (unlikely(p == NULL)) 2791d658336SSimo Sorce return -ENOSPC; 2801d658336SSimo Sorce 2811d658336SSimo Sorce length = be32_to_cpup(p); 2821d658336SSimo Sorce p = xdr_inline_decode(xdr, length); 2831d658336SSimo Sorce if (unlikely(p == NULL)) 2841d658336SSimo Sorce return -ENOSPC; 2851d658336SSimo Sorce 2861d658336SSimo Sorce if (length == sizeof(CREDS_VALUE) && 2871d658336SSimo Sorce memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) { 2881d658336SSimo Sorce /* We have creds here. parse them */ 2891d658336SSimo Sorce err = gssx_dec_linux_creds(xdr, creds); 2901d658336SSimo Sorce if (err) 2911d658336SSimo Sorce return err; 2921d658336SSimo Sorce oa->data[0].value.len = 1; /* presence */ 2931d658336SSimo Sorce } else { 2941d658336SSimo Sorce /* consume uninteresting buffer */ 2951d658336SSimo Sorce err = gssx_dec_buffer(xdr, &dummy); 2961d658336SSimo Sorce if (err) 2971d658336SSimo Sorce return err; 2981d658336SSimo Sorce } 2991d658336SSimo Sorce } 3001d658336SSimo Sorce return 0; 3011d658336SSimo Sorce } 3021d658336SSimo Sorce 3031d658336SSimo Sorce static int gssx_dec_status(struct xdr_stream *xdr, 3041d658336SSimo Sorce struct gssx_status *status) 3051d658336SSimo Sorce { 3061d658336SSimo Sorce __be32 *p; 3071d658336SSimo Sorce int err; 3081d658336SSimo Sorce 3091d658336SSimo Sorce /* status->major_status */ 3101d658336SSimo Sorce p = xdr_inline_decode(xdr, 8); 3111d658336SSimo Sorce if (unlikely(p == NULL)) 3121d658336SSimo Sorce return -ENOSPC; 3131d658336SSimo Sorce p = xdr_decode_hyper(p, &status->major_status); 3141d658336SSimo Sorce 3151d658336SSimo Sorce /* status->mech */ 3161d658336SSimo Sorce err = gssx_dec_buffer(xdr, &status->mech); 3171d658336SSimo Sorce if (err) 3181d658336SSimo Sorce return err; 3191d658336SSimo Sorce 3201d658336SSimo Sorce /* status->minor_status */ 3211d658336SSimo Sorce p = xdr_inline_decode(xdr, 8); 3221d658336SSimo Sorce if (unlikely(p == NULL)) 3231d658336SSimo Sorce return -ENOSPC; 3241d658336SSimo Sorce p = xdr_decode_hyper(p, &status->minor_status); 3251d658336SSimo Sorce 3261d658336SSimo Sorce /* status->major_status_string */ 3271d658336SSimo Sorce err = gssx_dec_buffer(xdr, &status->major_status_string); 3281d658336SSimo Sorce if (err) 3291d658336SSimo Sorce return err; 3301d658336SSimo Sorce 3311d658336SSimo Sorce /* status->minor_status_string */ 3321d658336SSimo Sorce err = gssx_dec_buffer(xdr, &status->minor_status_string); 3331d658336SSimo Sorce if (err) 3341d658336SSimo Sorce return err; 3351d658336SSimo Sorce 3361d658336SSimo Sorce /* status->server_ctx */ 3371d658336SSimo Sorce err = gssx_dec_buffer(xdr, &status->server_ctx); 3381d658336SSimo Sorce if (err) 3391d658336SSimo Sorce return err; 3401d658336SSimo Sorce 3411d658336SSimo Sorce /* we assume we have no options for now, so simply consume them */ 3421d658336SSimo Sorce /* status->options */ 3431d658336SSimo Sorce err = dummy_dec_opt_array(xdr, &status->options); 3441d658336SSimo Sorce 3451d658336SSimo Sorce return err; 3461d658336SSimo Sorce } 3471d658336SSimo Sorce 3481d658336SSimo Sorce static int gssx_enc_call_ctx(struct xdr_stream *xdr, 3491d658336SSimo Sorce struct gssx_call_ctx *ctx) 3501d658336SSimo Sorce { 3511d658336SSimo Sorce struct gssx_option opt; 3521d658336SSimo Sorce __be32 *p; 3531d658336SSimo Sorce int err; 3541d658336SSimo Sorce 3551d658336SSimo Sorce /* ctx->locale */ 3561d658336SSimo Sorce err = gssx_enc_buffer(xdr, &ctx->locale); 3571d658336SSimo Sorce if (err) 3581d658336SSimo Sorce return err; 3591d658336SSimo Sorce 3601d658336SSimo Sorce /* ctx->server_ctx */ 3611d658336SSimo Sorce err = gssx_enc_buffer(xdr, &ctx->server_ctx); 3621d658336SSimo Sorce if (err) 3631d658336SSimo Sorce return err; 3641d658336SSimo Sorce 3651d658336SSimo Sorce /* we always want to ask for lucid contexts */ 3661d658336SSimo Sorce /* ctx->options */ 3671d658336SSimo Sorce p = xdr_reserve_space(xdr, 4); 3681d658336SSimo Sorce *p = cpu_to_be32(2); 3691d658336SSimo Sorce 3701d658336SSimo Sorce /* we want a lucid_v1 context */ 3711d658336SSimo Sorce opt.option.data = LUCID_OPTION; 3721d658336SSimo Sorce opt.option.len = sizeof(LUCID_OPTION); 3731d658336SSimo Sorce opt.value.data = LUCID_VALUE; 3741d658336SSimo Sorce opt.value.len = sizeof(LUCID_VALUE); 3751d658336SSimo Sorce err = gssx_enc_option(xdr, &opt); 3761d658336SSimo Sorce 3771d658336SSimo Sorce /* ..and user creds */ 3781d658336SSimo Sorce opt.option.data = CREDS_OPTION; 3791d658336SSimo Sorce opt.option.len = sizeof(CREDS_OPTION); 3801d658336SSimo Sorce opt.value.data = CREDS_VALUE; 3811d658336SSimo Sorce opt.value.len = sizeof(CREDS_VALUE); 3821d658336SSimo Sorce err = gssx_enc_option(xdr, &opt); 3831d658336SSimo Sorce 3841d658336SSimo Sorce return err; 3851d658336SSimo Sorce } 3861d658336SSimo Sorce 3871d658336SSimo Sorce static int gssx_dec_name_attr(struct xdr_stream *xdr, 3881d658336SSimo Sorce struct gssx_name_attr *attr) 3891d658336SSimo Sorce { 3901d658336SSimo Sorce int err; 3911d658336SSimo Sorce 3921d658336SSimo Sorce /* attr->attr */ 3931d658336SSimo Sorce err = gssx_dec_buffer(xdr, &attr->attr); 3941d658336SSimo Sorce if (err) 3951d658336SSimo Sorce return err; 3961d658336SSimo Sorce 3971d658336SSimo Sorce /* attr->value */ 3981d658336SSimo Sorce err = gssx_dec_buffer(xdr, &attr->value); 3991d658336SSimo Sorce if (err) 4001d658336SSimo Sorce return err; 4011d658336SSimo Sorce 4021d658336SSimo Sorce /* attr->extensions */ 4031d658336SSimo Sorce err = dummy_dec_opt_array(xdr, &attr->extensions); 4041d658336SSimo Sorce 4051d658336SSimo Sorce return err; 4061d658336SSimo Sorce } 4071d658336SSimo Sorce 4081d658336SSimo Sorce static int dummy_enc_nameattr_array(struct xdr_stream *xdr, 4091d658336SSimo Sorce struct gssx_name_attr_array *naa) 4101d658336SSimo Sorce { 4111d658336SSimo Sorce __be32 *p; 4121d658336SSimo Sorce 4131d658336SSimo Sorce if (naa->count != 0) 4141d658336SSimo Sorce return -EINVAL; 4151d658336SSimo Sorce 4161d658336SSimo Sorce p = xdr_reserve_space(xdr, 4); 4171d658336SSimo Sorce if (!p) 4181d658336SSimo Sorce return -ENOSPC; 4191d658336SSimo Sorce *p = 0; 4201d658336SSimo Sorce 4211d658336SSimo Sorce return 0; 4221d658336SSimo Sorce } 4231d658336SSimo Sorce 4241d658336SSimo Sorce static int dummy_dec_nameattr_array(struct xdr_stream *xdr, 4251d658336SSimo Sorce struct gssx_name_attr_array *naa) 4261d658336SSimo Sorce { 427dc43376cSJ. Bruce Fields struct gssx_name_attr dummy = { .attr = {.len = 0} }; 4281d658336SSimo Sorce u32 count, i; 4291d658336SSimo Sorce __be32 *p; 4301d658336SSimo Sorce 4311d658336SSimo Sorce p = xdr_inline_decode(xdr, 4); 4321d658336SSimo Sorce if (unlikely(p == NULL)) 4331d658336SSimo Sorce return -ENOSPC; 4341d658336SSimo Sorce count = be32_to_cpup(p++); 4351d658336SSimo Sorce for (i = 0; i < count; i++) { 4361d658336SSimo Sorce gssx_dec_name_attr(xdr, &dummy); 4371d658336SSimo Sorce } 4381d658336SSimo Sorce 4391d658336SSimo Sorce naa->count = 0; 4401d658336SSimo Sorce naa->data = NULL; 4411d658336SSimo Sorce return 0; 4421d658336SSimo Sorce } 4431d658336SSimo Sorce 4441d658336SSimo Sorce static struct xdr_netobj zero_netobj = {}; 4451d658336SSimo Sorce 4461d658336SSimo Sorce static struct gssx_name_attr_array zero_name_attr_array = {}; 4471d658336SSimo Sorce 4481d658336SSimo Sorce static struct gssx_option_array zero_option_array = {}; 4491d658336SSimo Sorce 4501d658336SSimo Sorce static int gssx_enc_name(struct xdr_stream *xdr, 4511d658336SSimo Sorce struct gssx_name *name) 4521d658336SSimo Sorce { 4531d658336SSimo Sorce int err; 4541d658336SSimo Sorce 4551d658336SSimo Sorce /* name->display_name */ 4561d658336SSimo Sorce err = gssx_enc_buffer(xdr, &name->display_name); 4571d658336SSimo Sorce if (err) 4581d658336SSimo Sorce return err; 4591d658336SSimo Sorce 4601d658336SSimo Sorce /* name->name_type */ 4611d658336SSimo Sorce err = gssx_enc_buffer(xdr, &zero_netobj); 4621d658336SSimo Sorce if (err) 4631d658336SSimo Sorce return err; 4641d658336SSimo Sorce 4651d658336SSimo Sorce /* name->exported_name */ 4661d658336SSimo Sorce err = gssx_enc_buffer(xdr, &zero_netobj); 4671d658336SSimo Sorce if (err) 4681d658336SSimo Sorce return err; 4691d658336SSimo Sorce 4701d658336SSimo Sorce /* name->exported_composite_name */ 4711d658336SSimo Sorce err = gssx_enc_buffer(xdr, &zero_netobj); 4721d658336SSimo Sorce if (err) 4731d658336SSimo Sorce return err; 4741d658336SSimo Sorce 4751d658336SSimo Sorce /* leave name_attributes empty for now, will add once we have any 4761d658336SSimo Sorce * to pass up at all */ 4771d658336SSimo Sorce /* name->name_attributes */ 4781d658336SSimo Sorce err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array); 4791d658336SSimo Sorce if (err) 4801d658336SSimo Sorce return err; 4811d658336SSimo Sorce 4821d658336SSimo Sorce /* leave options empty for now, will add once we have any options 4831d658336SSimo Sorce * to pass up at all */ 4841d658336SSimo Sorce /* name->extensions */ 4851d658336SSimo Sorce err = dummy_enc_opt_array(xdr, &zero_option_array); 4861d658336SSimo Sorce 4871d658336SSimo Sorce return err; 4881d658336SSimo Sorce } 4891d658336SSimo Sorce 490dc43376cSJ. Bruce Fields 4911d658336SSimo Sorce static int gssx_dec_name(struct xdr_stream *xdr, 4921d658336SSimo Sorce struct gssx_name *name) 4931d658336SSimo Sorce { 494dc43376cSJ. Bruce Fields struct xdr_netobj dummy_netobj = { .len = 0 }; 495dc43376cSJ. Bruce Fields struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 }; 496dc43376cSJ. Bruce Fields struct gssx_option_array dummy_option_array = { .count = 0 }; 4971d658336SSimo Sorce int err; 4981d658336SSimo Sorce 4991d658336SSimo Sorce /* name->display_name */ 5001d658336SSimo Sorce err = gssx_dec_buffer(xdr, &name->display_name); 5011d658336SSimo Sorce if (err) 5021d658336SSimo Sorce return err; 5031d658336SSimo Sorce 5041d658336SSimo Sorce /* name->name_type */ 5051d658336SSimo Sorce err = gssx_dec_buffer(xdr, &dummy_netobj); 5061d658336SSimo Sorce if (err) 5071d658336SSimo Sorce return err; 5081d658336SSimo Sorce 5091d658336SSimo Sorce /* name->exported_name */ 5101d658336SSimo Sorce err = gssx_dec_buffer(xdr, &dummy_netobj); 5111d658336SSimo Sorce if (err) 5121d658336SSimo Sorce return err; 5131d658336SSimo Sorce 5141d658336SSimo Sorce /* name->exported_composite_name */ 5151d658336SSimo Sorce err = gssx_dec_buffer(xdr, &dummy_netobj); 5161d658336SSimo Sorce if (err) 5171d658336SSimo Sorce return err; 5181d658336SSimo Sorce 5191d658336SSimo Sorce /* we assume we have no attributes for now, so simply consume them */ 5201d658336SSimo Sorce /* name->name_attributes */ 5211d658336SSimo Sorce err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); 5221d658336SSimo Sorce if (err) 5231d658336SSimo Sorce return err; 5241d658336SSimo Sorce 5251d658336SSimo Sorce /* we assume we have no options for now, so simply consume them */ 5261d658336SSimo Sorce /* name->extensions */ 5271d658336SSimo Sorce err = dummy_dec_opt_array(xdr, &dummy_option_array); 5281d658336SSimo Sorce 5291d658336SSimo Sorce return err; 5301d658336SSimo Sorce } 5311d658336SSimo Sorce 5321d658336SSimo Sorce static int dummy_enc_credel_array(struct xdr_stream *xdr, 5331d658336SSimo Sorce struct gssx_cred_element_array *cea) 5341d658336SSimo Sorce { 5351d658336SSimo Sorce __be32 *p; 5361d658336SSimo Sorce 5371d658336SSimo Sorce if (cea->count != 0) 5381d658336SSimo Sorce return -EINVAL; 5391d658336SSimo Sorce 5401d658336SSimo Sorce p = xdr_reserve_space(xdr, 4); 5411d658336SSimo Sorce if (!p) 5421d658336SSimo Sorce return -ENOSPC; 5431d658336SSimo Sorce *p = 0; 5441d658336SSimo Sorce 5451d658336SSimo Sorce return 0; 5461d658336SSimo Sorce } 5471d658336SSimo Sorce 5481d658336SSimo Sorce static int gssx_enc_cred(struct xdr_stream *xdr, 5491d658336SSimo Sorce struct gssx_cred *cred) 5501d658336SSimo Sorce { 5511d658336SSimo Sorce int err; 5521d658336SSimo Sorce 5531d658336SSimo Sorce /* cred->desired_name */ 5541d658336SSimo Sorce err = gssx_enc_name(xdr, &cred->desired_name); 5551d658336SSimo Sorce if (err) 5561d658336SSimo Sorce return err; 5571d658336SSimo Sorce 5581d658336SSimo Sorce /* cred->elements */ 5591d658336SSimo Sorce err = dummy_enc_credel_array(xdr, &cred->elements); 5601d658336SSimo Sorce 5611d658336SSimo Sorce /* cred->cred_handle_reference */ 5621d658336SSimo Sorce err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); 5631d658336SSimo Sorce if (err) 5641d658336SSimo Sorce return err; 5651d658336SSimo Sorce 5661d658336SSimo Sorce /* cred->needs_release */ 5671d658336SSimo Sorce err = gssx_enc_bool(xdr, cred->needs_release); 5681d658336SSimo Sorce 5691d658336SSimo Sorce return err; 5701d658336SSimo Sorce } 5711d658336SSimo Sorce 5721d658336SSimo Sorce static int gssx_enc_ctx(struct xdr_stream *xdr, 5731d658336SSimo Sorce struct gssx_ctx *ctx) 5741d658336SSimo Sorce { 5751d658336SSimo Sorce __be32 *p; 5761d658336SSimo Sorce int err; 5771d658336SSimo Sorce 5781d658336SSimo Sorce /* ctx->exported_context_token */ 5791d658336SSimo Sorce err = gssx_enc_buffer(xdr, &ctx->exported_context_token); 5801d658336SSimo Sorce if (err) 5811d658336SSimo Sorce return err; 5821d658336SSimo Sorce 5831d658336SSimo Sorce /* ctx->state */ 5841d658336SSimo Sorce err = gssx_enc_buffer(xdr, &ctx->state); 5851d658336SSimo Sorce if (err) 5861d658336SSimo Sorce return err; 5871d658336SSimo Sorce 5881d658336SSimo Sorce /* ctx->need_release */ 5891d658336SSimo Sorce err = gssx_enc_bool(xdr, ctx->need_release); 5901d658336SSimo Sorce if (err) 5911d658336SSimo Sorce return err; 5921d658336SSimo Sorce 5931d658336SSimo Sorce /* ctx->mech */ 5941d658336SSimo Sorce err = gssx_enc_buffer(xdr, &ctx->mech); 5951d658336SSimo Sorce if (err) 5961d658336SSimo Sorce return err; 5971d658336SSimo Sorce 5981d658336SSimo Sorce /* ctx->src_name */ 5991d658336SSimo Sorce err = gssx_enc_name(xdr, &ctx->src_name); 6001d658336SSimo Sorce if (err) 6011d658336SSimo Sorce return err; 6021d658336SSimo Sorce 6031d658336SSimo Sorce /* ctx->targ_name */ 6041d658336SSimo Sorce err = gssx_enc_name(xdr, &ctx->targ_name); 6051d658336SSimo Sorce if (err) 6061d658336SSimo Sorce return err; 6071d658336SSimo Sorce 6081d658336SSimo Sorce /* ctx->lifetime */ 6091d658336SSimo Sorce p = xdr_reserve_space(xdr, 8+8); 6101d658336SSimo Sorce if (!p) 6111d658336SSimo Sorce return -ENOSPC; 6121d658336SSimo Sorce p = xdr_encode_hyper(p, ctx->lifetime); 6131d658336SSimo Sorce 6141d658336SSimo Sorce /* ctx->ctx_flags */ 6151d658336SSimo Sorce p = xdr_encode_hyper(p, ctx->ctx_flags); 6161d658336SSimo Sorce 6171d658336SSimo Sorce /* ctx->locally_initiated */ 6181d658336SSimo Sorce err = gssx_enc_bool(xdr, ctx->locally_initiated); 6191d658336SSimo Sorce if (err) 6201d658336SSimo Sorce return err; 6211d658336SSimo Sorce 6221d658336SSimo Sorce /* ctx->open */ 6231d658336SSimo Sorce err = gssx_enc_bool(xdr, ctx->open); 6241d658336SSimo Sorce if (err) 6251d658336SSimo Sorce return err; 6261d658336SSimo Sorce 6271d658336SSimo Sorce /* leave options empty for now, will add once we have any options 6281d658336SSimo Sorce * to pass up at all */ 6291d658336SSimo Sorce /* ctx->options */ 6301d658336SSimo Sorce err = dummy_enc_opt_array(xdr, &ctx->options); 6311d658336SSimo Sorce 6321d658336SSimo Sorce return err; 6331d658336SSimo Sorce } 6341d658336SSimo Sorce 6351d658336SSimo Sorce static int gssx_dec_ctx(struct xdr_stream *xdr, 6361d658336SSimo Sorce struct gssx_ctx *ctx) 6371d658336SSimo Sorce { 6381d658336SSimo Sorce __be32 *p; 6391d658336SSimo Sorce int err; 6401d658336SSimo Sorce 6411d658336SSimo Sorce /* ctx->exported_context_token */ 6421d658336SSimo Sorce err = gssx_dec_buffer(xdr, &ctx->exported_context_token); 6431d658336SSimo Sorce if (err) 6441d658336SSimo Sorce return err; 6451d658336SSimo Sorce 6461d658336SSimo Sorce /* ctx->state */ 6471d658336SSimo Sorce err = gssx_dec_buffer(xdr, &ctx->state); 6481d658336SSimo Sorce if (err) 6491d658336SSimo Sorce return err; 6501d658336SSimo Sorce 6511d658336SSimo Sorce /* ctx->need_release */ 6521d658336SSimo Sorce err = gssx_dec_bool(xdr, &ctx->need_release); 6531d658336SSimo Sorce if (err) 6541d658336SSimo Sorce return err; 6551d658336SSimo Sorce 6561d658336SSimo Sorce /* ctx->mech */ 6571d658336SSimo Sorce err = gssx_dec_buffer(xdr, &ctx->mech); 6581d658336SSimo Sorce if (err) 6591d658336SSimo Sorce return err; 6601d658336SSimo Sorce 6611d658336SSimo Sorce /* ctx->src_name */ 6621d658336SSimo Sorce err = gssx_dec_name(xdr, &ctx->src_name); 6631d658336SSimo Sorce if (err) 6641d658336SSimo Sorce return err; 6651d658336SSimo Sorce 6661d658336SSimo Sorce /* ctx->targ_name */ 6671d658336SSimo Sorce err = gssx_dec_name(xdr, &ctx->targ_name); 6681d658336SSimo Sorce if (err) 6691d658336SSimo Sorce return err; 6701d658336SSimo Sorce 6711d658336SSimo Sorce /* ctx->lifetime */ 6721d658336SSimo Sorce p = xdr_inline_decode(xdr, 8+8); 6731d658336SSimo Sorce if (unlikely(p == NULL)) 6741d658336SSimo Sorce return -ENOSPC; 6751d658336SSimo Sorce p = xdr_decode_hyper(p, &ctx->lifetime); 6761d658336SSimo Sorce 6771d658336SSimo Sorce /* ctx->ctx_flags */ 6781d658336SSimo Sorce p = xdr_decode_hyper(p, &ctx->ctx_flags); 6791d658336SSimo Sorce 6801d658336SSimo Sorce /* ctx->locally_initiated */ 6811d658336SSimo Sorce err = gssx_dec_bool(xdr, &ctx->locally_initiated); 6821d658336SSimo Sorce if (err) 6831d658336SSimo Sorce return err; 6841d658336SSimo Sorce 6851d658336SSimo Sorce /* ctx->open */ 6861d658336SSimo Sorce err = gssx_dec_bool(xdr, &ctx->open); 6871d658336SSimo Sorce if (err) 6881d658336SSimo Sorce return err; 6891d658336SSimo Sorce 6901d658336SSimo Sorce /* we assume we have no options for now, so simply consume them */ 6911d658336SSimo Sorce /* ctx->options */ 6921d658336SSimo Sorce err = dummy_dec_opt_array(xdr, &ctx->options); 6931d658336SSimo Sorce 6941d658336SSimo Sorce return err; 6951d658336SSimo Sorce } 6961d658336SSimo Sorce 6971d658336SSimo Sorce static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb) 6981d658336SSimo Sorce { 6991d658336SSimo Sorce __be32 *p; 7001d658336SSimo Sorce int err; 7011d658336SSimo Sorce 7021d658336SSimo Sorce /* cb->initiator_addrtype */ 7031d658336SSimo Sorce p = xdr_reserve_space(xdr, 8); 7041d658336SSimo Sorce if (!p) 7051d658336SSimo Sorce return -ENOSPC; 7061d658336SSimo Sorce p = xdr_encode_hyper(p, cb->initiator_addrtype); 7071d658336SSimo Sorce 7081d658336SSimo Sorce /* cb->initiator_address */ 7091d658336SSimo Sorce err = gssx_enc_buffer(xdr, &cb->initiator_address); 7101d658336SSimo Sorce if (err) 7111d658336SSimo Sorce return err; 7121d658336SSimo Sorce 7131d658336SSimo Sorce /* cb->acceptor_addrtype */ 7141d658336SSimo Sorce p = xdr_reserve_space(xdr, 8); 7151d658336SSimo Sorce if (!p) 7161d658336SSimo Sorce return -ENOSPC; 7171d658336SSimo Sorce p = xdr_encode_hyper(p, cb->acceptor_addrtype); 7181d658336SSimo Sorce 7191d658336SSimo Sorce /* cb->acceptor_address */ 7201d658336SSimo Sorce err = gssx_enc_buffer(xdr, &cb->acceptor_address); 7211d658336SSimo Sorce if (err) 7221d658336SSimo Sorce return err; 7231d658336SSimo Sorce 7241d658336SSimo Sorce /* cb->application_data */ 7251d658336SSimo Sorce err = gssx_enc_buffer(xdr, &cb->application_data); 7261d658336SSimo Sorce 7271d658336SSimo Sorce return err; 7281d658336SSimo Sorce } 7291d658336SSimo Sorce 7301d658336SSimo Sorce void gssx_enc_accept_sec_context(struct rpc_rqst *req, 7311d658336SSimo Sorce struct xdr_stream *xdr, 7321d658336SSimo Sorce struct gssx_arg_accept_sec_context *arg) 7331d658336SSimo Sorce { 7341d658336SSimo Sorce int err; 7351d658336SSimo Sorce 7361d658336SSimo Sorce err = gssx_enc_call_ctx(xdr, &arg->call_ctx); 7371d658336SSimo Sorce if (err) 7381d658336SSimo Sorce goto done; 7391d658336SSimo Sorce 7401d658336SSimo Sorce /* arg->context_handle */ 7411d658336SSimo Sorce if (arg->context_handle) { 7421d658336SSimo Sorce err = gssx_enc_ctx(xdr, arg->context_handle); 7431d658336SSimo Sorce if (err) 7441d658336SSimo Sorce goto done; 7451d658336SSimo Sorce } else { 7461d658336SSimo Sorce err = gssx_enc_bool(xdr, 0); 7471d658336SSimo Sorce } 7481d658336SSimo Sorce 7491d658336SSimo Sorce /* arg->cred_handle */ 7501d658336SSimo Sorce if (arg->cred_handle) { 7511d658336SSimo Sorce err = gssx_enc_cred(xdr, arg->cred_handle); 7521d658336SSimo Sorce if (err) 7531d658336SSimo Sorce goto done; 7541d658336SSimo Sorce } else { 7551d658336SSimo Sorce err = gssx_enc_bool(xdr, 0); 7561d658336SSimo Sorce } 7571d658336SSimo Sorce 7581d658336SSimo Sorce /* arg->input_token */ 7591d658336SSimo Sorce err = gssx_enc_in_token(xdr, &arg->input_token); 7601d658336SSimo Sorce if (err) 7611d658336SSimo Sorce goto done; 7621d658336SSimo Sorce 7631d658336SSimo Sorce /* arg->input_cb */ 7641d658336SSimo Sorce if (arg->input_cb) { 7651d658336SSimo Sorce err = gssx_enc_cb(xdr, arg->input_cb); 7661d658336SSimo Sorce if (err) 7671d658336SSimo Sorce goto done; 7681d658336SSimo Sorce } else { 7691d658336SSimo Sorce err = gssx_enc_bool(xdr, 0); 7701d658336SSimo Sorce } 7711d658336SSimo Sorce 7721d658336SSimo Sorce err = gssx_enc_bool(xdr, arg->ret_deleg_cred); 7731d658336SSimo Sorce if (err) 7741d658336SSimo Sorce goto done; 7751d658336SSimo Sorce 7761d658336SSimo Sorce /* leave options empty for now, will add once we have any options 7771d658336SSimo Sorce * to pass up at all */ 7781d658336SSimo Sorce /* arg->options */ 7791d658336SSimo Sorce err = dummy_enc_opt_array(xdr, &arg->options); 7801d658336SSimo Sorce 7811d658336SSimo Sorce done: 7821d658336SSimo Sorce if (err) 7831d658336SSimo Sorce dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); 7841d658336SSimo Sorce } 7851d658336SSimo Sorce 7861d658336SSimo Sorce int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, 7871d658336SSimo Sorce struct xdr_stream *xdr, 7881d658336SSimo Sorce struct gssx_res_accept_sec_context *res) 7891d658336SSimo Sorce { 790fb43f11cSJ. Bruce Fields u32 value_follows; 7911d658336SSimo Sorce int err; 7921d658336SSimo Sorce 7931d658336SSimo Sorce /* res->status */ 7941d658336SSimo Sorce err = gssx_dec_status(xdr, &res->status); 7951d658336SSimo Sorce if (err) 7961d658336SSimo Sorce return err; 7971d658336SSimo Sorce 7981d658336SSimo Sorce /* res->context_handle */ 799fb43f11cSJ. Bruce Fields err = gssx_dec_bool(xdr, &value_follows); 800fb43f11cSJ. Bruce Fields if (err) 801fb43f11cSJ. Bruce Fields return err; 802fb43f11cSJ. Bruce Fields if (value_follows) { 8031d658336SSimo Sorce err = gssx_dec_ctx(xdr, res->context_handle); 8041d658336SSimo Sorce if (err) 8051d658336SSimo Sorce return err; 8061d658336SSimo Sorce } else { 8071d658336SSimo Sorce res->context_handle = NULL; 8081d658336SSimo Sorce } 8091d658336SSimo Sorce 8101d658336SSimo Sorce /* res->output_token */ 811fb43f11cSJ. Bruce Fields err = gssx_dec_bool(xdr, &value_follows); 812fb43f11cSJ. Bruce Fields if (err) 813fb43f11cSJ. Bruce Fields return err; 814fb43f11cSJ. Bruce Fields if (value_follows) { 8151d658336SSimo Sorce err = gssx_dec_buffer(xdr, res->output_token); 8161d658336SSimo Sorce if (err) 8171d658336SSimo Sorce return err; 8181d658336SSimo Sorce } else { 8191d658336SSimo Sorce res->output_token = NULL; 8201d658336SSimo Sorce } 8211d658336SSimo Sorce 8221d658336SSimo Sorce /* res->delegated_cred_handle */ 823fb43f11cSJ. Bruce Fields err = gssx_dec_bool(xdr, &value_follows); 824fb43f11cSJ. Bruce Fields if (err) 825fb43f11cSJ. Bruce Fields return err; 826fb43f11cSJ. Bruce Fields if (value_follows) { 8271d658336SSimo Sorce /* we do not support upcall servers sending this data. */ 8281d658336SSimo Sorce return -EINVAL; 8291d658336SSimo Sorce } 8301d658336SSimo Sorce 8311d658336SSimo Sorce /* res->options */ 8321d658336SSimo Sorce err = gssx_dec_option_array(xdr, &res->options); 8331d658336SSimo Sorce 8341d658336SSimo Sorce return err; 8351d658336SSimo Sorce } 836