10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 22*132Srobinson 230Sstevel@tonic-gate /* 24*132Srobinson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 250Sstevel@tonic-gate * Use is subject to license terms. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include "mt.h" 310Sstevel@tonic-gate #include "rpc_mt.h" 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #include <sys/errno.h> 340Sstevel@tonic-gate #include <dlfcn.h> 350Sstevel@tonic-gate #include <rpc/rpc.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate #define RPCSEC "rpcsec.so.1" 380Sstevel@tonic-gate 390Sstevel@tonic-gate typedef struct { 400Sstevel@tonic-gate AUTH *(*rpc_gss_seccreate)(); 410Sstevel@tonic-gate bool_t (*rpc_gss_set_defaults)(); 420Sstevel@tonic-gate bool_t (*rpc_gss_get_principal_name)(); 430Sstevel@tonic-gate char **(*rpc_gss_get_mechanisms)(); 440Sstevel@tonic-gate char **(*rpc_gss_get_mech_info)(); 450Sstevel@tonic-gate bool_t (*rpc_gss_get_versions)(); 460Sstevel@tonic-gate bool_t (*rpc_gss_is_installed)(); 470Sstevel@tonic-gate bool_t (*rpc_gss_set_svc_name)(); 480Sstevel@tonic-gate bool_t (*rpc_gss_set_callback)(); 490Sstevel@tonic-gate bool_t (*rpc_gss_getcred)(); 500Sstevel@tonic-gate bool_t (*rpc_gss_mech_to_oid)(); 510Sstevel@tonic-gate bool_t (*rpc_gss_qop_to_num)(); 520Sstevel@tonic-gate enum auth_stat (*__svcrpcsec_gss)(); 530Sstevel@tonic-gate bool_t (*__rpc_gss_wrap)(); 540Sstevel@tonic-gate bool_t (*__rpc_gss_unwrap)(); 550Sstevel@tonic-gate int (*rpc_gss_max_data_length)(); 560Sstevel@tonic-gate int (*rpc_gss_svc_max_data_length)(); 570Sstevel@tonic-gate void (*rpc_gss_get_error)(); 580Sstevel@tonic-gate } rpcgss_calls_t; 590Sstevel@tonic-gate 600Sstevel@tonic-gate static rpcgss_calls_t calls; 610Sstevel@tonic-gate static mutex_t rpcgss_calls_mutex = DEFAULTMUTEX; 620Sstevel@tonic-gate static bool_t initialized = FALSE; 630Sstevel@tonic-gate 640Sstevel@tonic-gate static bool_t 65*132Srobinson rpcgss_calls_init(void) 660Sstevel@tonic-gate { 670Sstevel@tonic-gate void *handle = NULL; 680Sstevel@tonic-gate bool_t ret = FALSE; 690Sstevel@tonic-gate 70*132Srobinson (void) mutex_lock(&rpcgss_calls_mutex); 710Sstevel@tonic-gate if (initialized) { 720Sstevel@tonic-gate ret = TRUE; 730Sstevel@tonic-gate goto done; 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate if ((handle = dlopen(RPCSEC, RTLD_LAZY)) == NULL) 770Sstevel@tonic-gate goto done; 780Sstevel@tonic-gate 790Sstevel@tonic-gate if ((calls.rpc_gss_seccreate = (AUTH *(*)()) dlsym(handle, 800Sstevel@tonic-gate "__rpc_gss_seccreate")) == NULL) 810Sstevel@tonic-gate goto done; 820Sstevel@tonic-gate if ((calls.rpc_gss_set_defaults = (bool_t (*)()) dlsym(handle, 830Sstevel@tonic-gate "__rpc_gss_set_defaults")) == NULL) 840Sstevel@tonic-gate goto done; 850Sstevel@tonic-gate if ((calls.rpc_gss_get_principal_name = (bool_t (*)()) dlsym(handle, 860Sstevel@tonic-gate "__rpc_gss_get_principal_name")) == NULL) 870Sstevel@tonic-gate goto done; 880Sstevel@tonic-gate if ((calls.rpc_gss_get_mechanisms = (char **(*)()) dlsym(handle, 890Sstevel@tonic-gate "__rpc_gss_get_mechanisms")) == NULL) 900Sstevel@tonic-gate goto done; 910Sstevel@tonic-gate if ((calls.rpc_gss_get_mech_info = (char **(*)()) dlsym(handle, 920Sstevel@tonic-gate "__rpc_gss_get_mech_info")) == NULL) 930Sstevel@tonic-gate goto done; 940Sstevel@tonic-gate if ((calls.rpc_gss_get_versions = (bool_t (*)()) dlsym(handle, 950Sstevel@tonic-gate "__rpc_gss_get_versions")) == NULL) 960Sstevel@tonic-gate goto done; 970Sstevel@tonic-gate if ((calls.rpc_gss_is_installed = (bool_t (*)()) dlsym(handle, 980Sstevel@tonic-gate "__rpc_gss_is_installed")) == NULL) 990Sstevel@tonic-gate goto done; 1000Sstevel@tonic-gate if ((calls.rpc_gss_set_svc_name = (bool_t (*)()) dlsym(handle, 1010Sstevel@tonic-gate "__rpc_gss_set_svc_name")) == NULL) 1020Sstevel@tonic-gate goto done; 1030Sstevel@tonic-gate if ((calls.rpc_gss_set_callback = (bool_t (*)()) dlsym(handle, 1040Sstevel@tonic-gate "__rpc_gss_set_callback")) == NULL) 1050Sstevel@tonic-gate goto done; 1060Sstevel@tonic-gate if ((calls.rpc_gss_getcred = (bool_t (*)()) dlsym(handle, 1070Sstevel@tonic-gate "__rpc_gss_getcred")) == NULL) 1080Sstevel@tonic-gate goto done; 1090Sstevel@tonic-gate if ((calls.rpc_gss_mech_to_oid = (bool_t (*)()) dlsym(handle, 1100Sstevel@tonic-gate "__rpc_gss_mech_to_oid")) == NULL) 1110Sstevel@tonic-gate goto done; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate if ((calls.rpc_gss_qop_to_num = (bool_t (*)()) dlsym(handle, 1140Sstevel@tonic-gate "__rpc_gss_qop_to_num")) == NULL) 1150Sstevel@tonic-gate goto done; 1160Sstevel@tonic-gate if ((calls.__svcrpcsec_gss = (enum auth_stat (*)()) dlsym(handle, 1170Sstevel@tonic-gate "__svcrpcsec_gss")) == NULL) 1180Sstevel@tonic-gate goto done; 1190Sstevel@tonic-gate if ((calls.__rpc_gss_wrap = (bool_t (*)()) dlsym(handle, 1200Sstevel@tonic-gate "__rpc_gss_wrap")) == NULL) 1210Sstevel@tonic-gate goto done; 1220Sstevel@tonic-gate if ((calls.__rpc_gss_unwrap = (bool_t (*)()) dlsym(handle, 1230Sstevel@tonic-gate "__rpc_gss_unwrap")) == NULL) 1240Sstevel@tonic-gate goto done; 1250Sstevel@tonic-gate if ((calls.rpc_gss_max_data_length = (int (*)()) dlsym(handle, 1260Sstevel@tonic-gate "__rpc_gss_max_data_length")) == NULL) 1270Sstevel@tonic-gate goto done; 1280Sstevel@tonic-gate if ((calls.rpc_gss_svc_max_data_length = (int (*)()) dlsym(handle, 1290Sstevel@tonic-gate "__rpc_gss_svc_max_data_length")) == NULL) 1300Sstevel@tonic-gate goto done; 1310Sstevel@tonic-gate if ((calls.rpc_gss_get_error = (void (*)()) dlsym(handle, 1320Sstevel@tonic-gate "__rpc_gss_get_error")) == NULL) 1330Sstevel@tonic-gate goto done; 1340Sstevel@tonic-gate ret = TRUE; 1350Sstevel@tonic-gate done: 1360Sstevel@tonic-gate if (!ret) { 1370Sstevel@tonic-gate if (handle != NULL) 138*132Srobinson (void) dlclose(handle); 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate initialized = ret; 141*132Srobinson (void) mutex_unlock(&rpcgss_calls_mutex); 1420Sstevel@tonic-gate return (ret); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate AUTH * 1460Sstevel@tonic-gate rpc_gss_seccreate( 1470Sstevel@tonic-gate CLIENT *clnt, /* associated client handle */ 1480Sstevel@tonic-gate char *principal, /* server service principal */ 1490Sstevel@tonic-gate char *mechanism, /* security mechanism */ 1500Sstevel@tonic-gate rpc_gss_service_t service_type, /* security service */ 1510Sstevel@tonic-gate char *qop, /* requested QOP */ 1520Sstevel@tonic-gate rpc_gss_options_req_t *options_req, /* requested options */ 1530Sstevel@tonic-gate rpc_gss_options_ret_t *options_ret) /* returned options */ 1540Sstevel@tonic-gate { 1550Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 156*132Srobinson return (NULL); 1570Sstevel@tonic-gate return ((*calls.rpc_gss_seccreate)(clnt, principal, mechanism, 1580Sstevel@tonic-gate service_type, qop, options_req, options_ret)); 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate bool_t 162*132Srobinson rpc_gss_set_defaults(AUTH *auth, rpc_gss_service_t service, char *qop) 1630Sstevel@tonic-gate { 1640Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 1650Sstevel@tonic-gate return (FALSE); 1660Sstevel@tonic-gate return ((*calls.rpc_gss_set_defaults)(auth, service, qop)); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate bool_t 1700Sstevel@tonic-gate rpc_gss_get_principal_name( 1710Sstevel@tonic-gate rpc_gss_principal_t *principal, 1720Sstevel@tonic-gate char *mechanism, 1730Sstevel@tonic-gate char *user_name, 1740Sstevel@tonic-gate char *node, 1750Sstevel@tonic-gate char *secdomain) 1760Sstevel@tonic-gate { 1770Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 1780Sstevel@tonic-gate return (FALSE); 1790Sstevel@tonic-gate return ((*calls.rpc_gss_get_principal_name)(principal, mechanism, 1800Sstevel@tonic-gate user_name, node, secdomain)); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate char ** 184*132Srobinson rpc_gss_get_mechanisms(void) 1850Sstevel@tonic-gate { 1860Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 187*132Srobinson return (NULL); 1880Sstevel@tonic-gate return ((*calls.rpc_gss_get_mechanisms)()); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate char ** 192*132Srobinson rpc_gss_get_mech_info(char *mechanism, rpc_gss_service_t *service) 1930Sstevel@tonic-gate { 1940Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 195*132Srobinson return (NULL); 1960Sstevel@tonic-gate return ((*calls.rpc_gss_get_mech_info)(mechanism, service)); 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate bool_t 200*132Srobinson rpc_gss_get_versions(uint_t *vers_hi, uint_t *vers_lo) 2010Sstevel@tonic-gate { 2020Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2030Sstevel@tonic-gate return (FALSE); 2040Sstevel@tonic-gate return ((*calls.rpc_gss_get_versions)(vers_hi, vers_lo)); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate bool_t 208*132Srobinson rpc_gss_is_installed(char *mechanism) 2090Sstevel@tonic-gate { 2100Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2110Sstevel@tonic-gate return (FALSE); 2120Sstevel@tonic-gate return ((*calls.rpc_gss_is_installed)(mechanism)); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate bool_t 2160Sstevel@tonic-gate rpc_gss_set_svc_name( 2170Sstevel@tonic-gate char *principal, /* server service principal name */ 2180Sstevel@tonic-gate char *mechanism, 2190Sstevel@tonic-gate uint_t req_time, 2200Sstevel@tonic-gate uint_t program, 2210Sstevel@tonic-gate uint_t version) 2220Sstevel@tonic-gate { 2230Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2240Sstevel@tonic-gate return (FALSE); 2250Sstevel@tonic-gate return ((*calls.rpc_gss_set_svc_name)(principal, mechanism, req_time, 2260Sstevel@tonic-gate program, version)); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate bool_t 230*132Srobinson rpc_gss_set_callback(rpc_gss_callback_t *cb) 2310Sstevel@tonic-gate { 2320Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2330Sstevel@tonic-gate return (FALSE); 2340Sstevel@tonic-gate return ((*calls.rpc_gss_set_callback)(cb)); 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate bool_t 238*132Srobinson rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred, 239*132Srobinson rpc_gss_ucred_t **ucred, void **cookie) 2400Sstevel@tonic-gate { 2410Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2420Sstevel@tonic-gate return (FALSE); 2430Sstevel@tonic-gate return ((*calls.rpc_gss_getcred)(req, rcred, ucred, cookie)); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate bool_t 247*132Srobinson rpc_gss_mech_to_oid(char *mech, rpc_gss_OID *oid) 2480Sstevel@tonic-gate { 2490Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2500Sstevel@tonic-gate return (FALSE); 2510Sstevel@tonic-gate return ((*calls.rpc_gss_mech_to_oid)(mech, oid)); 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate bool_t 255*132Srobinson rpc_gss_qop_to_num(char *qop, char *mech, uint_t *num) 2560Sstevel@tonic-gate { 2570Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2580Sstevel@tonic-gate return (FALSE); 2590Sstevel@tonic-gate return ((*calls.rpc_gss_qop_to_num)(qop, mech, num)); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate enum auth_stat 263*132Srobinson __svcrpcsec_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) 2640Sstevel@tonic-gate { 2650Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2660Sstevel@tonic-gate return (AUTH_FAILED); 2670Sstevel@tonic-gate return ((*calls.__svcrpcsec_gss)(rqst, msg, no_dispatch)); 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate bool_t 271*132Srobinson __rpc_gss_wrap(AUTH *auth, char *buf, uint_t buflen, XDR *out_xdrs, 272*132Srobinson bool_t (*xdr_func)(), caddr_t xdr_ptr) 2730Sstevel@tonic-gate { 2740Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2750Sstevel@tonic-gate return (FALSE); 2760Sstevel@tonic-gate return ((*calls.__rpc_gss_wrap)(auth, buf, buflen, out_xdrs, 2770Sstevel@tonic-gate xdr_func, xdr_ptr)); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate bool_t 281*132Srobinson __rpc_gss_unwrap(AUTH *auth, XDR *in_xdrs, bool_t (*xdr_func)(), 282*132Srobinson caddr_t xdr_ptr) 2830Sstevel@tonic-gate { 2840Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2850Sstevel@tonic-gate return (FALSE); 2860Sstevel@tonic-gate return ((*calls.__rpc_gss_unwrap)(auth, in_xdrs, xdr_func, xdr_ptr)); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate int 290*132Srobinson rpc_gss_max_data_length(AUTH *rpcgss_handle, int max_tp_unit_len) 2910Sstevel@tonic-gate { 2920Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 2930Sstevel@tonic-gate return (0); 2940Sstevel@tonic-gate return ((*calls.rpc_gss_max_data_length)(rpcgss_handle, 2950Sstevel@tonic-gate max_tp_unit_len)); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate int 299*132Srobinson rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len) 3000Sstevel@tonic-gate { 3010Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) 3020Sstevel@tonic-gate return (0); 3030Sstevel@tonic-gate return ((*calls.rpc_gss_svc_max_data_length)(req, max_tp_unit_len)); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate void 307*132Srobinson rpc_gss_get_error(rpc_gss_error_t *error) 3080Sstevel@tonic-gate { 3090Sstevel@tonic-gate if (!initialized && !rpcgss_calls_init()) { 3100Sstevel@tonic-gate error->rpc_gss_error = RPC_GSS_ER_SYSTEMERROR; 3110Sstevel@tonic-gate error->system_error = ENOTSUP; 3120Sstevel@tonic-gate return; 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate (*calls.rpc_gss_get_error)(error); 3150Sstevel@tonic-gate } 316