18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * GSS Proxy upcall module 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Simo Sorce <simo@redhat.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/sunrpc/svcauth.h> 98c2ecf20Sopenharmony_ci#include "gss_rpc_xdr.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic int gssx_enc_bool(struct xdr_stream *xdr, int v) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci __be32 *p; 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 168c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 178c2ecf20Sopenharmony_ci return -ENOSPC; 188c2ecf20Sopenharmony_ci *p = v ? xdr_one : xdr_zero; 198c2ecf20Sopenharmony_ci return 0; 208c2ecf20Sopenharmony_ci} 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic int gssx_dec_bool(struct xdr_stream *xdr, u32 *v) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci __be32 *p; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 278c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 288c2ecf20Sopenharmony_ci return -ENOSPC; 298c2ecf20Sopenharmony_ci *v = be32_to_cpu(*p); 308c2ecf20Sopenharmony_ci return 0; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int gssx_enc_buffer(struct xdr_stream *xdr, 348c2ecf20Sopenharmony_ci const gssx_buffer *buf) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci __be32 *p; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, sizeof(u32) + buf->len); 398c2ecf20Sopenharmony_ci if (!p) 408c2ecf20Sopenharmony_ci return -ENOSPC; 418c2ecf20Sopenharmony_ci xdr_encode_opaque(p, buf->data, buf->len); 428c2ecf20Sopenharmony_ci return 0; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int gssx_enc_in_token(struct xdr_stream *xdr, 468c2ecf20Sopenharmony_ci const struct gssp_in_token *in) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci __be32 *p; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 518c2ecf20Sopenharmony_ci if (!p) 528c2ecf20Sopenharmony_ci return -ENOSPC; 538c2ecf20Sopenharmony_ci *p = cpu_to_be32(in->page_len); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* all we need to do is to write pages */ 568c2ecf20Sopenharmony_ci xdr_write_pages(xdr, in->pages, in->page_base, in->page_len); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic int gssx_dec_buffer(struct xdr_stream *xdr, 638c2ecf20Sopenharmony_ci gssx_buffer *buf) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci u32 length; 668c2ecf20Sopenharmony_ci __be32 *p; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 698c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 708c2ecf20Sopenharmony_ci return -ENOSPC; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci length = be32_to_cpup(p); 738c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, length); 748c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 758c2ecf20Sopenharmony_ci return -ENOSPC; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (buf->len == 0) { 788c2ecf20Sopenharmony_ci /* we intentionally are not interested in this buffer */ 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci if (length > buf->len) 828c2ecf20Sopenharmony_ci return -ENOSPC; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (!buf->data) { 858c2ecf20Sopenharmony_ci buf->data = kmemdup(p, length, GFP_KERNEL); 868c2ecf20Sopenharmony_ci if (!buf->data) 878c2ecf20Sopenharmony_ci return -ENOMEM; 888c2ecf20Sopenharmony_ci } else { 898c2ecf20Sopenharmony_ci memcpy(buf->data, p, length); 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci buf->len = length; 928c2ecf20Sopenharmony_ci return 0; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int gssx_enc_option(struct xdr_stream *xdr, 968c2ecf20Sopenharmony_ci struct gssx_option *opt) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci int err; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &opt->option); 1018c2ecf20Sopenharmony_ci if (err) 1028c2ecf20Sopenharmony_ci return err; 1038c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &opt->value); 1048c2ecf20Sopenharmony_ci return err; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic int gssx_dec_option(struct xdr_stream *xdr, 1088c2ecf20Sopenharmony_ci struct gssx_option *opt) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci int err; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &opt->option); 1138c2ecf20Sopenharmony_ci if (err) 1148c2ecf20Sopenharmony_ci return err; 1158c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &opt->value); 1168c2ecf20Sopenharmony_ci return err; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int dummy_enc_opt_array(struct xdr_stream *xdr, 1208c2ecf20Sopenharmony_ci const struct gssx_option_array *oa) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci __be32 *p; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (oa->count != 0) 1258c2ecf20Sopenharmony_ci return -EINVAL; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 1288c2ecf20Sopenharmony_ci if (!p) 1298c2ecf20Sopenharmony_ci return -ENOSPC; 1308c2ecf20Sopenharmony_ci *p = 0; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic int dummy_dec_opt_array(struct xdr_stream *xdr, 1368c2ecf20Sopenharmony_ci struct gssx_option_array *oa) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci struct gssx_option dummy; 1398c2ecf20Sopenharmony_ci u32 count, i; 1408c2ecf20Sopenharmony_ci __be32 *p; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 1438c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 1448c2ecf20Sopenharmony_ci return -ENOSPC; 1458c2ecf20Sopenharmony_ci count = be32_to_cpup(p++); 1468c2ecf20Sopenharmony_ci memset(&dummy, 0, sizeof(dummy)); 1478c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 1488c2ecf20Sopenharmony_ci gssx_dec_option(xdr, &dummy); 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci oa->count = 0; 1528c2ecf20Sopenharmony_ci oa->data = NULL; 1538c2ecf20Sopenharmony_ci return 0; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic int get_host_u32(struct xdr_stream *xdr, u32 *res) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci __be32 *p; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 1618c2ecf20Sopenharmony_ci if (!p) 1628c2ecf20Sopenharmony_ci return -EINVAL; 1638c2ecf20Sopenharmony_ci /* Contents of linux creds are all host-endian: */ 1648c2ecf20Sopenharmony_ci memcpy(res, p, sizeof(u32)); 1658c2ecf20Sopenharmony_ci return 0; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic int gssx_dec_linux_creds(struct xdr_stream *xdr, 1698c2ecf20Sopenharmony_ci struct svc_cred *creds) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci u32 length; 1728c2ecf20Sopenharmony_ci __be32 *p; 1738c2ecf20Sopenharmony_ci u32 tmp; 1748c2ecf20Sopenharmony_ci u32 N; 1758c2ecf20Sopenharmony_ci int i, err; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 1788c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 1798c2ecf20Sopenharmony_ci return -ENOSPC; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci length = be32_to_cpup(p); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (length > (3 + NGROUPS_MAX) * sizeof(u32)) 1848c2ecf20Sopenharmony_ci return -ENOSPC; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* uid */ 1878c2ecf20Sopenharmony_ci err = get_host_u32(xdr, &tmp); 1888c2ecf20Sopenharmony_ci if (err) 1898c2ecf20Sopenharmony_ci return err; 1908c2ecf20Sopenharmony_ci creds->cr_uid = make_kuid(&init_user_ns, tmp); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* gid */ 1938c2ecf20Sopenharmony_ci err = get_host_u32(xdr, &tmp); 1948c2ecf20Sopenharmony_ci if (err) 1958c2ecf20Sopenharmony_ci return err; 1968c2ecf20Sopenharmony_ci creds->cr_gid = make_kgid(&init_user_ns, tmp); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* number of additional gid's */ 1998c2ecf20Sopenharmony_ci err = get_host_u32(xdr, &tmp); 2008c2ecf20Sopenharmony_ci if (err) 2018c2ecf20Sopenharmony_ci return err; 2028c2ecf20Sopenharmony_ci N = tmp; 2038c2ecf20Sopenharmony_ci if ((3 + N) * sizeof(u32) != length) 2048c2ecf20Sopenharmony_ci return -EINVAL; 2058c2ecf20Sopenharmony_ci creds->cr_group_info = groups_alloc(N); 2068c2ecf20Sopenharmony_ci if (creds->cr_group_info == NULL) 2078c2ecf20Sopenharmony_ci return -ENOMEM; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* gid's */ 2108c2ecf20Sopenharmony_ci for (i = 0; i < N; i++) { 2118c2ecf20Sopenharmony_ci kgid_t kgid; 2128c2ecf20Sopenharmony_ci err = get_host_u32(xdr, &tmp); 2138c2ecf20Sopenharmony_ci if (err) 2148c2ecf20Sopenharmony_ci goto out_free_groups; 2158c2ecf20Sopenharmony_ci err = -EINVAL; 2168c2ecf20Sopenharmony_ci kgid = make_kgid(&init_user_ns, tmp); 2178c2ecf20Sopenharmony_ci if (!gid_valid(kgid)) 2188c2ecf20Sopenharmony_ci goto out_free_groups; 2198c2ecf20Sopenharmony_ci creds->cr_group_info->gid[i] = kgid; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci groups_sort(creds->cr_group_info); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ciout_free_groups: 2258c2ecf20Sopenharmony_ci groups_free(creds->cr_group_info); 2268c2ecf20Sopenharmony_ci return err; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic int gssx_dec_option_array(struct xdr_stream *xdr, 2308c2ecf20Sopenharmony_ci struct gssx_option_array *oa) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct svc_cred *creds; 2338c2ecf20Sopenharmony_ci u32 count, i; 2348c2ecf20Sopenharmony_ci __be32 *p; 2358c2ecf20Sopenharmony_ci int err; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 2388c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 2398c2ecf20Sopenharmony_ci return -ENOSPC; 2408c2ecf20Sopenharmony_ci count = be32_to_cpup(p++); 2418c2ecf20Sopenharmony_ci if (!count) 2428c2ecf20Sopenharmony_ci return 0; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* we recognize only 1 currently: CREDS_VALUE */ 2458c2ecf20Sopenharmony_ci oa->count = 1; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); 2488c2ecf20Sopenharmony_ci if (!oa->data) 2498c2ecf20Sopenharmony_ci return -ENOMEM; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL); 2528c2ecf20Sopenharmony_ci if (!creds) { 2538c2ecf20Sopenharmony_ci err = -ENOMEM; 2548c2ecf20Sopenharmony_ci goto free_oa; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci oa->data[0].option.data = CREDS_VALUE; 2588c2ecf20Sopenharmony_ci oa->data[0].option.len = sizeof(CREDS_VALUE); 2598c2ecf20Sopenharmony_ci oa->data[0].value.data = (void *)creds; 2608c2ecf20Sopenharmony_ci oa->data[0].value.len = 0; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 2638c2ecf20Sopenharmony_ci gssx_buffer dummy = { 0, NULL }; 2648c2ecf20Sopenharmony_ci u32 length; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* option buffer */ 2678c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 2688c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) { 2698c2ecf20Sopenharmony_ci err = -ENOSPC; 2708c2ecf20Sopenharmony_ci goto free_creds; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci length = be32_to_cpup(p); 2748c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, length); 2758c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) { 2768c2ecf20Sopenharmony_ci err = -ENOSPC; 2778c2ecf20Sopenharmony_ci goto free_creds; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (length == sizeof(CREDS_VALUE) && 2818c2ecf20Sopenharmony_ci memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) { 2828c2ecf20Sopenharmony_ci /* We have creds here. parse them */ 2838c2ecf20Sopenharmony_ci err = gssx_dec_linux_creds(xdr, creds); 2848c2ecf20Sopenharmony_ci if (err) 2858c2ecf20Sopenharmony_ci goto free_creds; 2868c2ecf20Sopenharmony_ci oa->data[0].value.len = 1; /* presence */ 2878c2ecf20Sopenharmony_ci } else { 2888c2ecf20Sopenharmony_ci /* consume uninteresting buffer */ 2898c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &dummy); 2908c2ecf20Sopenharmony_ci if (err) 2918c2ecf20Sopenharmony_ci goto free_creds; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cifree_creds: 2978c2ecf20Sopenharmony_ci kfree(creds); 2988c2ecf20Sopenharmony_cifree_oa: 2998c2ecf20Sopenharmony_ci kfree(oa->data); 3008c2ecf20Sopenharmony_ci oa->data = NULL; 3018c2ecf20Sopenharmony_ci return err; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int gssx_dec_status(struct xdr_stream *xdr, 3058c2ecf20Sopenharmony_ci struct gssx_status *status) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci __be32 *p; 3088c2ecf20Sopenharmony_ci int err; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* status->major_status */ 3118c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 8); 3128c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 3138c2ecf20Sopenharmony_ci return -ENOSPC; 3148c2ecf20Sopenharmony_ci p = xdr_decode_hyper(p, &status->major_status); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* status->mech */ 3178c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &status->mech); 3188c2ecf20Sopenharmony_ci if (err) 3198c2ecf20Sopenharmony_ci return err; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* status->minor_status */ 3228c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 8); 3238c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 3248c2ecf20Sopenharmony_ci return -ENOSPC; 3258c2ecf20Sopenharmony_ci p = xdr_decode_hyper(p, &status->minor_status); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* status->major_status_string */ 3288c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &status->major_status_string); 3298c2ecf20Sopenharmony_ci if (err) 3308c2ecf20Sopenharmony_ci return err; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* status->minor_status_string */ 3338c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &status->minor_status_string); 3348c2ecf20Sopenharmony_ci if (err) 3358c2ecf20Sopenharmony_ci return err; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* status->server_ctx */ 3388c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &status->server_ctx); 3398c2ecf20Sopenharmony_ci if (err) 3408c2ecf20Sopenharmony_ci return err; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* we assume we have no options for now, so simply consume them */ 3438c2ecf20Sopenharmony_ci /* status->options */ 3448c2ecf20Sopenharmony_ci err = dummy_dec_opt_array(xdr, &status->options); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci return err; 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic int gssx_enc_call_ctx(struct xdr_stream *xdr, 3508c2ecf20Sopenharmony_ci const struct gssx_call_ctx *ctx) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci struct gssx_option opt; 3538c2ecf20Sopenharmony_ci __be32 *p; 3548c2ecf20Sopenharmony_ci int err; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* ctx->locale */ 3578c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &ctx->locale); 3588c2ecf20Sopenharmony_ci if (err) 3598c2ecf20Sopenharmony_ci return err; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* ctx->server_ctx */ 3628c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &ctx->server_ctx); 3638c2ecf20Sopenharmony_ci if (err) 3648c2ecf20Sopenharmony_ci return err; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* we always want to ask for lucid contexts */ 3678c2ecf20Sopenharmony_ci /* ctx->options */ 3688c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 3698c2ecf20Sopenharmony_ci *p = cpu_to_be32(2); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci /* we want a lucid_v1 context */ 3728c2ecf20Sopenharmony_ci opt.option.data = LUCID_OPTION; 3738c2ecf20Sopenharmony_ci opt.option.len = sizeof(LUCID_OPTION); 3748c2ecf20Sopenharmony_ci opt.value.data = LUCID_VALUE; 3758c2ecf20Sopenharmony_ci opt.value.len = sizeof(LUCID_VALUE); 3768c2ecf20Sopenharmony_ci err = gssx_enc_option(xdr, &opt); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* ..and user creds */ 3798c2ecf20Sopenharmony_ci opt.option.data = CREDS_OPTION; 3808c2ecf20Sopenharmony_ci opt.option.len = sizeof(CREDS_OPTION); 3818c2ecf20Sopenharmony_ci opt.value.data = CREDS_VALUE; 3828c2ecf20Sopenharmony_ci opt.value.len = sizeof(CREDS_VALUE); 3838c2ecf20Sopenharmony_ci err = gssx_enc_option(xdr, &opt); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci return err; 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic int gssx_dec_name_attr(struct xdr_stream *xdr, 3898c2ecf20Sopenharmony_ci struct gssx_name_attr *attr) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci int err; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* attr->attr */ 3948c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &attr->attr); 3958c2ecf20Sopenharmony_ci if (err) 3968c2ecf20Sopenharmony_ci return err; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* attr->value */ 3998c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &attr->value); 4008c2ecf20Sopenharmony_ci if (err) 4018c2ecf20Sopenharmony_ci return err; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci /* attr->extensions */ 4048c2ecf20Sopenharmony_ci err = dummy_dec_opt_array(xdr, &attr->extensions); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci return err; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic int dummy_enc_nameattr_array(struct xdr_stream *xdr, 4108c2ecf20Sopenharmony_ci struct gssx_name_attr_array *naa) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci __be32 *p; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (naa->count != 0) 4158c2ecf20Sopenharmony_ci return -EINVAL; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 4188c2ecf20Sopenharmony_ci if (!p) 4198c2ecf20Sopenharmony_ci return -ENOSPC; 4208c2ecf20Sopenharmony_ci *p = 0; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic int dummy_dec_nameattr_array(struct xdr_stream *xdr, 4268c2ecf20Sopenharmony_ci struct gssx_name_attr_array *naa) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci struct gssx_name_attr dummy = { .attr = {.len = 0} }; 4298c2ecf20Sopenharmony_ci u32 count, i; 4308c2ecf20Sopenharmony_ci __be32 *p; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 4338c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 4348c2ecf20Sopenharmony_ci return -ENOSPC; 4358c2ecf20Sopenharmony_ci count = be32_to_cpup(p++); 4368c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 4378c2ecf20Sopenharmony_ci gssx_dec_name_attr(xdr, &dummy); 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci naa->count = 0; 4418c2ecf20Sopenharmony_ci naa->data = NULL; 4428c2ecf20Sopenharmony_ci return 0; 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic struct xdr_netobj zero_netobj = {}; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic struct gssx_name_attr_array zero_name_attr_array = {}; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic struct gssx_option_array zero_option_array = {}; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic int gssx_enc_name(struct xdr_stream *xdr, 4528c2ecf20Sopenharmony_ci struct gssx_name *name) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci int err; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* name->display_name */ 4578c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &name->display_name); 4588c2ecf20Sopenharmony_ci if (err) 4598c2ecf20Sopenharmony_ci return err; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci /* name->name_type */ 4628c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &zero_netobj); 4638c2ecf20Sopenharmony_ci if (err) 4648c2ecf20Sopenharmony_ci return err; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci /* name->exported_name */ 4678c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &zero_netobj); 4688c2ecf20Sopenharmony_ci if (err) 4698c2ecf20Sopenharmony_ci return err; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* name->exported_composite_name */ 4728c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &zero_netobj); 4738c2ecf20Sopenharmony_ci if (err) 4748c2ecf20Sopenharmony_ci return err; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci /* leave name_attributes empty for now, will add once we have any 4778c2ecf20Sopenharmony_ci * to pass up at all */ 4788c2ecf20Sopenharmony_ci /* name->name_attributes */ 4798c2ecf20Sopenharmony_ci err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array); 4808c2ecf20Sopenharmony_ci if (err) 4818c2ecf20Sopenharmony_ci return err; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* leave options empty for now, will add once we have any options 4848c2ecf20Sopenharmony_ci * to pass up at all */ 4858c2ecf20Sopenharmony_ci /* name->extensions */ 4868c2ecf20Sopenharmony_ci err = dummy_enc_opt_array(xdr, &zero_option_array); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci return err; 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic int gssx_dec_name(struct xdr_stream *xdr, 4938c2ecf20Sopenharmony_ci struct gssx_name *name) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct xdr_netobj dummy_netobj = { .len = 0 }; 4968c2ecf20Sopenharmony_ci struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 }; 4978c2ecf20Sopenharmony_ci struct gssx_option_array dummy_option_array = { .count = 0 }; 4988c2ecf20Sopenharmony_ci int err; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /* name->display_name */ 5018c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &name->display_name); 5028c2ecf20Sopenharmony_ci if (err) 5038c2ecf20Sopenharmony_ci return err; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* name->name_type */ 5068c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &dummy_netobj); 5078c2ecf20Sopenharmony_ci if (err) 5088c2ecf20Sopenharmony_ci return err; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* name->exported_name */ 5118c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &dummy_netobj); 5128c2ecf20Sopenharmony_ci if (err) 5138c2ecf20Sopenharmony_ci return err; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* name->exported_composite_name */ 5168c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &dummy_netobj); 5178c2ecf20Sopenharmony_ci if (err) 5188c2ecf20Sopenharmony_ci return err; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* we assume we have no attributes for now, so simply consume them */ 5218c2ecf20Sopenharmony_ci /* name->name_attributes */ 5228c2ecf20Sopenharmony_ci err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); 5238c2ecf20Sopenharmony_ci if (err) 5248c2ecf20Sopenharmony_ci return err; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci /* we assume we have no options for now, so simply consume them */ 5278c2ecf20Sopenharmony_ci /* name->extensions */ 5288c2ecf20Sopenharmony_ci err = dummy_dec_opt_array(xdr, &dummy_option_array); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci return err; 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic int dummy_enc_credel_array(struct xdr_stream *xdr, 5348c2ecf20Sopenharmony_ci struct gssx_cred_element_array *cea) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci __be32 *p; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if (cea->count != 0) 5398c2ecf20Sopenharmony_ci return -EINVAL; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 5428c2ecf20Sopenharmony_ci if (!p) 5438c2ecf20Sopenharmony_ci return -ENOSPC; 5448c2ecf20Sopenharmony_ci *p = 0; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci return 0; 5478c2ecf20Sopenharmony_ci} 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic int gssx_enc_cred(struct xdr_stream *xdr, 5508c2ecf20Sopenharmony_ci struct gssx_cred *cred) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci int err; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* cred->desired_name */ 5558c2ecf20Sopenharmony_ci err = gssx_enc_name(xdr, &cred->desired_name); 5568c2ecf20Sopenharmony_ci if (err) 5578c2ecf20Sopenharmony_ci return err; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci /* cred->elements */ 5608c2ecf20Sopenharmony_ci err = dummy_enc_credel_array(xdr, &cred->elements); 5618c2ecf20Sopenharmony_ci if (err) 5628c2ecf20Sopenharmony_ci return err; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci /* cred->cred_handle_reference */ 5658c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); 5668c2ecf20Sopenharmony_ci if (err) 5678c2ecf20Sopenharmony_ci return err; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* cred->needs_release */ 5708c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, cred->needs_release); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci return err; 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cistatic int gssx_enc_ctx(struct xdr_stream *xdr, 5768c2ecf20Sopenharmony_ci struct gssx_ctx *ctx) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci __be32 *p; 5798c2ecf20Sopenharmony_ci int err; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci /* ctx->exported_context_token */ 5828c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &ctx->exported_context_token); 5838c2ecf20Sopenharmony_ci if (err) 5848c2ecf20Sopenharmony_ci return err; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /* ctx->state */ 5878c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &ctx->state); 5888c2ecf20Sopenharmony_ci if (err) 5898c2ecf20Sopenharmony_ci return err; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* ctx->need_release */ 5928c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, ctx->need_release); 5938c2ecf20Sopenharmony_ci if (err) 5948c2ecf20Sopenharmony_ci return err; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci /* ctx->mech */ 5978c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &ctx->mech); 5988c2ecf20Sopenharmony_ci if (err) 5998c2ecf20Sopenharmony_ci return err; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* ctx->src_name */ 6028c2ecf20Sopenharmony_ci err = gssx_enc_name(xdr, &ctx->src_name); 6038c2ecf20Sopenharmony_ci if (err) 6048c2ecf20Sopenharmony_ci return err; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci /* ctx->targ_name */ 6078c2ecf20Sopenharmony_ci err = gssx_enc_name(xdr, &ctx->targ_name); 6088c2ecf20Sopenharmony_ci if (err) 6098c2ecf20Sopenharmony_ci return err; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* ctx->lifetime */ 6128c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 8+8); 6138c2ecf20Sopenharmony_ci if (!p) 6148c2ecf20Sopenharmony_ci return -ENOSPC; 6158c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, ctx->lifetime); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci /* ctx->ctx_flags */ 6188c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, ctx->ctx_flags); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci /* ctx->locally_initiated */ 6218c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, ctx->locally_initiated); 6228c2ecf20Sopenharmony_ci if (err) 6238c2ecf20Sopenharmony_ci return err; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci /* ctx->open */ 6268c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, ctx->open); 6278c2ecf20Sopenharmony_ci if (err) 6288c2ecf20Sopenharmony_ci return err; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci /* leave options empty for now, will add once we have any options 6318c2ecf20Sopenharmony_ci * to pass up at all */ 6328c2ecf20Sopenharmony_ci /* ctx->options */ 6338c2ecf20Sopenharmony_ci err = dummy_enc_opt_array(xdr, &ctx->options); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci return err; 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_cistatic int gssx_dec_ctx(struct xdr_stream *xdr, 6398c2ecf20Sopenharmony_ci struct gssx_ctx *ctx) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci __be32 *p; 6428c2ecf20Sopenharmony_ci int err; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* ctx->exported_context_token */ 6458c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &ctx->exported_context_token); 6468c2ecf20Sopenharmony_ci if (err) 6478c2ecf20Sopenharmony_ci return err; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci /* ctx->state */ 6508c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &ctx->state); 6518c2ecf20Sopenharmony_ci if (err) 6528c2ecf20Sopenharmony_ci return err; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci /* ctx->need_release */ 6558c2ecf20Sopenharmony_ci err = gssx_dec_bool(xdr, &ctx->need_release); 6568c2ecf20Sopenharmony_ci if (err) 6578c2ecf20Sopenharmony_ci return err; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* ctx->mech */ 6608c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, &ctx->mech); 6618c2ecf20Sopenharmony_ci if (err) 6628c2ecf20Sopenharmony_ci return err; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci /* ctx->src_name */ 6658c2ecf20Sopenharmony_ci err = gssx_dec_name(xdr, &ctx->src_name); 6668c2ecf20Sopenharmony_ci if (err) 6678c2ecf20Sopenharmony_ci return err; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci /* ctx->targ_name */ 6708c2ecf20Sopenharmony_ci err = gssx_dec_name(xdr, &ctx->targ_name); 6718c2ecf20Sopenharmony_ci if (err) 6728c2ecf20Sopenharmony_ci return err; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci /* ctx->lifetime */ 6758c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 8+8); 6768c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 6778c2ecf20Sopenharmony_ci return -ENOSPC; 6788c2ecf20Sopenharmony_ci p = xdr_decode_hyper(p, &ctx->lifetime); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci /* ctx->ctx_flags */ 6818c2ecf20Sopenharmony_ci p = xdr_decode_hyper(p, &ctx->ctx_flags); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci /* ctx->locally_initiated */ 6848c2ecf20Sopenharmony_ci err = gssx_dec_bool(xdr, &ctx->locally_initiated); 6858c2ecf20Sopenharmony_ci if (err) 6868c2ecf20Sopenharmony_ci return err; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci /* ctx->open */ 6898c2ecf20Sopenharmony_ci err = gssx_dec_bool(xdr, &ctx->open); 6908c2ecf20Sopenharmony_ci if (err) 6918c2ecf20Sopenharmony_ci return err; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* we assume we have no options for now, so simply consume them */ 6948c2ecf20Sopenharmony_ci /* ctx->options */ 6958c2ecf20Sopenharmony_ci err = dummy_dec_opt_array(xdr, &ctx->options); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci return err; 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_cistatic int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb) 7018c2ecf20Sopenharmony_ci{ 7028c2ecf20Sopenharmony_ci __be32 *p; 7038c2ecf20Sopenharmony_ci int err; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci /* cb->initiator_addrtype */ 7068c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 8); 7078c2ecf20Sopenharmony_ci if (!p) 7088c2ecf20Sopenharmony_ci return -ENOSPC; 7098c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, cb->initiator_addrtype); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* cb->initiator_address */ 7128c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &cb->initiator_address); 7138c2ecf20Sopenharmony_ci if (err) 7148c2ecf20Sopenharmony_ci return err; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci /* cb->acceptor_addrtype */ 7178c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 8); 7188c2ecf20Sopenharmony_ci if (!p) 7198c2ecf20Sopenharmony_ci return -ENOSPC; 7208c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, cb->acceptor_addrtype); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* cb->acceptor_address */ 7238c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &cb->acceptor_address); 7248c2ecf20Sopenharmony_ci if (err) 7258c2ecf20Sopenharmony_ci return err; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci /* cb->application_data */ 7288c2ecf20Sopenharmony_ci err = gssx_enc_buffer(xdr, &cb->application_data); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci return err; 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_civoid gssx_enc_accept_sec_context(struct rpc_rqst *req, 7348c2ecf20Sopenharmony_ci struct xdr_stream *xdr, 7358c2ecf20Sopenharmony_ci const void *data) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci const struct gssx_arg_accept_sec_context *arg = data; 7388c2ecf20Sopenharmony_ci int err; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci err = gssx_enc_call_ctx(xdr, &arg->call_ctx); 7418c2ecf20Sopenharmony_ci if (err) 7428c2ecf20Sopenharmony_ci goto done; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci /* arg->context_handle */ 7458c2ecf20Sopenharmony_ci if (arg->context_handle) 7468c2ecf20Sopenharmony_ci err = gssx_enc_ctx(xdr, arg->context_handle); 7478c2ecf20Sopenharmony_ci else 7488c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, 0); 7498c2ecf20Sopenharmony_ci if (err) 7508c2ecf20Sopenharmony_ci goto done; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* arg->cred_handle */ 7538c2ecf20Sopenharmony_ci if (arg->cred_handle) 7548c2ecf20Sopenharmony_ci err = gssx_enc_cred(xdr, arg->cred_handle); 7558c2ecf20Sopenharmony_ci else 7568c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, 0); 7578c2ecf20Sopenharmony_ci if (err) 7588c2ecf20Sopenharmony_ci goto done; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci /* arg->input_token */ 7618c2ecf20Sopenharmony_ci err = gssx_enc_in_token(xdr, &arg->input_token); 7628c2ecf20Sopenharmony_ci if (err) 7638c2ecf20Sopenharmony_ci goto done; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci /* arg->input_cb */ 7668c2ecf20Sopenharmony_ci if (arg->input_cb) 7678c2ecf20Sopenharmony_ci err = gssx_enc_cb(xdr, arg->input_cb); 7688c2ecf20Sopenharmony_ci else 7698c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, 0); 7708c2ecf20Sopenharmony_ci if (err) 7718c2ecf20Sopenharmony_ci goto done; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci err = gssx_enc_bool(xdr, arg->ret_deleg_cred); 7748c2ecf20Sopenharmony_ci if (err) 7758c2ecf20Sopenharmony_ci goto done; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* leave options empty for now, will add once we have any options 7788c2ecf20Sopenharmony_ci * to pass up at all */ 7798c2ecf20Sopenharmony_ci /* arg->options */ 7808c2ecf20Sopenharmony_ci err = dummy_enc_opt_array(xdr, &arg->options); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci xdr_inline_pages(&req->rq_rcv_buf, 7838c2ecf20Sopenharmony_ci PAGE_SIZE/2 /* pretty arbitrary */, 7848c2ecf20Sopenharmony_ci arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE); 7858c2ecf20Sopenharmony_ci req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES; 7868c2ecf20Sopenharmony_cidone: 7878c2ecf20Sopenharmony_ci if (err) 7888c2ecf20Sopenharmony_ci dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ciint gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, 7928c2ecf20Sopenharmony_ci struct xdr_stream *xdr, 7938c2ecf20Sopenharmony_ci void *data) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci struct gssx_res_accept_sec_context *res = data; 7968c2ecf20Sopenharmony_ci u32 value_follows; 7978c2ecf20Sopenharmony_ci int err; 7988c2ecf20Sopenharmony_ci struct page *scratch; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci scratch = alloc_page(GFP_KERNEL); 8018c2ecf20Sopenharmony_ci if (!scratch) 8028c2ecf20Sopenharmony_ci return -ENOMEM; 8038c2ecf20Sopenharmony_ci xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci /* res->status */ 8068c2ecf20Sopenharmony_ci err = gssx_dec_status(xdr, &res->status); 8078c2ecf20Sopenharmony_ci if (err) 8088c2ecf20Sopenharmony_ci goto out_free; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci /* res->context_handle */ 8118c2ecf20Sopenharmony_ci err = gssx_dec_bool(xdr, &value_follows); 8128c2ecf20Sopenharmony_ci if (err) 8138c2ecf20Sopenharmony_ci goto out_free; 8148c2ecf20Sopenharmony_ci if (value_follows) { 8158c2ecf20Sopenharmony_ci err = gssx_dec_ctx(xdr, res->context_handle); 8168c2ecf20Sopenharmony_ci if (err) 8178c2ecf20Sopenharmony_ci goto out_free; 8188c2ecf20Sopenharmony_ci } else { 8198c2ecf20Sopenharmony_ci res->context_handle = NULL; 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci /* res->output_token */ 8238c2ecf20Sopenharmony_ci err = gssx_dec_bool(xdr, &value_follows); 8248c2ecf20Sopenharmony_ci if (err) 8258c2ecf20Sopenharmony_ci goto out_free; 8268c2ecf20Sopenharmony_ci if (value_follows) { 8278c2ecf20Sopenharmony_ci err = gssx_dec_buffer(xdr, res->output_token); 8288c2ecf20Sopenharmony_ci if (err) 8298c2ecf20Sopenharmony_ci goto out_free; 8308c2ecf20Sopenharmony_ci } else { 8318c2ecf20Sopenharmony_ci res->output_token = NULL; 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* res->delegated_cred_handle */ 8358c2ecf20Sopenharmony_ci err = gssx_dec_bool(xdr, &value_follows); 8368c2ecf20Sopenharmony_ci if (err) 8378c2ecf20Sopenharmony_ci goto out_free; 8388c2ecf20Sopenharmony_ci if (value_follows) { 8398c2ecf20Sopenharmony_ci /* we do not support upcall servers sending this data. */ 8408c2ecf20Sopenharmony_ci err = -EINVAL; 8418c2ecf20Sopenharmony_ci goto out_free; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci /* res->options */ 8458c2ecf20Sopenharmony_ci err = gssx_dec_option_array(xdr, &res->options); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ciout_free: 8488c2ecf20Sopenharmony_ci __free_page(scratch); 8498c2ecf20Sopenharmony_ci return err; 8508c2ecf20Sopenharmony_ci} 851