17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*cb620785Sraf * Common Development and Distribution License (the "License"). 6*cb620785Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2161961e0fSrobinson 227c478bd9Sstevel@tonic-gate /* 23*cb620785Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include "mt.h" 307c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 317c478bd9Sstevel@tonic-gate #include <stdio.h> 32*cb620785Sraf #include <atomic.h> 337c478bd9Sstevel@tonic-gate #include <sys/errno.h> 347c478bd9Sstevel@tonic-gate #include <dlfcn.h> 357c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #define RPCSEC "rpcsec.so.1" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate typedef struct { 407c478bd9Sstevel@tonic-gate AUTH *(*rpc_gss_seccreate)(); 417c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_set_defaults)(); 427c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_get_principal_name)(); 437c478bd9Sstevel@tonic-gate char **(*rpc_gss_get_mechanisms)(); 447c478bd9Sstevel@tonic-gate char **(*rpc_gss_get_mech_info)(); 457c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_get_versions)(); 467c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_is_installed)(); 477c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_set_svc_name)(); 487c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_set_callback)(); 497c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_getcred)(); 507c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_mech_to_oid)(); 517c478bd9Sstevel@tonic-gate bool_t (*rpc_gss_qop_to_num)(); 527c478bd9Sstevel@tonic-gate enum auth_stat (*__svcrpcsec_gss)(); 537c478bd9Sstevel@tonic-gate bool_t (*__rpc_gss_wrap)(); 547c478bd9Sstevel@tonic-gate bool_t (*__rpc_gss_unwrap)(); 557c478bd9Sstevel@tonic-gate int (*rpc_gss_max_data_length)(); 567c478bd9Sstevel@tonic-gate int (*rpc_gss_svc_max_data_length)(); 577c478bd9Sstevel@tonic-gate void (*rpc_gss_get_error)(); 587c478bd9Sstevel@tonic-gate } rpcgss_calls_t; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static rpcgss_calls_t calls; 617c478bd9Sstevel@tonic-gate static mutex_t rpcgss_calls_mutex = DEFAULTMUTEX; 627c478bd9Sstevel@tonic-gate static bool_t initialized = FALSE; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static bool_t 6561961e0fSrobinson rpcgss_calls_init(void) 667c478bd9Sstevel@tonic-gate { 67*cb620785Sraf void *handle; 687c478bd9Sstevel@tonic-gate bool_t ret = FALSE; 697c478bd9Sstevel@tonic-gate 70*cb620785Sraf if (initialized) { 71*cb620785Sraf membar_consumer(); 72*cb620785Sraf return (TRUE); 73*cb620785Sraf } 7461961e0fSrobinson (void) mutex_lock(&rpcgss_calls_mutex); 757c478bd9Sstevel@tonic-gate if (initialized) { 76*cb620785Sraf (void) mutex_unlock(&rpcgss_calls_mutex); 77*cb620785Sraf membar_consumer(); 78*cb620785Sraf return (TRUE); 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate if ((handle = dlopen(RPCSEC, RTLD_LAZY)) == NULL) 827c478bd9Sstevel@tonic-gate goto done; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_seccreate = (AUTH *(*)()) dlsym(handle, 857c478bd9Sstevel@tonic-gate "__rpc_gss_seccreate")) == NULL) 867c478bd9Sstevel@tonic-gate goto done; 877c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_set_defaults = (bool_t (*)()) dlsym(handle, 887c478bd9Sstevel@tonic-gate "__rpc_gss_set_defaults")) == NULL) 897c478bd9Sstevel@tonic-gate goto done; 907c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_get_principal_name = (bool_t (*)()) dlsym(handle, 917c478bd9Sstevel@tonic-gate "__rpc_gss_get_principal_name")) == NULL) 927c478bd9Sstevel@tonic-gate goto done; 937c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_get_mechanisms = (char **(*)()) dlsym(handle, 947c478bd9Sstevel@tonic-gate "__rpc_gss_get_mechanisms")) == NULL) 957c478bd9Sstevel@tonic-gate goto done; 967c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_get_mech_info = (char **(*)()) dlsym(handle, 977c478bd9Sstevel@tonic-gate "__rpc_gss_get_mech_info")) == NULL) 987c478bd9Sstevel@tonic-gate goto done; 997c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_get_versions = (bool_t (*)()) dlsym(handle, 1007c478bd9Sstevel@tonic-gate "__rpc_gss_get_versions")) == NULL) 1017c478bd9Sstevel@tonic-gate goto done; 1027c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_is_installed = (bool_t (*)()) dlsym(handle, 1037c478bd9Sstevel@tonic-gate "__rpc_gss_is_installed")) == NULL) 1047c478bd9Sstevel@tonic-gate goto done; 1057c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_set_svc_name = (bool_t (*)()) dlsym(handle, 1067c478bd9Sstevel@tonic-gate "__rpc_gss_set_svc_name")) == NULL) 1077c478bd9Sstevel@tonic-gate goto done; 1087c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_set_callback = (bool_t (*)()) dlsym(handle, 1097c478bd9Sstevel@tonic-gate "__rpc_gss_set_callback")) == NULL) 1107c478bd9Sstevel@tonic-gate goto done; 1117c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_getcred = (bool_t (*)()) dlsym(handle, 1127c478bd9Sstevel@tonic-gate "__rpc_gss_getcred")) == NULL) 1137c478bd9Sstevel@tonic-gate goto done; 1147c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_mech_to_oid = (bool_t (*)()) dlsym(handle, 1157c478bd9Sstevel@tonic-gate "__rpc_gss_mech_to_oid")) == NULL) 1167c478bd9Sstevel@tonic-gate goto done; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_qop_to_num = (bool_t (*)()) dlsym(handle, 1197c478bd9Sstevel@tonic-gate "__rpc_gss_qop_to_num")) == NULL) 1207c478bd9Sstevel@tonic-gate goto done; 1217c478bd9Sstevel@tonic-gate if ((calls.__svcrpcsec_gss = (enum auth_stat (*)()) dlsym(handle, 1227c478bd9Sstevel@tonic-gate "__svcrpcsec_gss")) == NULL) 1237c478bd9Sstevel@tonic-gate goto done; 1247c478bd9Sstevel@tonic-gate if ((calls.__rpc_gss_wrap = (bool_t (*)()) dlsym(handle, 1257c478bd9Sstevel@tonic-gate "__rpc_gss_wrap")) == NULL) 1267c478bd9Sstevel@tonic-gate goto done; 1277c478bd9Sstevel@tonic-gate if ((calls.__rpc_gss_unwrap = (bool_t (*)()) dlsym(handle, 1287c478bd9Sstevel@tonic-gate "__rpc_gss_unwrap")) == NULL) 1297c478bd9Sstevel@tonic-gate goto done; 1307c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_max_data_length = (int (*)()) dlsym(handle, 1317c478bd9Sstevel@tonic-gate "__rpc_gss_max_data_length")) == NULL) 1327c478bd9Sstevel@tonic-gate goto done; 1337c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_svc_max_data_length = (int (*)()) dlsym(handle, 1347c478bd9Sstevel@tonic-gate "__rpc_gss_svc_max_data_length")) == NULL) 1357c478bd9Sstevel@tonic-gate goto done; 1367c478bd9Sstevel@tonic-gate if ((calls.rpc_gss_get_error = (void (*)()) dlsym(handle, 1377c478bd9Sstevel@tonic-gate "__rpc_gss_get_error")) == NULL) 1387c478bd9Sstevel@tonic-gate goto done; 1397c478bd9Sstevel@tonic-gate ret = TRUE; 1407c478bd9Sstevel@tonic-gate done: 1417c478bd9Sstevel@tonic-gate if (!ret) { 1427c478bd9Sstevel@tonic-gate if (handle != NULL) 14361961e0fSrobinson (void) dlclose(handle); 1447c478bd9Sstevel@tonic-gate } 145*cb620785Sraf membar_producer(); 1467c478bd9Sstevel@tonic-gate initialized = ret; 14761961e0fSrobinson (void) mutex_unlock(&rpcgss_calls_mutex); 1487c478bd9Sstevel@tonic-gate return (ret); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate AUTH * 1527c478bd9Sstevel@tonic-gate rpc_gss_seccreate( 1537c478bd9Sstevel@tonic-gate CLIENT *clnt, /* associated client handle */ 1547c478bd9Sstevel@tonic-gate char *principal, /* server service principal */ 1557c478bd9Sstevel@tonic-gate char *mechanism, /* security mechanism */ 1567c478bd9Sstevel@tonic-gate rpc_gss_service_t service_type, /* security service */ 1577c478bd9Sstevel@tonic-gate char *qop, /* requested QOP */ 1587c478bd9Sstevel@tonic-gate rpc_gss_options_req_t *options_req, /* requested options */ 1597c478bd9Sstevel@tonic-gate rpc_gss_options_ret_t *options_ret) /* returned options */ 1607c478bd9Sstevel@tonic-gate { 161*cb620785Sraf if (!rpcgss_calls_init()) 16261961e0fSrobinson return (NULL); 1637c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_seccreate)(clnt, principal, mechanism, 1647c478bd9Sstevel@tonic-gate service_type, qop, options_req, options_ret)); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate bool_t 16861961e0fSrobinson rpc_gss_set_defaults(AUTH *auth, rpc_gss_service_t service, char *qop) 1697c478bd9Sstevel@tonic-gate { 170*cb620785Sraf if (!rpcgss_calls_init()) 1717c478bd9Sstevel@tonic-gate return (FALSE); 1727c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_set_defaults)(auth, service, qop)); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate bool_t 1767c478bd9Sstevel@tonic-gate rpc_gss_get_principal_name( 1777c478bd9Sstevel@tonic-gate rpc_gss_principal_t *principal, 1787c478bd9Sstevel@tonic-gate char *mechanism, 1797c478bd9Sstevel@tonic-gate char *user_name, 1807c478bd9Sstevel@tonic-gate char *node, 1817c478bd9Sstevel@tonic-gate char *secdomain) 1827c478bd9Sstevel@tonic-gate { 183*cb620785Sraf if (!rpcgss_calls_init()) 1847c478bd9Sstevel@tonic-gate return (FALSE); 1857c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_get_principal_name)(principal, mechanism, 1867c478bd9Sstevel@tonic-gate user_name, node, secdomain)); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate char ** 19061961e0fSrobinson rpc_gss_get_mechanisms(void) 1917c478bd9Sstevel@tonic-gate { 192*cb620785Sraf if (!rpcgss_calls_init()) 19361961e0fSrobinson return (NULL); 1947c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_get_mechanisms)()); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate char ** 19861961e0fSrobinson rpc_gss_get_mech_info(char *mechanism, rpc_gss_service_t *service) 1997c478bd9Sstevel@tonic-gate { 200*cb620785Sraf if (!rpcgss_calls_init()) 20161961e0fSrobinson return (NULL); 2027c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_get_mech_info)(mechanism, service)); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate bool_t 20661961e0fSrobinson rpc_gss_get_versions(uint_t *vers_hi, uint_t *vers_lo) 2077c478bd9Sstevel@tonic-gate { 208*cb620785Sraf if (!rpcgss_calls_init()) 2097c478bd9Sstevel@tonic-gate return (FALSE); 2107c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_get_versions)(vers_hi, vers_lo)); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate bool_t 21461961e0fSrobinson rpc_gss_is_installed(char *mechanism) 2157c478bd9Sstevel@tonic-gate { 216*cb620785Sraf if (!rpcgss_calls_init()) 2177c478bd9Sstevel@tonic-gate return (FALSE); 2187c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_is_installed)(mechanism)); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate bool_t 2227c478bd9Sstevel@tonic-gate rpc_gss_set_svc_name( 2237c478bd9Sstevel@tonic-gate char *principal, /* server service principal name */ 2247c478bd9Sstevel@tonic-gate char *mechanism, 2257c478bd9Sstevel@tonic-gate uint_t req_time, 2267c478bd9Sstevel@tonic-gate uint_t program, 2277c478bd9Sstevel@tonic-gate uint_t version) 2287c478bd9Sstevel@tonic-gate { 229*cb620785Sraf if (!rpcgss_calls_init()) 2307c478bd9Sstevel@tonic-gate return (FALSE); 2317c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_set_svc_name)(principal, mechanism, req_time, 2327c478bd9Sstevel@tonic-gate program, version)); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate bool_t 23661961e0fSrobinson rpc_gss_set_callback(rpc_gss_callback_t *cb) 2377c478bd9Sstevel@tonic-gate { 238*cb620785Sraf if (!rpcgss_calls_init()) 2397c478bd9Sstevel@tonic-gate return (FALSE); 2407c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_set_callback)(cb)); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate bool_t 24461961e0fSrobinson rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred, 24561961e0fSrobinson rpc_gss_ucred_t **ucred, void **cookie) 2467c478bd9Sstevel@tonic-gate { 247*cb620785Sraf if (!rpcgss_calls_init()) 2487c478bd9Sstevel@tonic-gate return (FALSE); 2497c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_getcred)(req, rcred, ucred, cookie)); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate bool_t 25361961e0fSrobinson rpc_gss_mech_to_oid(char *mech, rpc_gss_OID *oid) 2547c478bd9Sstevel@tonic-gate { 255*cb620785Sraf if (!rpcgss_calls_init()) 2567c478bd9Sstevel@tonic-gate return (FALSE); 2577c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_mech_to_oid)(mech, oid)); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate bool_t 26161961e0fSrobinson rpc_gss_qop_to_num(char *qop, char *mech, uint_t *num) 2627c478bd9Sstevel@tonic-gate { 263*cb620785Sraf if (!rpcgss_calls_init()) 2647c478bd9Sstevel@tonic-gate return (FALSE); 2657c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_qop_to_num)(qop, mech, num)); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate enum auth_stat 26961961e0fSrobinson __svcrpcsec_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) 2707c478bd9Sstevel@tonic-gate { 271*cb620785Sraf if (!rpcgss_calls_init()) 2727c478bd9Sstevel@tonic-gate return (AUTH_FAILED); 2737c478bd9Sstevel@tonic-gate return ((*calls.__svcrpcsec_gss)(rqst, msg, no_dispatch)); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate bool_t 27761961e0fSrobinson __rpc_gss_wrap(AUTH *auth, char *buf, uint_t buflen, XDR *out_xdrs, 27861961e0fSrobinson bool_t (*xdr_func)(), caddr_t xdr_ptr) 2797c478bd9Sstevel@tonic-gate { 280*cb620785Sraf if (!rpcgss_calls_init()) 2817c478bd9Sstevel@tonic-gate return (FALSE); 2827c478bd9Sstevel@tonic-gate return ((*calls.__rpc_gss_wrap)(auth, buf, buflen, out_xdrs, 2837c478bd9Sstevel@tonic-gate xdr_func, xdr_ptr)); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate bool_t 28761961e0fSrobinson __rpc_gss_unwrap(AUTH *auth, XDR *in_xdrs, bool_t (*xdr_func)(), 28861961e0fSrobinson caddr_t xdr_ptr) 2897c478bd9Sstevel@tonic-gate { 290*cb620785Sraf if (!rpcgss_calls_init()) 2917c478bd9Sstevel@tonic-gate return (FALSE); 2927c478bd9Sstevel@tonic-gate return ((*calls.__rpc_gss_unwrap)(auth, in_xdrs, xdr_func, xdr_ptr)); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate int 29661961e0fSrobinson rpc_gss_max_data_length(AUTH *rpcgss_handle, int max_tp_unit_len) 2977c478bd9Sstevel@tonic-gate { 298*cb620785Sraf if (!rpcgss_calls_init()) 2997c478bd9Sstevel@tonic-gate return (0); 3007c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_max_data_length)(rpcgss_handle, 3017c478bd9Sstevel@tonic-gate max_tp_unit_len)); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate int 30561961e0fSrobinson rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len) 3067c478bd9Sstevel@tonic-gate { 307*cb620785Sraf if (!rpcgss_calls_init()) 3087c478bd9Sstevel@tonic-gate return (0); 3097c478bd9Sstevel@tonic-gate return ((*calls.rpc_gss_svc_max_data_length)(req, max_tp_unit_len)); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate void 31361961e0fSrobinson rpc_gss_get_error(rpc_gss_error_t *error) 3147c478bd9Sstevel@tonic-gate { 315*cb620785Sraf if (!rpcgss_calls_init()) { 3167c478bd9Sstevel@tonic-gate error->rpc_gss_error = RPC_GSS_ER_SYSTEMERROR; 3177c478bd9Sstevel@tonic-gate error->system_error = ENOTSUP; 3187c478bd9Sstevel@tonic-gate return; 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate (*calls.rpc_gss_get_error)(error); 3217c478bd9Sstevel@tonic-gate } 322