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 1986-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 #include "mt.h" 30 #include "rpc_mt.h" 31 #include <stdio.h> 32 #include <sys/errno.h> 33 #include <dlfcn.h> 34 #include <rpc/rpc.h> 35 36 #define RPCSEC "rpcsec.so.1" 37 38 typedef struct { 39 AUTH *(*rpc_gss_seccreate)(); 40 bool_t (*rpc_gss_set_defaults)(); 41 bool_t (*rpc_gss_get_principal_name)(); 42 char **(*rpc_gss_get_mechanisms)(); 43 char **(*rpc_gss_get_mech_info)(); 44 bool_t (*rpc_gss_get_versions)(); 45 bool_t (*rpc_gss_is_installed)(); 46 bool_t (*rpc_gss_set_svc_name)(); 47 bool_t (*rpc_gss_set_callback)(); 48 bool_t (*rpc_gss_getcred)(); 49 bool_t (*rpc_gss_mech_to_oid)(); 50 bool_t (*rpc_gss_qop_to_num)(); 51 enum auth_stat (*__svcrpcsec_gss)(); 52 bool_t (*__rpc_gss_wrap)(); 53 bool_t (*__rpc_gss_unwrap)(); 54 int (*rpc_gss_max_data_length)(); 55 int (*rpc_gss_svc_max_data_length)(); 56 void (*rpc_gss_get_error)(); 57 } rpcgss_calls_t; 58 59 static rpcgss_calls_t calls; 60 static mutex_t rpcgss_calls_mutex = DEFAULTMUTEX; 61 static bool_t initialized = FALSE; 62 63 static bool_t 64 rpcgss_calls_init() 65 { 66 void *handle = NULL; 67 bool_t ret = FALSE; 68 69 mutex_lock(&rpcgss_calls_mutex); 70 if (initialized) { 71 ret = TRUE; 72 goto done; 73 } 74 75 if ((handle = dlopen(RPCSEC, RTLD_LAZY)) == NULL) 76 goto done; 77 78 if ((calls.rpc_gss_seccreate = (AUTH *(*)()) dlsym(handle, 79 "__rpc_gss_seccreate")) == NULL) 80 goto done; 81 if ((calls.rpc_gss_set_defaults = (bool_t (*)()) dlsym(handle, 82 "__rpc_gss_set_defaults")) == NULL) 83 goto done; 84 if ((calls.rpc_gss_get_principal_name = (bool_t (*)()) dlsym(handle, 85 "__rpc_gss_get_principal_name")) == NULL) 86 goto done; 87 if ((calls.rpc_gss_get_mechanisms = (char **(*)()) dlsym(handle, 88 "__rpc_gss_get_mechanisms")) == NULL) 89 goto done; 90 if ((calls.rpc_gss_get_mech_info = (char **(*)()) dlsym(handle, 91 "__rpc_gss_get_mech_info")) == NULL) 92 goto done; 93 if ((calls.rpc_gss_get_versions = (bool_t (*)()) dlsym(handle, 94 "__rpc_gss_get_versions")) == NULL) 95 goto done; 96 if ((calls.rpc_gss_is_installed = (bool_t (*)()) dlsym(handle, 97 "__rpc_gss_is_installed")) == NULL) 98 goto done; 99 if ((calls.rpc_gss_set_svc_name = (bool_t (*)()) dlsym(handle, 100 "__rpc_gss_set_svc_name")) == NULL) 101 goto done; 102 if ((calls.rpc_gss_set_callback = (bool_t (*)()) dlsym(handle, 103 "__rpc_gss_set_callback")) == NULL) 104 goto done; 105 if ((calls.rpc_gss_getcred = (bool_t (*)()) dlsym(handle, 106 "__rpc_gss_getcred")) == NULL) 107 goto done; 108 if ((calls.rpc_gss_mech_to_oid = (bool_t (*)()) dlsym(handle, 109 "__rpc_gss_mech_to_oid")) == NULL) 110 goto done; 111 112 if ((calls.rpc_gss_qop_to_num = (bool_t (*)()) dlsym(handle, 113 "__rpc_gss_qop_to_num")) == NULL) 114 goto done; 115 if ((calls.__svcrpcsec_gss = (enum auth_stat (*)()) dlsym(handle, 116 "__svcrpcsec_gss")) == NULL) 117 goto done; 118 if ((calls.__rpc_gss_wrap = (bool_t (*)()) dlsym(handle, 119 "__rpc_gss_wrap")) == NULL) 120 goto done; 121 if ((calls.__rpc_gss_unwrap = (bool_t (*)()) dlsym(handle, 122 "__rpc_gss_unwrap")) == NULL) 123 goto done; 124 if ((calls.rpc_gss_max_data_length = (int (*)()) dlsym(handle, 125 "__rpc_gss_max_data_length")) == NULL) 126 goto done; 127 if ((calls.rpc_gss_svc_max_data_length = (int (*)()) dlsym(handle, 128 "__rpc_gss_svc_max_data_length")) == NULL) 129 goto done; 130 if ((calls.rpc_gss_get_error = (void (*)()) dlsym(handle, 131 "__rpc_gss_get_error")) == NULL) 132 goto done; 133 ret = TRUE; 134 done: 135 if (!ret) { 136 if (handle != NULL) 137 dlclose(handle); 138 } 139 initialized = ret; 140 mutex_unlock(&rpcgss_calls_mutex); 141 return (ret); 142 } 143 144 AUTH * 145 rpc_gss_seccreate( 146 CLIENT *clnt, /* associated client handle */ 147 char *principal, /* server service principal */ 148 char *mechanism, /* security mechanism */ 149 rpc_gss_service_t service_type, /* security service */ 150 char *qop, /* requested QOP */ 151 rpc_gss_options_req_t *options_req, /* requested options */ 152 rpc_gss_options_ret_t *options_ret) /* returned options */ 153 { 154 if (!initialized && !rpcgss_calls_init()) 155 return ((AUTH *)NULL); 156 return ((*calls.rpc_gss_seccreate)(clnt, principal, mechanism, 157 service_type, qop, options_req, options_ret)); 158 } 159 160 bool_t 161 rpc_gss_set_defaults(auth, service, qop) 162 AUTH *auth; 163 rpc_gss_service_t service; 164 char *qop; 165 { 166 if (!initialized && !rpcgss_calls_init()) 167 return (FALSE); 168 return ((*calls.rpc_gss_set_defaults)(auth, service, qop)); 169 } 170 171 bool_t 172 rpc_gss_get_principal_name( 173 rpc_gss_principal_t *principal, 174 char *mechanism, 175 char *user_name, 176 char *node, 177 char *secdomain) 178 { 179 if (!initialized && !rpcgss_calls_init()) 180 return (FALSE); 181 return ((*calls.rpc_gss_get_principal_name)(principal, mechanism, 182 user_name, node, secdomain)); 183 } 184 185 char ** 186 rpc_gss_get_mechanisms() 187 { 188 if (!initialized && !rpcgss_calls_init()) 189 return ((char **)NULL); 190 return ((*calls.rpc_gss_get_mechanisms)()); 191 } 192 193 char ** 194 rpc_gss_get_mech_info(mechanism, service) 195 char *mechanism; 196 rpc_gss_service_t *service; 197 { 198 if (!initialized && !rpcgss_calls_init()) 199 return ((char **)NULL); 200 return ((*calls.rpc_gss_get_mech_info)(mechanism, service)); 201 } 202 203 bool_t 204 rpc_gss_get_versions(vers_hi, vers_lo) 205 uint_t *vers_hi; 206 uint_t *vers_lo; 207 { 208 if (!initialized && !rpcgss_calls_init()) 209 return (FALSE); 210 return ((*calls.rpc_gss_get_versions)(vers_hi, vers_lo)); 211 } 212 213 bool_t 214 rpc_gss_is_installed(mechanism) 215 char *mechanism; 216 { 217 if (!initialized && !rpcgss_calls_init()) 218 return (FALSE); 219 return ((*calls.rpc_gss_is_installed)(mechanism)); 220 } 221 222 bool_t 223 rpc_gss_set_svc_name( 224 char *principal, /* server service principal name */ 225 char *mechanism, 226 uint_t req_time, 227 uint_t program, 228 uint_t version) 229 { 230 if (!initialized && !rpcgss_calls_init()) 231 return (FALSE); 232 return ((*calls.rpc_gss_set_svc_name)(principal, mechanism, req_time, 233 program, version)); 234 } 235 236 bool_t 237 rpc_gss_set_callback(cb) 238 rpc_gss_callback_t *cb; 239 { 240 if (!initialized && !rpcgss_calls_init()) 241 return (FALSE); 242 return ((*calls.rpc_gss_set_callback)(cb)); 243 } 244 245 bool_t 246 rpc_gss_getcred(req, rcred, ucred, cookie) 247 struct svc_req *req; 248 rpc_gss_rawcred_t **rcred; 249 rpc_gss_ucred_t **ucred; 250 void **cookie; 251 { 252 if (!initialized && !rpcgss_calls_init()) 253 return (FALSE); 254 return ((*calls.rpc_gss_getcred)(req, rcred, ucred, cookie)); 255 } 256 257 bool_t 258 rpc_gss_mech_to_oid(mech, oid) 259 char *mech; 260 rpc_gss_OID *oid; 261 { 262 if (!initialized && !rpcgss_calls_init()) 263 return (FALSE); 264 return ((*calls.rpc_gss_mech_to_oid)(mech, oid)); 265 } 266 267 bool_t 268 rpc_gss_qop_to_num(qop, mech, num) 269 char *qop; 270 char *mech; 271 uint_t *num; 272 { 273 if (!initialized && !rpcgss_calls_init()) 274 return (FALSE); 275 return ((*calls.rpc_gss_qop_to_num)(qop, mech, num)); 276 } 277 278 enum auth_stat 279 __svcrpcsec_gss(rqst, msg, no_dispatch) 280 struct svc_req *rqst; 281 struct rpc_msg *msg; 282 bool_t *no_dispatch; 283 { 284 if (!initialized && !rpcgss_calls_init()) 285 return (AUTH_FAILED); 286 return ((*calls.__svcrpcsec_gss)(rqst, msg, no_dispatch)); 287 } 288 289 bool_t 290 __rpc_gss_wrap(auth, buf, buflen, out_xdrs, xdr_func, xdr_ptr) 291 AUTH *auth; 292 char *buf; /* encoded header */ 293 uint_t buflen; /* encoded header length */ 294 XDR *out_xdrs; 295 bool_t (*xdr_func)(); 296 caddr_t xdr_ptr; 297 { 298 if (!initialized && !rpcgss_calls_init()) 299 return (FALSE); 300 return ((*calls.__rpc_gss_wrap)(auth, buf, buflen, out_xdrs, 301 xdr_func, xdr_ptr)); 302 } 303 304 bool_t 305 __rpc_gss_unwrap(auth, in_xdrs, xdr_func, xdr_ptr) 306 AUTH *auth; 307 XDR *in_xdrs; 308 bool_t (*xdr_func)(); 309 caddr_t xdr_ptr; 310 { 311 if (!initialized && !rpcgss_calls_init()) 312 return (FALSE); 313 return ((*calls.__rpc_gss_unwrap)(auth, in_xdrs, xdr_func, xdr_ptr)); 314 } 315 316 int 317 rpc_gss_max_data_length(rpcgss_handle, max_tp_unit_len) 318 AUTH *rpcgss_handle; 319 int max_tp_unit_len; 320 { 321 if (!initialized && !rpcgss_calls_init()) 322 return (0); 323 return ((*calls.rpc_gss_max_data_length)(rpcgss_handle, 324 max_tp_unit_len)); 325 } 326 327 int 328 rpc_gss_svc_max_data_length(req, max_tp_unit_len) 329 struct svc_req *req; 330 int max_tp_unit_len; 331 { 332 if (!initialized && !rpcgss_calls_init()) 333 return (0); 334 return ((*calls.rpc_gss_svc_max_data_length)(req, max_tp_unit_len)); 335 } 336 337 void 338 rpc_gss_get_error(error) 339 rpc_gss_error_t *error; 340 { 341 if (!initialized && !rpcgss_calls_init()) { 342 error->rpc_gss_error = RPC_GSS_ER_SYSTEMERROR; 343 error->system_error = ENOTSUP; 344 return; 345 } 346 (*calls.rpc_gss_get_error)(error); 347 } 348