18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/net/sunrpc/gss_rpc_upcall.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Simo Sorce <simo@redhat.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/types.h> 98c2ecf20Sopenharmony_ci#include <linux/un.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/sunrpc/svcauth.h> 128c2ecf20Sopenharmony_ci#include "gss_rpc_upcall.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define GSSPROXY_SOCK_PATHNAME "/var/run/gssproxy.sock" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define GSSPROXY_PROGRAM (400112u) 178c2ecf20Sopenharmony_ci#define GSSPROXY_VERS_1 (1u) 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * Encoding/Decoding functions 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cienum { 248c2ecf20Sopenharmony_ci GSSX_NULL = 0, /* Unused */ 258c2ecf20Sopenharmony_ci GSSX_INDICATE_MECHS = 1, 268c2ecf20Sopenharmony_ci GSSX_GET_CALL_CONTEXT = 2, 278c2ecf20Sopenharmony_ci GSSX_IMPORT_AND_CANON_NAME = 3, 288c2ecf20Sopenharmony_ci GSSX_EXPORT_CRED = 4, 298c2ecf20Sopenharmony_ci GSSX_IMPORT_CRED = 5, 308c2ecf20Sopenharmony_ci GSSX_ACQUIRE_CRED = 6, 318c2ecf20Sopenharmony_ci GSSX_STORE_CRED = 7, 328c2ecf20Sopenharmony_ci GSSX_INIT_SEC_CONTEXT = 8, 338c2ecf20Sopenharmony_ci GSSX_ACCEPT_SEC_CONTEXT = 9, 348c2ecf20Sopenharmony_ci GSSX_RELEASE_HANDLE = 10, 358c2ecf20Sopenharmony_ci GSSX_GET_MIC = 11, 368c2ecf20Sopenharmony_ci GSSX_VERIFY = 12, 378c2ecf20Sopenharmony_ci GSSX_WRAP = 13, 388c2ecf20Sopenharmony_ci GSSX_UNWRAP = 14, 398c2ecf20Sopenharmony_ci GSSX_WRAP_SIZE_LIMIT = 15, 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define PROC(proc, name) \ 438c2ecf20Sopenharmony_ci[GSSX_##proc] = { \ 448c2ecf20Sopenharmony_ci .p_proc = GSSX_##proc, \ 458c2ecf20Sopenharmony_ci .p_encode = gssx_enc_##name, \ 468c2ecf20Sopenharmony_ci .p_decode = gssx_dec_##name, \ 478c2ecf20Sopenharmony_ci .p_arglen = GSSX_ARG_##name##_sz, \ 488c2ecf20Sopenharmony_ci .p_replen = GSSX_RES_##name##_sz, \ 498c2ecf20Sopenharmony_ci .p_statidx = GSSX_##proc, \ 508c2ecf20Sopenharmony_ci .p_name = #proc, \ 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic const struct rpc_procinfo gssp_procedures[] = { 548c2ecf20Sopenharmony_ci PROC(INDICATE_MECHS, indicate_mechs), 558c2ecf20Sopenharmony_ci PROC(GET_CALL_CONTEXT, get_call_context), 568c2ecf20Sopenharmony_ci PROC(IMPORT_AND_CANON_NAME, import_and_canon_name), 578c2ecf20Sopenharmony_ci PROC(EXPORT_CRED, export_cred), 588c2ecf20Sopenharmony_ci PROC(IMPORT_CRED, import_cred), 598c2ecf20Sopenharmony_ci PROC(ACQUIRE_CRED, acquire_cred), 608c2ecf20Sopenharmony_ci PROC(STORE_CRED, store_cred), 618c2ecf20Sopenharmony_ci PROC(INIT_SEC_CONTEXT, init_sec_context), 628c2ecf20Sopenharmony_ci PROC(ACCEPT_SEC_CONTEXT, accept_sec_context), 638c2ecf20Sopenharmony_ci PROC(RELEASE_HANDLE, release_handle), 648c2ecf20Sopenharmony_ci PROC(GET_MIC, get_mic), 658c2ecf20Sopenharmony_ci PROC(VERIFY, verify), 668c2ecf20Sopenharmony_ci PROC(WRAP, wrap), 678c2ecf20Sopenharmony_ci PROC(UNWRAP, unwrap), 688c2ecf20Sopenharmony_ci PROC(WRAP_SIZE_LIMIT, wrap_size_limit), 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* 748c2ecf20Sopenharmony_ci * Common transport functions 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic const struct rpc_program gssp_program; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci static const struct sockaddr_un gssp_localaddr = { 828c2ecf20Sopenharmony_ci .sun_family = AF_LOCAL, 838c2ecf20Sopenharmony_ci .sun_path = GSSPROXY_SOCK_PATHNAME, 848c2ecf20Sopenharmony_ci }; 858c2ecf20Sopenharmony_ci struct rpc_create_args args = { 868c2ecf20Sopenharmony_ci .net = net, 878c2ecf20Sopenharmony_ci .protocol = XPRT_TRANSPORT_LOCAL, 888c2ecf20Sopenharmony_ci .address = (struct sockaddr *)&gssp_localaddr, 898c2ecf20Sopenharmony_ci .addrsize = sizeof(gssp_localaddr), 908c2ecf20Sopenharmony_ci .servername = "localhost", 918c2ecf20Sopenharmony_ci .program = &gssp_program, 928c2ecf20Sopenharmony_ci .version = GSSPROXY_VERS_1, 938c2ecf20Sopenharmony_ci .authflavor = RPC_AUTH_NULL, 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * Note we want connection to be done in the caller's 968c2ecf20Sopenharmony_ci * filesystem namespace. We therefore turn off the idle 978c2ecf20Sopenharmony_ci * timeout, which would result in reconnections being 988c2ecf20Sopenharmony_ci * done without the correct namespace: 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci .flags = RPC_CLNT_CREATE_NOPING | 1018c2ecf20Sopenharmony_ci RPC_CLNT_CREATE_NO_IDLE_TIMEOUT 1028c2ecf20Sopenharmony_ci }; 1038c2ecf20Sopenharmony_ci struct rpc_clnt *clnt; 1048c2ecf20Sopenharmony_ci int result = 0; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci clnt = rpc_create(&args); 1078c2ecf20Sopenharmony_ci if (IS_ERR(clnt)) { 1088c2ecf20Sopenharmony_ci dprintk("RPC: failed to create AF_LOCAL gssproxy " 1098c2ecf20Sopenharmony_ci "client (errno %ld).\n", PTR_ERR(clnt)); 1108c2ecf20Sopenharmony_ci result = PTR_ERR(clnt); 1118c2ecf20Sopenharmony_ci *_clnt = NULL; 1128c2ecf20Sopenharmony_ci goto out; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci dprintk("RPC: created new gssp local client (gssp_local_clnt: " 1168c2ecf20Sopenharmony_ci "%p)\n", clnt); 1178c2ecf20Sopenharmony_ci *_clnt = clnt; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciout: 1208c2ecf20Sopenharmony_ci return result; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_civoid init_gssp_clnt(struct sunrpc_net *sn) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci mutex_init(&sn->gssp_lock); 1268c2ecf20Sopenharmony_ci sn->gssp_clnt = NULL; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ciint set_gssp_clnt(struct net *net) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1328c2ecf20Sopenharmony_ci struct rpc_clnt *clnt; 1338c2ecf20Sopenharmony_ci int ret; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci mutex_lock(&sn->gssp_lock); 1368c2ecf20Sopenharmony_ci ret = gssp_rpc_create(net, &clnt); 1378c2ecf20Sopenharmony_ci if (!ret) { 1388c2ecf20Sopenharmony_ci if (sn->gssp_clnt) 1398c2ecf20Sopenharmony_ci rpc_shutdown_client(sn->gssp_clnt); 1408c2ecf20Sopenharmony_ci sn->gssp_clnt = clnt; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci mutex_unlock(&sn->gssp_lock); 1438c2ecf20Sopenharmony_ci return ret; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_civoid clear_gssp_clnt(struct sunrpc_net *sn) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci mutex_lock(&sn->gssp_lock); 1498c2ecf20Sopenharmony_ci if (sn->gssp_clnt) { 1508c2ecf20Sopenharmony_ci rpc_shutdown_client(sn->gssp_clnt); 1518c2ecf20Sopenharmony_ci sn->gssp_clnt = NULL; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci mutex_unlock(&sn->gssp_lock); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic struct rpc_clnt *get_gssp_clnt(struct sunrpc_net *sn) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct rpc_clnt *clnt; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci mutex_lock(&sn->gssp_lock); 1618c2ecf20Sopenharmony_ci clnt = sn->gssp_clnt; 1628c2ecf20Sopenharmony_ci if (clnt) 1638c2ecf20Sopenharmony_ci atomic_inc(&clnt->cl_count); 1648c2ecf20Sopenharmony_ci mutex_unlock(&sn->gssp_lock); 1658c2ecf20Sopenharmony_ci return clnt; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic int gssp_call(struct net *net, struct rpc_message *msg) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1718c2ecf20Sopenharmony_ci struct rpc_clnt *clnt; 1728c2ecf20Sopenharmony_ci int status; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci clnt = get_gssp_clnt(sn); 1758c2ecf20Sopenharmony_ci if (!clnt) 1768c2ecf20Sopenharmony_ci return -EIO; 1778c2ecf20Sopenharmony_ci status = rpc_call_sync(clnt, msg, 0); 1788c2ecf20Sopenharmony_ci if (status < 0) { 1798c2ecf20Sopenharmony_ci dprintk("gssp: rpc_call returned error %d\n", -status); 1808c2ecf20Sopenharmony_ci switch (status) { 1818c2ecf20Sopenharmony_ci case -EPROTONOSUPPORT: 1828c2ecf20Sopenharmony_ci status = -EINVAL; 1838c2ecf20Sopenharmony_ci break; 1848c2ecf20Sopenharmony_ci case -ECONNREFUSED: 1858c2ecf20Sopenharmony_ci case -ETIMEDOUT: 1868c2ecf20Sopenharmony_ci case -ENOTCONN: 1878c2ecf20Sopenharmony_ci status = -EAGAIN; 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci case -ERESTARTSYS: 1908c2ecf20Sopenharmony_ci if (signalled ()) 1918c2ecf20Sopenharmony_ci status = -EINTR; 1928c2ecf20Sopenharmony_ci break; 1938c2ecf20Sopenharmony_ci default: 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci rpc_release_client(clnt); 1988c2ecf20Sopenharmony_ci return status; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci int i; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci for (i = 0; i < arg->npages && arg->pages[i]; i++) 2068c2ecf20Sopenharmony_ci __free_page(arg->pages[i]); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci kfree(arg->pages); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE); 2148c2ecf20Sopenharmony_ci arg->pages = kcalloc(arg->npages, sizeof(struct page *), GFP_KERNEL); 2158c2ecf20Sopenharmony_ci /* 2168c2ecf20Sopenharmony_ci * XXX: actual pages are allocated by xdr layer in 2178c2ecf20Sopenharmony_ci * xdr_partial_copy_from_skb. 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci if (!arg->pages) 2208c2ecf20Sopenharmony_ci return -ENOMEM; 2218c2ecf20Sopenharmony_ci return 0; 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic char *gssp_stringify(struct xdr_netobj *netobj) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci return kmemdup_nul(netobj->data, netobj->len, GFP_KERNEL); 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic void gssp_hostbased_service(char **principal) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci char *c; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (!*principal) 2348c2ecf20Sopenharmony_ci return; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* terminate and remove realm part */ 2378c2ecf20Sopenharmony_ci c = strchr(*principal, '@'); 2388c2ecf20Sopenharmony_ci if (c) { 2398c2ecf20Sopenharmony_ci *c = '\0'; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* change service-hostname delimiter */ 2428c2ecf20Sopenharmony_ci c = strchr(*principal, '/'); 2438c2ecf20Sopenharmony_ci if (c) 2448c2ecf20Sopenharmony_ci *c = '@'; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci if (!c) { 2478c2ecf20Sopenharmony_ci /* not a service principal */ 2488c2ecf20Sopenharmony_ci kfree(*principal); 2498c2ecf20Sopenharmony_ci *principal = NULL; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci/* 2548c2ecf20Sopenharmony_ci * Public functions 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci/* numbers somewhat arbitrary but large enough for current needs */ 2588c2ecf20Sopenharmony_ci#define GSSX_MAX_OUT_HANDLE 128 2598c2ecf20Sopenharmony_ci#define GSSX_MAX_SRC_PRINC 256 2608c2ecf20Sopenharmony_ci#define GSSX_KMEMBUF (GSSX_max_output_handle_sz + \ 2618c2ecf20Sopenharmony_ci GSSX_max_oid_sz + \ 2628c2ecf20Sopenharmony_ci GSSX_max_princ_sz + \ 2638c2ecf20Sopenharmony_ci sizeof(struct svc_cred)) 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciint gssp_accept_sec_context_upcall(struct net *net, 2668c2ecf20Sopenharmony_ci struct gssp_upcall_data *data) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct gssx_ctx ctxh = { 2698c2ecf20Sopenharmony_ci .state = data->in_handle 2708c2ecf20Sopenharmony_ci }; 2718c2ecf20Sopenharmony_ci struct gssx_arg_accept_sec_context arg = { 2728c2ecf20Sopenharmony_ci .input_token = data->in_token, 2738c2ecf20Sopenharmony_ci }; 2748c2ecf20Sopenharmony_ci struct gssx_ctx rctxh = { 2758c2ecf20Sopenharmony_ci /* 2768c2ecf20Sopenharmony_ci * pass in the max length we expect for each of these 2778c2ecf20Sopenharmony_ci * buffers but let the xdr code kmalloc them: 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci .exported_context_token.len = GSSX_max_output_handle_sz, 2808c2ecf20Sopenharmony_ci .mech.len = GSS_OID_MAX_LEN, 2818c2ecf20Sopenharmony_ci .targ_name.display_name.len = GSSX_max_princ_sz, 2828c2ecf20Sopenharmony_ci .src_name.display_name.len = GSSX_max_princ_sz 2838c2ecf20Sopenharmony_ci }; 2848c2ecf20Sopenharmony_ci struct gssx_res_accept_sec_context res = { 2858c2ecf20Sopenharmony_ci .context_handle = &rctxh, 2868c2ecf20Sopenharmony_ci .output_token = &data->out_token 2878c2ecf20Sopenharmony_ci }; 2888c2ecf20Sopenharmony_ci struct rpc_message msg = { 2898c2ecf20Sopenharmony_ci .rpc_proc = &gssp_procedures[GSSX_ACCEPT_SEC_CONTEXT], 2908c2ecf20Sopenharmony_ci .rpc_argp = &arg, 2918c2ecf20Sopenharmony_ci .rpc_resp = &res, 2928c2ecf20Sopenharmony_ci .rpc_cred = NULL, /* FIXME ? */ 2938c2ecf20Sopenharmony_ci }; 2948c2ecf20Sopenharmony_ci struct xdr_netobj client_name = { 0 , NULL }; 2958c2ecf20Sopenharmony_ci struct xdr_netobj target_name = { 0, NULL }; 2968c2ecf20Sopenharmony_ci int ret; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (data->in_handle.len != 0) 2998c2ecf20Sopenharmony_ci arg.context_handle = &ctxh; 3008c2ecf20Sopenharmony_ci res.output_token->len = GSSX_max_output_token_sz; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci ret = gssp_alloc_receive_pages(&arg); 3038c2ecf20Sopenharmony_ci if (ret) 3048c2ecf20Sopenharmony_ci return ret; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci ret = gssp_call(net, &msg); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci gssp_free_receive_pages(&arg); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* we need to fetch all data even in case of error so 3118c2ecf20Sopenharmony_ci * that we can free special strctures is they have been allocated */ 3128c2ecf20Sopenharmony_ci data->major_status = res.status.major_status; 3138c2ecf20Sopenharmony_ci data->minor_status = res.status.minor_status; 3148c2ecf20Sopenharmony_ci if (res.context_handle) { 3158c2ecf20Sopenharmony_ci data->out_handle = rctxh.exported_context_token; 3168c2ecf20Sopenharmony_ci data->mech_oid.len = rctxh.mech.len; 3178c2ecf20Sopenharmony_ci if (rctxh.mech.data) { 3188c2ecf20Sopenharmony_ci memcpy(data->mech_oid.data, rctxh.mech.data, 3198c2ecf20Sopenharmony_ci data->mech_oid.len); 3208c2ecf20Sopenharmony_ci kfree(rctxh.mech.data); 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci client_name = rctxh.src_name.display_name; 3238c2ecf20Sopenharmony_ci target_name = rctxh.targ_name.display_name; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (res.options.count == 1) { 3278c2ecf20Sopenharmony_ci gssx_buffer *value = &res.options.data[0].value; 3288c2ecf20Sopenharmony_ci /* Currently we only decode CREDS_VALUE, if we add 3298c2ecf20Sopenharmony_ci * anything else we'll have to loop and match on the 3308c2ecf20Sopenharmony_ci * option name */ 3318c2ecf20Sopenharmony_ci if (value->len == 1) { 3328c2ecf20Sopenharmony_ci /* steal group info from struct svc_cred */ 3338c2ecf20Sopenharmony_ci data->creds = *(struct svc_cred *)value->data; 3348c2ecf20Sopenharmony_ci data->found_creds = 1; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci /* whether we use it or not, free data */ 3378c2ecf20Sopenharmony_ci kfree(value->data); 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (res.options.count != 0) { 3418c2ecf20Sopenharmony_ci kfree(res.options.data); 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */ 3458c2ecf20Sopenharmony_ci if (data->found_creds) { 3468c2ecf20Sopenharmony_ci if (client_name.data) { 3478c2ecf20Sopenharmony_ci data->creds.cr_raw_principal = 3488c2ecf20Sopenharmony_ci gssp_stringify(&client_name); 3498c2ecf20Sopenharmony_ci data->creds.cr_principal = 3508c2ecf20Sopenharmony_ci gssp_stringify(&client_name); 3518c2ecf20Sopenharmony_ci gssp_hostbased_service(&data->creds.cr_principal); 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci if (target_name.data) { 3548c2ecf20Sopenharmony_ci data->creds.cr_targ_princ = 3558c2ecf20Sopenharmony_ci gssp_stringify(&target_name); 3568c2ecf20Sopenharmony_ci gssp_hostbased_service(&data->creds.cr_targ_princ); 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci kfree(client_name.data); 3608c2ecf20Sopenharmony_ci kfree(target_name.data); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci return ret; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_civoid gssp_free_upcall_data(struct gssp_upcall_data *data) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci kfree(data->in_handle.data); 3688c2ecf20Sopenharmony_ci kfree(data->out_handle.data); 3698c2ecf20Sopenharmony_ci kfree(data->out_token.data); 3708c2ecf20Sopenharmony_ci free_svc_cred(&data->creds); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/* 3748c2ecf20Sopenharmony_ci * Initialization stuff 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_cistatic unsigned int gssp_version1_counts[ARRAY_SIZE(gssp_procedures)]; 3778c2ecf20Sopenharmony_cistatic const struct rpc_version gssp_version1 = { 3788c2ecf20Sopenharmony_ci .number = GSSPROXY_VERS_1, 3798c2ecf20Sopenharmony_ci .nrprocs = ARRAY_SIZE(gssp_procedures), 3808c2ecf20Sopenharmony_ci .procs = gssp_procedures, 3818c2ecf20Sopenharmony_ci .counts = gssp_version1_counts, 3828c2ecf20Sopenharmony_ci}; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic const struct rpc_version *gssp_version[] = { 3858c2ecf20Sopenharmony_ci NULL, 3868c2ecf20Sopenharmony_ci &gssp_version1, 3878c2ecf20Sopenharmony_ci}; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic struct rpc_stat gssp_stats; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic const struct rpc_program gssp_program = { 3928c2ecf20Sopenharmony_ci .name = "gssproxy", 3938c2ecf20Sopenharmony_ci .number = GSSPROXY_PROGRAM, 3948c2ecf20Sopenharmony_ci .nrvers = ARRAY_SIZE(gssp_version), 3958c2ecf20Sopenharmony_ci .version = gssp_version, 3968c2ecf20Sopenharmony_ci .stats = &gssp_stats, 3978c2ecf20Sopenharmony_ci}; 398