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