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