1 /* 2 * linux/net/sunrpc/gss_rpc_upcall.c 3 * 4 * Copyright (C) 2012 Simo Sorce <simo@redhat.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include <linux/types.h> 22 #include <linux/un.h> 23 24 #include <linux/sunrpc/svcauth.h> 25 #include "gss_rpc_upcall.h" 26 27 #define GSSPROXY_SOCK_PATHNAME "/var/run/gssproxy.sock" 28 29 #define GSSPROXY_PROGRAM (400112u) 30 #define GSSPROXY_VERS_1 (1u) 31 32 /* 33 * Encoding/Decoding functions 34 */ 35 36 enum { 37 GSSX_NULL = 0, /* Unused */ 38 GSSX_INDICATE_MECHS = 1, 39 GSSX_GET_CALL_CONTEXT = 2, 40 GSSX_IMPORT_AND_CANON_NAME = 3, 41 GSSX_EXPORT_CRED = 4, 42 GSSX_IMPORT_CRED = 5, 43 GSSX_ACQUIRE_CRED = 6, 44 GSSX_STORE_CRED = 7, 45 GSSX_INIT_SEC_CONTEXT = 8, 46 GSSX_ACCEPT_SEC_CONTEXT = 9, 47 GSSX_RELEASE_HANDLE = 10, 48 GSSX_GET_MIC = 11, 49 GSSX_VERIFY = 12, 50 GSSX_WRAP = 13, 51 GSSX_UNWRAP = 14, 52 GSSX_WRAP_SIZE_LIMIT = 15, 53 }; 54 55 #define PROC(proc, name) \ 56 [GSSX_##proc] = { \ 57 .p_proc = GSSX_##proc, \ 58 .p_encode = gssx_enc_##name, \ 59 .p_decode = gssx_dec_##name, \ 60 .p_arglen = GSSX_ARG_##name##_sz, \ 61 .p_replen = GSSX_RES_##name##_sz, \ 62 .p_statidx = GSSX_##proc, \ 63 .p_name = #proc, \ 64 } 65 66 static const struct rpc_procinfo gssp_procedures[] = { 67 PROC(INDICATE_MECHS, indicate_mechs), 68 PROC(GET_CALL_CONTEXT, get_call_context), 69 PROC(IMPORT_AND_CANON_NAME, import_and_canon_name), 70 PROC(EXPORT_CRED, export_cred), 71 PROC(IMPORT_CRED, import_cred), 72 PROC(ACQUIRE_CRED, acquire_cred), 73 PROC(STORE_CRED, store_cred), 74 PROC(INIT_SEC_CONTEXT, init_sec_context), 75 PROC(ACCEPT_SEC_CONTEXT, accept_sec_context), 76 PROC(RELEASE_HANDLE, release_handle), 77 PROC(GET_MIC, get_mic), 78 PROC(VERIFY, verify), 79 PROC(WRAP, wrap), 80 PROC(UNWRAP, unwrap), 81 PROC(WRAP_SIZE_LIMIT, wrap_size_limit), 82 }; 83 84 85 86 /* 87 * Common transport functions 88 */ 89 90 static const struct rpc_program gssp_program; 91 92 static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt) 93 { 94 static const struct sockaddr_un gssp_localaddr = { 95 .sun_family = AF_LOCAL, 96 .sun_path = GSSPROXY_SOCK_PATHNAME, 97 }; 98 struct rpc_create_args args = { 99 .net = net, 100 .protocol = XPRT_TRANSPORT_LOCAL, 101 .address = (struct sockaddr *)&gssp_localaddr, 102 .addrsize = sizeof(gssp_localaddr), 103 .servername = "localhost", 104 .program = &gssp_program, 105 .version = GSSPROXY_VERS_1, 106 .authflavor = RPC_AUTH_NULL, 107 /* 108 * Note we want connection to be done in the caller's 109 * filesystem namespace. We therefore turn off the idle 110 * timeout, which would result in reconnections being 111 * done without the correct namespace: 112 */ 113 .flags = RPC_CLNT_CREATE_NOPING | 114 RPC_CLNT_CREATE_NO_IDLE_TIMEOUT 115 }; 116 struct rpc_clnt *clnt; 117 int result = 0; 118 119 clnt = rpc_create(&args); 120 if (IS_ERR(clnt)) { 121 dprintk("RPC: failed to create AF_LOCAL gssproxy " 122 "client (errno %ld).\n", PTR_ERR(clnt)); 123 result = PTR_ERR(clnt); 124 *_clnt = NULL; 125 goto out; 126 } 127 128 dprintk("RPC: created new gssp local client (gssp_local_clnt: " 129 "%p)\n", clnt); 130 *_clnt = clnt; 131 132 out: 133 return result; 134 } 135 136 void init_gssp_clnt(struct sunrpc_net *sn) 137 { 138 mutex_init(&sn->gssp_lock); 139 sn->gssp_clnt = NULL; 140 } 141 142 int set_gssp_clnt(struct net *net) 143 { 144 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 145 struct rpc_clnt *clnt; 146 int ret; 147 148 mutex_lock(&sn->gssp_lock); 149 ret = gssp_rpc_create(net, &clnt); 150 if (!ret) { 151 if (sn->gssp_clnt) 152 rpc_shutdown_client(sn->gssp_clnt); 153 sn->gssp_clnt = clnt; 154 } 155 mutex_unlock(&sn->gssp_lock); 156 return ret; 157 } 158 159 void clear_gssp_clnt(struct sunrpc_net *sn) 160 { 161 mutex_lock(&sn->gssp_lock); 162 if (sn->gssp_clnt) { 163 rpc_shutdown_client(sn->gssp_clnt); 164 sn->gssp_clnt = NULL; 165 } 166 mutex_unlock(&sn->gssp_lock); 167 } 168 169 static struct rpc_clnt *get_gssp_clnt(struct sunrpc_net *sn) 170 { 171 struct rpc_clnt *clnt; 172 173 mutex_lock(&sn->gssp_lock); 174 clnt = sn->gssp_clnt; 175 if (clnt) 176 atomic_inc(&clnt->cl_count); 177 mutex_unlock(&sn->gssp_lock); 178 return clnt; 179 } 180 181 static int gssp_call(struct net *net, struct rpc_message *msg) 182 { 183 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 184 struct rpc_clnt *clnt; 185 int status; 186 187 clnt = get_gssp_clnt(sn); 188 if (!clnt) 189 return -EIO; 190 status = rpc_call_sync(clnt, msg, 0); 191 if (status < 0) { 192 dprintk("gssp: rpc_call returned error %d\n", -status); 193 switch (status) { 194 case -EPROTONOSUPPORT: 195 status = -EINVAL; 196 break; 197 case -ECONNREFUSED: 198 case -ETIMEDOUT: 199 case -ENOTCONN: 200 status = -EAGAIN; 201 break; 202 case -ERESTARTSYS: 203 if (signalled ()) 204 status = -EINTR; 205 break; 206 default: 207 break; 208 } 209 } 210 rpc_release_client(clnt); 211 return status; 212 } 213 214 static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg) 215 { 216 int i; 217 218 for (i = 0; i < arg->npages && arg->pages[i]; i++) 219 __free_page(arg->pages[i]); 220 221 kfree(arg->pages); 222 } 223 224 static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) 225 { 226 arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE); 227 arg->pages = kcalloc(arg->npages, sizeof(struct page *), GFP_KERNEL); 228 /* 229 * XXX: actual pages are allocated by xdr layer in 230 * xdr_partial_copy_from_skb. 231 */ 232 if (!arg->pages) 233 return -ENOMEM; 234 return 0; 235 } 236 237 static char *gssp_stringify(struct xdr_netobj *netobj) 238 { 239 return kstrndup(netobj->data, netobj->len, GFP_KERNEL); 240 } 241 242 static void gssp_hostbased_service(char **principal) 243 { 244 char *c; 245 246 if (!*principal) 247 return; 248 249 /* terminate and remove realm part */ 250 c = strchr(*principal, '@'); 251 if (c) { 252 *c = '\0'; 253 254 /* change service-hostname delimiter */ 255 c = strchr(*principal, '/'); 256 if (c) 257 *c = '@'; 258 } 259 if (!c) { 260 /* not a service principal */ 261 kfree(*principal); 262 *principal = NULL; 263 } 264 } 265 266 /* 267 * Public functions 268 */ 269 270 /* numbers somewhat arbitrary but large enough for current needs */ 271 #define GSSX_MAX_OUT_HANDLE 128 272 #define GSSX_MAX_SRC_PRINC 256 273 #define GSSX_KMEMBUF (GSSX_max_output_handle_sz + \ 274 GSSX_max_oid_sz + \ 275 GSSX_max_princ_sz + \ 276 sizeof(struct svc_cred)) 277 278 int gssp_accept_sec_context_upcall(struct net *net, 279 struct gssp_upcall_data *data) 280 { 281 struct gssx_ctx ctxh = { 282 .state = data->in_handle 283 }; 284 struct gssx_arg_accept_sec_context arg = { 285 .input_token = data->in_token, 286 }; 287 struct gssx_ctx rctxh = { 288 /* 289 * pass in the max length we expect for each of these 290 * buffers but let the xdr code kmalloc them: 291 */ 292 .exported_context_token.len = GSSX_max_output_handle_sz, 293 .mech.len = GSS_OID_MAX_LEN, 294 .targ_name.display_name.len = GSSX_max_princ_sz, 295 .src_name.display_name.len = GSSX_max_princ_sz 296 }; 297 struct gssx_res_accept_sec_context res = { 298 .context_handle = &rctxh, 299 .output_token = &data->out_token 300 }; 301 struct rpc_message msg = { 302 .rpc_proc = &gssp_procedures[GSSX_ACCEPT_SEC_CONTEXT], 303 .rpc_argp = &arg, 304 .rpc_resp = &res, 305 .rpc_cred = NULL, /* FIXME ? */ 306 }; 307 struct xdr_netobj client_name = { 0 , NULL }; 308 struct xdr_netobj target_name = { 0, NULL }; 309 int ret; 310 311 if (data->in_handle.len != 0) 312 arg.context_handle = &ctxh; 313 res.output_token->len = GSSX_max_output_token_sz; 314 315 ret = gssp_alloc_receive_pages(&arg); 316 if (ret) 317 return ret; 318 319 ret = gssp_call(net, &msg); 320 321 gssp_free_receive_pages(&arg); 322 323 /* we need to fetch all data even in case of error so 324 * that we can free special strctures is they have been allocated */ 325 data->major_status = res.status.major_status; 326 data->minor_status = res.status.minor_status; 327 if (res.context_handle) { 328 data->out_handle = rctxh.exported_context_token; 329 data->mech_oid.len = rctxh.mech.len; 330 if (rctxh.mech.data) { 331 memcpy(data->mech_oid.data, rctxh.mech.data, 332 data->mech_oid.len); 333 kfree(rctxh.mech.data); 334 } 335 client_name = rctxh.src_name.display_name; 336 target_name = rctxh.targ_name.display_name; 337 } 338 339 if (res.options.count == 1) { 340 gssx_buffer *value = &res.options.data[0].value; 341 /* Currently we only decode CREDS_VALUE, if we add 342 * anything else we'll have to loop and match on the 343 * option name */ 344 if (value->len == 1) { 345 /* steal group info from struct svc_cred */ 346 data->creds = *(struct svc_cred *)value->data; 347 data->found_creds = 1; 348 } 349 /* whether we use it or not, free data */ 350 kfree(value->data); 351 } 352 353 if (res.options.count != 0) { 354 kfree(res.options.data); 355 } 356 357 /* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */ 358 if (data->found_creds) { 359 if (client_name.data) { 360 data->creds.cr_raw_principal = 361 gssp_stringify(&client_name); 362 data->creds.cr_principal = 363 gssp_stringify(&client_name); 364 gssp_hostbased_service(&data->creds.cr_principal); 365 } 366 if (target_name.data) { 367 data->creds.cr_targ_princ = 368 gssp_stringify(&target_name); 369 gssp_hostbased_service(&data->creds.cr_targ_princ); 370 } 371 } 372 kfree(client_name.data); 373 kfree(target_name.data); 374 375 return ret; 376 } 377 378 void gssp_free_upcall_data(struct gssp_upcall_data *data) 379 { 380 kfree(data->in_handle.data); 381 kfree(data->out_handle.data); 382 kfree(data->out_token.data); 383 free_svc_cred(&data->creds); 384 } 385 386 /* 387 * Initialization stuff 388 */ 389 static unsigned int gssp_version1_counts[ARRAY_SIZE(gssp_procedures)]; 390 static const struct rpc_version gssp_version1 = { 391 .number = GSSPROXY_VERS_1, 392 .nrprocs = ARRAY_SIZE(gssp_procedures), 393 .procs = gssp_procedures, 394 .counts = gssp_version1_counts, 395 }; 396 397 static const struct rpc_version *gssp_version[] = { 398 NULL, 399 &gssp_version1, 400 }; 401 402 static struct rpc_stat gssp_stats; 403 404 static const struct rpc_program gssp_program = { 405 .name = "gssproxy", 406 .number = GSSPROXY_PROGRAM, 407 .nrvers = ARRAY_SIZE(gssp_version), 408 .version = gssp_version, 409 .stats = &gssp_stats, 410 }; 411