1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 0 stevel * Common Development and Distribution License, Version 1.0 only 6 0 stevel * (the "License"). You may not use this file except in compliance 7 0 stevel * with the License. 8 0 stevel * 9 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 0 stevel * or http://www.opensolaris.org/os/licensing. 11 0 stevel * See the License for the specific language governing permissions 12 0 stevel * and limitations under the License. 13 0 stevel * 14 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 15 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 0 stevel * If applicable, add the following below this CDDL HEADER, with the 17 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 18 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 19 0 stevel * 20 0 stevel * CDDL HEADER END 21 0 stevel */ 22 0 stevel /* 23 0 stevel * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 28 0 stevel 29 0 stevel /* 30 0 stevel * Kernel code to obtain client handle to gssd server 31 0 stevel */ 32 0 stevel 33 0 stevel #include <sys/types.h> 34 0 stevel #include <gssapi/gssapi.h> 35 0 stevel #include <gssapi/gssd_prot.h> 36 0 stevel #include <gssapi/kgssapi_defs.h> 37 0 stevel 38 0 stevel #include <sys/systm.h> 39 0 stevel #include <sys/vnode.h> 40 0 stevel #include <sys/uio.h> 41 0 stevel #include <sys/pathname.h> 42 0 stevel #include <sys/utsname.h> 43 0 stevel 44 0 stevel #define GSSD_RETRY 5 45 0 stevel 46 0 stevel kmutex_t gssrpcb_lock; 47 0 stevel zone_key_t gss_zone_key; 48 0 stevel 49 0 stevel struct gss_globals { 50 0 stevel enum clnt_stat gss_last_stat; 51 0 stevel struct netbuf gss_netaddr; 52 0 stevel struct knetconfig gss_config; 53 0 stevel }; 54 0 stevel 55 0 stevel /* ARGSUSED */ 56 0 stevel void * 57 0 stevel gss_zone_init(zoneid_t zoneid) 58 0 stevel { 59 0 stevel struct gss_globals *gssg; 60 0 stevel 61 0 stevel gssg = kmem_zalloc(sizeof (*gssg), KM_SLEEP); 62 0 stevel return (gssg); 63 0 stevel } 64 0 stevel 65 0 stevel /* ARGSUSED */ 66 0 stevel void 67 0 stevel gss_zone_fini(zoneid_t zoneid, void *data) 68 0 stevel { 69 0 stevel struct gss_globals *gssg = data; 70 0 stevel struct netbuf *netaddrp = &gssg->gss_netaddr; 71 0 stevel 72 0 stevel if (netaddrp->len != 0) 73 0 stevel kmem_free(netaddrp->buf, netaddrp->maxlen); 74 0 stevel kmem_free(gssg, sizeof (*gssg)); 75 0 stevel } 76 0 stevel 77 0 stevel void 78 0 stevel killgssd_handle(CLIENT *client) 79 0 stevel { 80 0 stevel struct rpc_err rpcerr; 81 0 stevel struct gss_globals *gssg; 82 0 stevel 83 0 stevel gssg = zone_getspecific(gss_zone_key, curproc->p_zone); 84 0 stevel CLNT_GETERR(client, &rpcerr); 85 0 stevel gssg->gss_last_stat = rpcerr.re_status; 86 0 stevel 87 0 stevel AUTH_DESTROY(client->cl_auth); 88 0 stevel CLNT_DESTROY(client); 89 0 stevel } 90 0 stevel 91 0 stevel CLIENT * 92 0 stevel getgssd_handle(void) 93 0 stevel { 94 0 stevel struct vnode *vp; 95 0 stevel int error; 96 0 stevel CLIENT *clnt; 97 0 stevel char *gssname; 98 0 stevel enum clnt_stat stat; 99 0 stevel struct netbuf tmpaddr; 100 0 stevel struct gss_globals *gssg; 101 0 stevel struct netbuf *netaddrp; 102 0 stevel 103 0 stevel gssg = zone_getspecific(gss_zone_key, curproc->p_zone); 104 0 stevel /* 105 0 stevel * Cribbed from kerb_krpc.c. Really should do the config set up 106 0 stevel * in the _init routine. 107 0 stevel */ 108 0 stevel if (gssg->gss_config.knc_rdev == 0) { 109 0 stevel if ((error = lookupname("/dev/ticotsord", UIO_SYSSPACE, 110 0 stevel FOLLOW, NULLVPP, &vp)) != 0) { 111 0 stevel GSSLOG(1, "getgssd_handle: lookupname: %d\n", error); 112 0 stevel return (NULL); 113 0 stevel } 114 0 stevel gssg->gss_config.knc_rdev = vp->v_rdev; 115 0 stevel gssg->gss_config.knc_protofmly = loopback_name; 116 0 stevel VN_RELE(vp); 117 0 stevel gssg->gss_config.knc_semantics = NC_TPI_COTS_ORD; 118 0 stevel } 119 0 stevel 120 0 stevel /* 121 0 stevel * Contact rpcbind to get gssd's address only 122 0 stevel * once and re-use the address. 123 0 stevel */ 124 0 stevel mutex_enter(&gssrpcb_lock); 125 0 stevel netaddrp = &gssg->gss_netaddr; 126 0 stevel 127 0 stevel if (netaddrp->len == 0 || gssg->gss_last_stat != RPC_SUCCESS) { 128 0 stevel char *nodename = uts_nodename(); 129 0 stevel 130 0 stevel /* Set up netaddr to be <nodename>. */ 131 0 stevel netaddrp->len = strlen(nodename) + 1; 132 0 stevel if (netaddrp->buf != (char *)NULL) 133 0 stevel kmem_free(netaddrp->buf, netaddrp->maxlen); 134 0 stevel gssname = kmem_zalloc(netaddrp->len, KM_SLEEP); 135 0 stevel 136 0 stevel (void) strncpy(gssname, nodename, netaddrp->len - 1); 137 0 stevel 138 0 stevel /* Append "." to end of gssname */ 139 0 stevel (void) strncpy(gssname+(netaddrp->len-1), ".", 1); 140 0 stevel netaddrp->buf = gssname; 141 0 stevel netaddrp->maxlen = netaddrp->len; 142 0 stevel 143 0 stevel /* Get address of gssd from rpcbind */ 144 0 stevel stat = rpcbind_getaddr(&gssg->gss_config, GSSPROG, GSSVERS, 145 0 stevel netaddrp); 146 0 stevel if (stat != RPC_SUCCESS) { 147 0 stevel kmem_free(netaddrp->buf, netaddrp->maxlen); 148 0 stevel netaddrp->buf = (char *)NULL; 149 0 stevel netaddrp->len = netaddrp->maxlen = 0; 150 0 stevel mutex_exit(&gssrpcb_lock); 151 0 stevel return (NULL); 152 0 stevel } 153 0 stevel } 154 0 stevel 155 0 stevel /* 156 0 stevel * Copy the netaddr information into a tmp location to 157 0 stevel * be used by clnt_tli_kcreate. The purpose of this 158 0 stevel * is for MT race condition (ie. netaddr being modified 159 0 stevel * while it is being used.) 160 0 stevel */ 161 0 stevel tmpaddr.buf = kmem_zalloc(netaddrp->maxlen, KM_SLEEP); 162 0 stevel bcopy(netaddrp->buf, tmpaddr.buf, netaddrp->maxlen); 163 0 stevel tmpaddr.maxlen = netaddrp->maxlen; 164 0 stevel tmpaddr.len = netaddrp->len; 165 0 stevel 166 0 stevel mutex_exit(&gssrpcb_lock); 167 0 stevel 168 0 stevel error = clnt_tli_kcreate(&gssg->gss_config, &tmpaddr, GSSPROG, 169 0 stevel GSSVERS, 0, GSSD_RETRY, kcred, &clnt); 170 0 stevel 171 0 stevel kmem_free(tmpaddr.buf, tmpaddr.maxlen); 172 0 stevel 173 0 stevel if (error != 0) { 174 0 stevel GSSLOG(1, 175 0 stevel "getgssd_handle: clnt_tli_kcreate: error %d\n", error); 176 0 stevel return (NULL); 177 0 stevel } 178 0 stevel 179 0 stevel return (clnt); 180 0 stevel } 181