xref: /titanic_44/usr/src/lib/libnsl/rpc/rpcsec_gss_if.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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