gssd.c revision 245016
1184588Sdfr/*- 2184588Sdfr * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3184588Sdfr * Authors: Doug Rabson <dfr@rabson.org> 4184588Sdfr * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 5184588Sdfr * 6184588Sdfr * Redistribution and use in source and binary forms, with or without 7184588Sdfr * modification, are permitted provided that the following conditions 8184588Sdfr * are met: 9184588Sdfr * 1. Redistributions of source code must retain the above copyright 10184588Sdfr * notice, this list of conditions and the following disclaimer. 11184588Sdfr * 2. Redistributions in binary form must reproduce the above copyright 12184588Sdfr * notice, this list of conditions and the following disclaimer in the 13184588Sdfr * documentation and/or other materials provided with the distribution. 14184588Sdfr * 15184588Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16184588Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17184588Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18184588Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19184588Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20184588Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21184588Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22184588Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23184588Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24184588Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25184588Sdfr * SUCH DAMAGE. 26184588Sdfr */ 27184588Sdfr 28184588Sdfr#include <sys/cdefs.h> 29184588Sdfr__FBSDID("$FreeBSD: stable/9/usr.sbin/gssd/gssd.c 245016 2013-01-03 23:09:16Z rmacklem $"); 30184588Sdfr 31184588Sdfr#include <sys/param.h> 32184588Sdfr#include <sys/stat.h> 33184588Sdfr#include <sys/linker.h> 34184588Sdfr#include <sys/module.h> 35184588Sdfr#include <sys/queue.h> 36245016Srmacklem#include <sys/syslog.h> 37184588Sdfr#include <ctype.h> 38184588Sdfr#include <err.h> 39184588Sdfr#include <pwd.h> 40184588Sdfr#include <stdio.h> 41184588Sdfr#include <stdlib.h> 42184588Sdfr#include <string.h> 43184588Sdfr#include <unistd.h> 44184588Sdfr#include <gssapi/gssapi.h> 45184588Sdfr#include <rpc/rpc.h> 46184588Sdfr#include <rpc/rpc_com.h> 47184588Sdfr 48184588Sdfr#include "gssd.h" 49184588Sdfr 50184588Sdfr#ifndef _PATH_GSS_MECH 51184588Sdfr#define _PATH_GSS_MECH "/etc/gss/mech" 52184588Sdfr#endif 53184588Sdfr#ifndef _PATH_GSSDSOCK 54184588Sdfr#define _PATH_GSSDSOCK "/var/run/gssd.sock" 55184588Sdfr#endif 56184588Sdfr 57184588Sdfrstruct gss_resource { 58184588Sdfr LIST_ENTRY(gss_resource) gr_link; 59184588Sdfr uint64_t gr_id; /* indentifier exported to kernel */ 60184588Sdfr void* gr_res; /* GSS-API resource pointer */ 61184588Sdfr}; 62184588SdfrLIST_HEAD(gss_resource_list, gss_resource) gss_resources; 63184588Sdfrint gss_resource_count; 64184588Sdfruint32_t gss_next_id; 65184588Sdfruint32_t gss_start_time; 66184588Sdfrint debug_level; 67184588Sdfr 68184588Sdfrstatic void gssd_load_mech(void); 69184588Sdfr 70184588Sdfrextern void gssd_1(struct svc_req *rqstp, SVCXPRT *transp); 71184588Sdfrextern int gssd_syscall(char *path); 72184588Sdfr 73184588Sdfrint 74184588Sdfrmain(int argc, char **argv) 75184588Sdfr{ 76184588Sdfr /* 77184588Sdfr * We provide an RPC service on a local-domain socket. The 78184588Sdfr * kernel's GSS-API code will pass what it can't handle 79184588Sdfr * directly to us. 80184588Sdfr */ 81184588Sdfr struct sockaddr_un sun; 82184588Sdfr int fd, oldmask, ch, debug; 83184588Sdfr SVCXPRT *xprt; 84184588Sdfr 85184588Sdfr debug = 0; 86184588Sdfr while ((ch = getopt(argc, argv, "d")) != -1) { 87184588Sdfr switch (ch) { 88184588Sdfr case 'd': 89184588Sdfr debug_level++; 90184588Sdfr break; 91184588Sdfr default: 92184588Sdfr fprintf(stderr, "usage: %s [-d]\n", argv[0]); 93184588Sdfr exit(1); 94184588Sdfr break; 95184588Sdfr } 96184588Sdfr } 97184588Sdfr 98184588Sdfr gssd_load_mech(); 99184588Sdfr 100184588Sdfr if (!debug_level) 101184588Sdfr daemon(0, 0); 102184588Sdfr 103184588Sdfr memset(&sun, 0, sizeof sun); 104184588Sdfr sun.sun_family = AF_LOCAL; 105184588Sdfr unlink(_PATH_GSSDSOCK); 106184588Sdfr strcpy(sun.sun_path, _PATH_GSSDSOCK); 107184588Sdfr sun.sun_len = SUN_LEN(&sun); 108184588Sdfr fd = socket(AF_LOCAL, SOCK_STREAM, 0); 109184588Sdfr if (!fd) { 110245016Srmacklem if (debug_level == 0) { 111245016Srmacklem syslog(LOG_ERR, "Can't create local gssd socket"); 112245016Srmacklem exit(1); 113245016Srmacklem } 114184588Sdfr err(1, "Can't create local gssd socket"); 115184588Sdfr } 116184588Sdfr oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO); 117184588Sdfr if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) { 118245016Srmacklem if (debug_level == 0) { 119245016Srmacklem syslog(LOG_ERR, "Can't bind local gssd socket"); 120245016Srmacklem exit(1); 121245016Srmacklem } 122184588Sdfr err(1, "Can't bind local gssd socket"); 123184588Sdfr } 124184588Sdfr umask(oldmask); 125184588Sdfr if (listen(fd, SOMAXCONN) < 0) { 126245016Srmacklem if (debug_level == 0) { 127245016Srmacklem syslog(LOG_ERR, "Can't listen on local gssd socket"); 128245016Srmacklem exit(1); 129245016Srmacklem } 130184588Sdfr err(1, "Can't listen on local gssd socket"); 131184588Sdfr } 132184588Sdfr xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE); 133184588Sdfr if (!xprt) { 134245016Srmacklem if (debug_level == 0) { 135245016Srmacklem syslog(LOG_ERR, 136245016Srmacklem "Can't create transport for local gssd socket"); 137245016Srmacklem exit(1); 138245016Srmacklem } 139184588Sdfr err(1, "Can't create transport for local gssd socket"); 140184588Sdfr } 141184588Sdfr if (!svc_reg(xprt, GSSD, GSSDVERS, gssd_1, NULL)) { 142245016Srmacklem if (debug_level == 0) { 143245016Srmacklem syslog(LOG_ERR, 144245016Srmacklem "Can't register service for local gssd socket"); 145245016Srmacklem exit(1); 146245016Srmacklem } 147184588Sdfr err(1, "Can't register service for local gssd socket"); 148184588Sdfr } 149184588Sdfr 150184588Sdfr LIST_INIT(&gss_resources); 151184588Sdfr gss_next_id = 1; 152184588Sdfr gss_start_time = time(0); 153184588Sdfr 154184588Sdfr gssd_syscall(_PATH_GSSDSOCK); 155184588Sdfr svc_run(); 156184588Sdfr 157184588Sdfr return (0); 158184588Sdfr} 159184588Sdfr 160184588Sdfrstatic void 161184588Sdfrgssd_load_mech(void) 162184588Sdfr{ 163184588Sdfr FILE *fp; 164184588Sdfr char buf[256]; 165184588Sdfr char *p; 166184588Sdfr char *name, *oid, *lib, *kobj; 167184588Sdfr 168184588Sdfr fp = fopen(_PATH_GSS_MECH, "r"); 169184588Sdfr if (!fp) 170184588Sdfr return; 171184588Sdfr 172184588Sdfr while (fgets(buf, sizeof(buf), fp)) { 173184588Sdfr if (*buf == '#') 174184588Sdfr continue; 175184588Sdfr p = buf; 176184588Sdfr name = strsep(&p, "\t\n "); 177184588Sdfr if (p) while (isspace(*p)) p++; 178184588Sdfr oid = strsep(&p, "\t\n "); 179184588Sdfr if (p) while (isspace(*p)) p++; 180184588Sdfr lib = strsep(&p, "\t\n "); 181184588Sdfr if (p) while (isspace(*p)) p++; 182184588Sdfr kobj = strsep(&p, "\t\n "); 183184588Sdfr if (!name || !oid || !lib || !kobj) 184184588Sdfr continue; 185184588Sdfr 186184588Sdfr if (strcmp(kobj, "-")) { 187184588Sdfr /* 188184588Sdfr * Attempt to load the kernel module if its 189184588Sdfr * not already present. 190184588Sdfr */ 191184588Sdfr if (modfind(kobj) < 0) { 192184588Sdfr if (kldload(kobj) < 0) { 193184588Sdfr fprintf(stderr, 194184588Sdfr "%s: can't find or load kernel module %s for %s\n", 195184588Sdfr getprogname(), kobj, name); 196184588Sdfr } 197184588Sdfr } 198184588Sdfr } 199184588Sdfr } 200184588Sdfr fclose(fp); 201184588Sdfr} 202184588Sdfr 203184588Sdfrstatic void * 204184588Sdfrgssd_find_resource(uint64_t id) 205184588Sdfr{ 206184588Sdfr struct gss_resource *gr; 207184588Sdfr 208184588Sdfr if (!id) 209184588Sdfr return (NULL); 210184588Sdfr 211184588Sdfr LIST_FOREACH(gr, &gss_resources, gr_link) 212184588Sdfr if (gr->gr_id == id) 213184588Sdfr return (gr->gr_res); 214184588Sdfr 215184588Sdfr return (NULL); 216184588Sdfr} 217184588Sdfr 218184588Sdfrstatic uint64_t 219184588Sdfrgssd_make_resource(void *res) 220184588Sdfr{ 221184588Sdfr struct gss_resource *gr; 222184588Sdfr 223184588Sdfr if (!res) 224184588Sdfr return (0); 225184588Sdfr 226184588Sdfr gr = malloc(sizeof(struct gss_resource)); 227184588Sdfr if (!gr) 228184588Sdfr return (0); 229184588Sdfr gr->gr_id = (gss_next_id++) + ((uint64_t) gss_start_time << 32); 230184588Sdfr gr->gr_res = res; 231184588Sdfr LIST_INSERT_HEAD(&gss_resources, gr, gr_link); 232184588Sdfr gss_resource_count++; 233184588Sdfr if (debug_level > 1) 234184588Sdfr printf("%d resources allocated\n", gss_resource_count); 235184588Sdfr 236184588Sdfr return (gr->gr_id); 237184588Sdfr} 238184588Sdfr 239184588Sdfrstatic void 240184588Sdfrgssd_delete_resource(uint64_t id) 241184588Sdfr{ 242184588Sdfr struct gss_resource *gr; 243184588Sdfr 244184588Sdfr LIST_FOREACH(gr, &gss_resources, gr_link) { 245184588Sdfr if (gr->gr_id == id) { 246184588Sdfr LIST_REMOVE(gr, gr_link); 247184588Sdfr free(gr); 248184588Sdfr gss_resource_count--; 249184588Sdfr if (debug_level > 1) 250184588Sdfr printf("%d resources allocated\n", 251184588Sdfr gss_resource_count); 252184588Sdfr return; 253184588Sdfr } 254184588Sdfr } 255184588Sdfr} 256184588Sdfr 257184588Sdfrbool_t 258184588Sdfrgssd_null_1_svc(void *argp, void *result, struct svc_req *rqstp) 259184588Sdfr{ 260184588Sdfr 261184588Sdfr return (TRUE); 262184588Sdfr} 263184588Sdfr 264184588Sdfrbool_t 265184588Sdfrgssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *result, struct svc_req *rqstp) 266184588Sdfr{ 267184588Sdfr gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 268184588Sdfr gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 269184588Sdfr gss_name_t name = GSS_C_NO_NAME; 270184588Sdfr char ccname[strlen("FILE:/tmp/krb5cc_") + 6 + 1]; 271184588Sdfr 272184588Sdfr snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%d", 273184588Sdfr (int) argp->uid); 274184588Sdfr setenv("KRB5CCNAME", ccname, TRUE); 275184588Sdfr 276184588Sdfr memset(result, 0, sizeof(*result)); 277184588Sdfr if (argp->cred) { 278184588Sdfr cred = gssd_find_resource(argp->cred); 279184588Sdfr if (!cred) { 280184588Sdfr result->major_status = GSS_S_CREDENTIALS_EXPIRED; 281184588Sdfr return (TRUE); 282184588Sdfr } 283184588Sdfr } 284184588Sdfr if (argp->ctx) { 285184588Sdfr ctx = gssd_find_resource(argp->ctx); 286184588Sdfr if (!ctx) { 287184588Sdfr result->major_status = GSS_S_CONTEXT_EXPIRED; 288184588Sdfr return (TRUE); 289184588Sdfr } 290184588Sdfr } 291184588Sdfr if (argp->name) { 292184588Sdfr name = gssd_find_resource(argp->name); 293184588Sdfr if (!name) { 294184588Sdfr result->major_status = GSS_S_BAD_NAME; 295184588Sdfr return (TRUE); 296184588Sdfr } 297184588Sdfr } 298184588Sdfr 299184588Sdfr memset(result, 0, sizeof(*result)); 300184588Sdfr result->major_status = gss_init_sec_context(&result->minor_status, 301184588Sdfr cred, &ctx, name, argp->mech_type, 302184588Sdfr argp->req_flags, argp->time_req, argp->input_chan_bindings, 303184588Sdfr &argp->input_token, &result->actual_mech_type, 304184588Sdfr &result->output_token, &result->ret_flags, &result->time_rec); 305184588Sdfr 306184588Sdfr if (result->major_status == GSS_S_COMPLETE 307184588Sdfr || result->major_status == GSS_S_CONTINUE_NEEDED) { 308184588Sdfr if (argp->ctx) 309184588Sdfr result->ctx = argp->ctx; 310184588Sdfr else 311184588Sdfr result->ctx = gssd_make_resource(ctx); 312184588Sdfr } 313184588Sdfr 314184588Sdfr return (TRUE); 315184588Sdfr} 316184588Sdfr 317184588Sdfrbool_t 318184588Sdfrgssd_accept_sec_context_1_svc(accept_sec_context_args *argp, accept_sec_context_res *result, struct svc_req *rqstp) 319184588Sdfr{ 320184588Sdfr gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 321184588Sdfr gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 322184588Sdfr gss_name_t src_name; 323184588Sdfr gss_cred_id_t delegated_cred_handle; 324184588Sdfr 325184588Sdfr memset(result, 0, sizeof(*result)); 326184588Sdfr if (argp->ctx) { 327184588Sdfr ctx = gssd_find_resource(argp->ctx); 328184588Sdfr if (!ctx) { 329184588Sdfr result->major_status = GSS_S_CONTEXT_EXPIRED; 330184588Sdfr return (TRUE); 331184588Sdfr } 332184588Sdfr } 333184588Sdfr if (argp->cred) { 334184588Sdfr cred = gssd_find_resource(argp->cred); 335184588Sdfr if (!cred) { 336184588Sdfr result->major_status = GSS_S_CREDENTIALS_EXPIRED; 337184588Sdfr return (TRUE); 338184588Sdfr } 339184588Sdfr } 340184588Sdfr 341184588Sdfr memset(result, 0, sizeof(*result)); 342184588Sdfr result->major_status = gss_accept_sec_context(&result->minor_status, 343184588Sdfr &ctx, cred, &argp->input_token, argp->input_chan_bindings, 344184588Sdfr &src_name, &result->mech_type, &result->output_token, 345184588Sdfr &result->ret_flags, &result->time_rec, 346184588Sdfr &delegated_cred_handle); 347184588Sdfr 348184588Sdfr if (result->major_status == GSS_S_COMPLETE 349184588Sdfr || result->major_status == GSS_S_CONTINUE_NEEDED) { 350184588Sdfr if (argp->ctx) 351184588Sdfr result->ctx = argp->ctx; 352184588Sdfr else 353184588Sdfr result->ctx = gssd_make_resource(ctx); 354184588Sdfr result->src_name = gssd_make_resource(src_name); 355184588Sdfr result->delegated_cred_handle = 356184588Sdfr gssd_make_resource(delegated_cred_handle); 357184588Sdfr } 358184588Sdfr 359184588Sdfr return (TRUE); 360184588Sdfr} 361184588Sdfr 362184588Sdfrbool_t 363184588Sdfrgssd_delete_sec_context_1_svc(delete_sec_context_args *argp, delete_sec_context_res *result, struct svc_req *rqstp) 364184588Sdfr{ 365184588Sdfr gss_ctx_id_t ctx = gssd_find_resource(argp->ctx); 366184588Sdfr 367184588Sdfr if (ctx) { 368184588Sdfr result->major_status = gss_delete_sec_context( 369184588Sdfr &result->minor_status, &ctx, &result->output_token); 370184588Sdfr gssd_delete_resource(argp->ctx); 371184588Sdfr } else { 372184588Sdfr result->major_status = GSS_S_COMPLETE; 373184588Sdfr result->minor_status = 0; 374184588Sdfr } 375184588Sdfr 376184588Sdfr return (TRUE); 377184588Sdfr} 378184588Sdfr 379184588Sdfrbool_t 380184588Sdfrgssd_export_sec_context_1_svc(export_sec_context_args *argp, export_sec_context_res *result, struct svc_req *rqstp) 381184588Sdfr{ 382184588Sdfr gss_ctx_id_t ctx = gssd_find_resource(argp->ctx); 383184588Sdfr 384184588Sdfr if (ctx) { 385184588Sdfr result->major_status = gss_export_sec_context( 386184588Sdfr &result->minor_status, &ctx, 387184588Sdfr &result->interprocess_token); 388184588Sdfr result->format = KGSS_HEIMDAL_1_1; 389184588Sdfr gssd_delete_resource(argp->ctx); 390184588Sdfr } else { 391184588Sdfr result->major_status = GSS_S_FAILURE; 392184588Sdfr result->minor_status = 0; 393184588Sdfr result->interprocess_token.length = 0; 394184588Sdfr result->interprocess_token.value = NULL; 395184588Sdfr } 396184588Sdfr 397184588Sdfr return (TRUE); 398184588Sdfr} 399184588Sdfr 400184588Sdfrbool_t 401184588Sdfrgssd_import_name_1_svc(import_name_args *argp, import_name_res *result, struct svc_req *rqstp) 402184588Sdfr{ 403184588Sdfr gss_name_t name; 404184588Sdfr 405184588Sdfr result->major_status = gss_import_name(&result->minor_status, 406184588Sdfr &argp->input_name_buffer, argp->input_name_type, &name); 407184588Sdfr 408184588Sdfr if (result->major_status == GSS_S_COMPLETE) 409184588Sdfr result->output_name = gssd_make_resource(name); 410184588Sdfr else 411184588Sdfr result->output_name = 0; 412184588Sdfr 413184588Sdfr return (TRUE); 414184588Sdfr} 415184588Sdfr 416184588Sdfrbool_t 417184588Sdfrgssd_canonicalize_name_1_svc(canonicalize_name_args *argp, canonicalize_name_res *result, struct svc_req *rqstp) 418184588Sdfr{ 419184588Sdfr gss_name_t name = gssd_find_resource(argp->input_name); 420184588Sdfr gss_name_t output_name; 421184588Sdfr 422184588Sdfr memset(result, 0, sizeof(*result)); 423184588Sdfr if (!name) { 424184588Sdfr result->major_status = GSS_S_BAD_NAME; 425184588Sdfr return (TRUE); 426184588Sdfr } 427184588Sdfr 428184588Sdfr result->major_status = gss_canonicalize_name(&result->minor_status, 429184588Sdfr name, argp->mech_type, &output_name); 430184588Sdfr 431184588Sdfr if (result->major_status == GSS_S_COMPLETE) 432184588Sdfr result->output_name = gssd_make_resource(output_name); 433184588Sdfr else 434184588Sdfr result->output_name = 0; 435184588Sdfr 436184588Sdfr return (TRUE); 437184588Sdfr} 438184588Sdfr 439184588Sdfrbool_t 440184588Sdfrgssd_export_name_1_svc(export_name_args *argp, export_name_res *result, struct svc_req *rqstp) 441184588Sdfr{ 442184588Sdfr gss_name_t name = gssd_find_resource(argp->input_name); 443184588Sdfr 444184588Sdfr memset(result, 0, sizeof(*result)); 445184588Sdfr if (!name) { 446184588Sdfr result->major_status = GSS_S_BAD_NAME; 447184588Sdfr return (TRUE); 448184588Sdfr } 449184588Sdfr 450184588Sdfr result->major_status = gss_export_name(&result->minor_status, 451184588Sdfr name, &result->exported_name); 452184588Sdfr 453184588Sdfr return (TRUE); 454184588Sdfr} 455184588Sdfr 456184588Sdfrbool_t 457184588Sdfrgssd_release_name_1_svc(release_name_args *argp, release_name_res *result, struct svc_req *rqstp) 458184588Sdfr{ 459184588Sdfr gss_name_t name = gssd_find_resource(argp->input_name); 460184588Sdfr 461184588Sdfr if (name) { 462184588Sdfr result->major_status = gss_release_name(&result->minor_status, 463184588Sdfr &name); 464184588Sdfr gssd_delete_resource(argp->input_name); 465184588Sdfr } else { 466184588Sdfr result->major_status = GSS_S_COMPLETE; 467184588Sdfr result->minor_status = 0; 468184588Sdfr } 469184588Sdfr 470184588Sdfr return (TRUE); 471184588Sdfr} 472184588Sdfr 473184588Sdfrbool_t 474184588Sdfrgssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struct svc_req *rqstp) 475184588Sdfr{ 476184588Sdfr gss_name_t name = gssd_find_resource(argp->pname); 477184588Sdfr uid_t uid; 478184588Sdfr char buf[128]; 479184588Sdfr struct passwd pwd, *pw; 480184588Sdfr 481184588Sdfr memset(result, 0, sizeof(*result)); 482184588Sdfr if (name) { 483184588Sdfr result->major_status = 484184588Sdfr gss_pname_to_uid(&result->minor_status, 485184588Sdfr name, argp->mech, &uid); 486184588Sdfr if (result->major_status == GSS_S_COMPLETE) { 487184588Sdfr result->uid = uid; 488184588Sdfr getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw); 489184588Sdfr if (pw) { 490184588Sdfr int len = NGRPS; 491184588Sdfr int groups[NGRPS]; 492184588Sdfr result->gid = pw->pw_gid; 493184588Sdfr getgrouplist(pw->pw_name, pw->pw_gid, 494184588Sdfr groups, &len); 495184588Sdfr result->gidlist.gidlist_len = len; 496184588Sdfr result->gidlist.gidlist_val = 497184588Sdfr mem_alloc(len * sizeof(int)); 498184588Sdfr memcpy(result->gidlist.gidlist_val, groups, 499184588Sdfr len * sizeof(int)); 500184588Sdfr } else { 501184588Sdfr result->gid = 65534; 502184588Sdfr result->gidlist.gidlist_len = 0; 503184588Sdfr result->gidlist.gidlist_val = NULL; 504184588Sdfr } 505184588Sdfr } 506184588Sdfr } else { 507184588Sdfr result->major_status = GSS_S_BAD_NAME; 508184588Sdfr result->minor_status = 0; 509184588Sdfr } 510184588Sdfr 511184588Sdfr return (TRUE); 512184588Sdfr} 513184588Sdfr 514184588Sdfrbool_t 515184588Sdfrgssd_acquire_cred_1_svc(acquire_cred_args *argp, acquire_cred_res *result, struct svc_req *rqstp) 516184588Sdfr{ 517184588Sdfr gss_name_t desired_name = GSS_C_NO_NAME; 518184588Sdfr gss_cred_id_t cred; 519184588Sdfr char ccname[strlen("FILE:/tmp/krb5cc_") + 6 + 1]; 520184588Sdfr 521184588Sdfr snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%d", 522184588Sdfr (int) argp->uid); 523184588Sdfr setenv("KRB5CCNAME", ccname, TRUE); 524184588Sdfr 525184588Sdfr memset(result, 0, sizeof(*result)); 526184588Sdfr if (argp->desired_name) { 527184588Sdfr desired_name = gssd_find_resource(argp->desired_name); 528184588Sdfr if (!desired_name) { 529184588Sdfr result->major_status = GSS_S_BAD_NAME; 530184588Sdfr return (TRUE); 531184588Sdfr } 532184588Sdfr } 533184588Sdfr 534184588Sdfr result->major_status = gss_acquire_cred(&result->minor_status, 535184588Sdfr desired_name, argp->time_req, argp->desired_mechs, 536184588Sdfr argp->cred_usage, &cred, &result->actual_mechs, &result->time_rec); 537184588Sdfr 538184588Sdfr if (result->major_status == GSS_S_COMPLETE) 539184588Sdfr result->output_cred = gssd_make_resource(cred); 540184588Sdfr else 541184588Sdfr result->output_cred = 0; 542184588Sdfr 543184588Sdfr return (TRUE); 544184588Sdfr} 545184588Sdfr 546184588Sdfrbool_t 547184588Sdfrgssd_set_cred_option_1_svc(set_cred_option_args *argp, set_cred_option_res *result, struct svc_req *rqstp) 548184588Sdfr{ 549184588Sdfr gss_cred_id_t cred = gssd_find_resource(argp->cred); 550184588Sdfr 551184588Sdfr memset(result, 0, sizeof(*result)); 552184588Sdfr if (!cred) { 553184588Sdfr result->major_status = GSS_S_CREDENTIALS_EXPIRED; 554184588Sdfr return (TRUE); 555184588Sdfr } 556184588Sdfr 557184588Sdfr result->major_status = gss_set_cred_option(&result->minor_status, 558184588Sdfr &cred, argp->option_name, &argp->option_value); 559184588Sdfr 560184588Sdfr return (TRUE); 561184588Sdfr} 562184588Sdfr 563184588Sdfrbool_t 564184588Sdfrgssd_release_cred_1_svc(release_cred_args *argp, release_cred_res *result, struct svc_req *rqstp) 565184588Sdfr{ 566184588Sdfr gss_cred_id_t cred = gssd_find_resource(argp->cred); 567184588Sdfr 568184588Sdfr if (cred) { 569184588Sdfr result->major_status = gss_release_cred(&result->minor_status, 570184588Sdfr &cred); 571184588Sdfr gssd_delete_resource(argp->cred); 572184588Sdfr } else { 573184588Sdfr result->major_status = GSS_S_COMPLETE; 574184588Sdfr result->minor_status = 0; 575184588Sdfr } 576184588Sdfr 577184588Sdfr return (TRUE); 578184588Sdfr} 579184588Sdfr 580184588Sdfrbool_t 581184588Sdfrgssd_display_status_1_svc(display_status_args *argp, display_status_res *result, struct svc_req *rqstp) 582184588Sdfr{ 583184588Sdfr 584184588Sdfr result->message_context = argp->message_context; 585184588Sdfr result->major_status = gss_display_status(&result->minor_status, 586184588Sdfr argp->status_value, argp->status_type, argp->mech_type, 587184588Sdfr &result->message_context, &result->status_string); 588184588Sdfr 589184588Sdfr return (TRUE); 590184588Sdfr} 591184588Sdfr 592184588Sdfrint 593184588Sdfrgssd_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) 594184588Sdfr{ 595184588Sdfr /* 596184588Sdfr * We don't use XDR to free the results - anything which was 597184588Sdfr * allocated came from GSS-API. We use xdr_result to figure 598184588Sdfr * out what to do. 599184588Sdfr */ 600184588Sdfr OM_uint32 junk; 601184588Sdfr 602184588Sdfr if (xdr_result == (xdrproc_t) xdr_init_sec_context_res) { 603184588Sdfr init_sec_context_res *p = (init_sec_context_res *) result; 604184588Sdfr gss_release_buffer(&junk, &p->output_token); 605184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_accept_sec_context_res) { 606184588Sdfr accept_sec_context_res *p = (accept_sec_context_res *) result; 607184588Sdfr gss_release_buffer(&junk, &p->output_token); 608184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_delete_sec_context_res) { 609184588Sdfr delete_sec_context_res *p = (delete_sec_context_res *) result; 610184588Sdfr gss_release_buffer(&junk, &p->output_token); 611184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_export_sec_context_res) { 612184588Sdfr export_sec_context_res *p = (export_sec_context_res *) result; 613184588Sdfr if (p->interprocess_token.length) 614184588Sdfr memset(p->interprocess_token.value, 0, 615184588Sdfr p->interprocess_token.length); 616184588Sdfr gss_release_buffer(&junk, &p->interprocess_token); 617184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_export_name_res) { 618184588Sdfr export_name_res *p = (export_name_res *) result; 619184588Sdfr gss_release_buffer(&junk, &p->exported_name); 620184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_acquire_cred_res) { 621184588Sdfr acquire_cred_res *p = (acquire_cred_res *) result; 622184588Sdfr gss_release_oid_set(&junk, &p->actual_mechs); 623184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_pname_to_uid_res) { 624184588Sdfr pname_to_uid_res *p = (pname_to_uid_res *) result; 625184588Sdfr if (p->gidlist.gidlist_val) 626184588Sdfr free(p->gidlist.gidlist_val); 627184588Sdfr } else if (xdr_result == (xdrproc_t) xdr_display_status_res) { 628184588Sdfr display_status_res *p = (display_status_res *) result; 629184588Sdfr gss_release_buffer(&junk, &p->status_string); 630184588Sdfr } 631184588Sdfr 632184588Sdfr return (TRUE); 633184588Sdfr} 634