remove pyzfs
[unleashed.git] / usr / src / lib / rpcsec_gss / rpcsec_gss_misc.c
blobe9bf848365fdaded8c5f0673b1a173e3afd9d287
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1986-1995, 1997, 2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
32 * $Header:
33 * /afs/gza.com/product/secure/rel-eng/src/1.1/rpc/RCS/auth_gssapi_misc.c,v
34 * 1.10 1994/10/27 12:39:23 jik Exp $
37 #include <stdlib.h>
38 #include <gssapi/gssapi.h>
39 #include <rpc/rpc.h>
40 #include <rpc/rpcsec_defs.h>
43 * Miscellaneous XDR routines.
45 bool_t
46 __xdr_gss_buf(xdrs, buf)
47 XDR *xdrs;
48 gss_buffer_t buf;
50 u_int cast_len, bound_len;
53 * We go through this contortion because size_t is a now a ulong,
54 * GSS-API uses ulongs.
57 if (xdrs->x_op != XDR_DECODE) {
58 bound_len = cast_len = (u_int) buf->length;
59 } else {
60 bound_len = (u_int)-1;
63 if (xdr_bytes(xdrs, (char **)&buf->value, &cast_len,
64 bound_len) == TRUE) {
65 if (xdrs->x_op == XDR_DECODE)
66 buf->length = cast_len;
68 return (TRUE);
71 return (FALSE);
74 bool_t
75 __xdr_rpc_gss_creds(xdrs, creds)
76 XDR *xdrs;
77 rpc_gss_creds *creds;
79 if (!xdr_u_int(xdrs, &creds->version) ||
80 !xdr_u_int(xdrs, &creds->gss_proc) ||
81 !xdr_u_int(xdrs, &creds->seq_num) ||
82 !xdr_u_int(xdrs, (u_int *)&creds->service) ||
83 !__xdr_gss_buf(xdrs, &creds->ctx_handle))
84 return (FALSE);
85 return (TRUE);
88 bool_t
89 __xdr_rpc_gss_init_arg(xdrs, init_arg)
90 XDR *xdrs;
91 rpc_gss_init_arg *init_arg;
93 if (!__xdr_gss_buf(xdrs, init_arg))
94 return (FALSE);
95 return (TRUE);
98 bool_t
99 __xdr_rpc_gss_init_res(xdrs, init_res)
100 XDR *xdrs;
101 rpc_gss_init_res *init_res;
103 if (!__xdr_gss_buf(xdrs, &init_res->ctx_handle) ||
104 !xdr_u_int(xdrs, (u_int *)&init_res->gss_major) ||
105 !xdr_u_int(xdrs, (u_int *)&init_res->gss_minor) ||
106 !xdr_u_int(xdrs, (u_int *)&init_res->seq_window) ||
107 !__xdr_gss_buf(xdrs, &init_res->token))
108 return (FALSE);
109 return (TRUE);
113 * Generic routine to wrap data used by client and server sides.
115 bool_t
116 __rpc_gss_wrap_data(service, qop, context, seq_num, out_xdrs, xdr_func,
117 xdr_ptr)
118 OM_uint32 qop;
119 rpc_gss_service_t service;
120 gss_ctx_id_t context;
121 u_int seq_num;
122 XDR *out_xdrs;
123 bool_t (*xdr_func)();
124 caddr_t xdr_ptr;
126 OM_uint32 minor;
127 gss_buffer_desc in_buf, out_buf;
128 XDR temp_xdrs;
129 bool_t conf_state;
130 bool_t ret = FALSE;
131 u_int bufsiz;
132 char *buf;
135 * Create a temporary XDR/buffer to hold the data to be wrapped.
137 out_buf.length = 0;
138 bufsiz = xdr_sizeof(xdr_func, xdr_ptr) +
139 xdr_sizeof(xdr_u_int, &seq_num);
140 if ((buf = (char *)malloc(bufsiz)) == NULL) {
141 fprintf(stderr, dgettext(TEXT_DOMAIN, "malloc failed in "
142 "__rpc_gss_wrap_data\n"));
143 return (FALSE);
145 xdrmem_create(&temp_xdrs, buf, bufsiz, XDR_ENCODE);
148 * serialize the sequence number into tmp memory
150 if (!xdr_u_int(&temp_xdrs, &seq_num))
151 goto fail;
154 * serialize the arguments into tmp memory
156 if (!(*xdr_func)(&temp_xdrs, xdr_ptr))
157 goto fail;
160 * Data to be wrapped goes in in_buf. If privacy is used,
161 * out_buf will have wrapped data (in_buf will no longer be
162 * needed). If integrity is used, out_buf will have checksum
163 * which will follow the data in in_buf.
165 in_buf.length = xdr_getpos(&temp_xdrs);
166 in_buf.value = temp_xdrs.x_base;
168 switch (service) {
169 case rpc_gss_svc_privacy:
170 if (gss_seal(&minor, context, TRUE, qop, &in_buf,
171 &conf_state, &out_buf) != GSS_S_COMPLETE)
172 goto fail;
173 in_buf.length = 0; /* in_buf not needed */
174 if (!conf_state)
175 goto fail;
176 break;
177 case rpc_gss_svc_integrity:
178 if (gss_sign(&minor, context, qop, &in_buf,
179 &out_buf) != GSS_S_COMPLETE)
180 goto fail;
181 break;
182 default:
183 goto fail;
187 * write out in_buf and out_buf as needed
189 if (in_buf.length != 0) {
190 if (!__xdr_gss_buf(out_xdrs, &in_buf))
191 goto fail;
194 if (!__xdr_gss_buf(out_xdrs, &out_buf))
195 goto fail;
196 ret = TRUE;
197 fail:
198 XDR_DESTROY(&temp_xdrs);
199 if (buf)
200 (void) free(buf);
201 if (out_buf.length != 0)
202 (void) gss_release_buffer(&minor, &out_buf);
203 return (ret);
207 * Generic routine to unwrap data used by client and server sides.
209 bool_t
210 __rpc_gss_unwrap_data(service, context, seq_num, qop_check, in_xdrs, xdr_func,
211 xdr_ptr)
212 rpc_gss_service_t service;
213 gss_ctx_id_t context;
214 u_int seq_num;
215 OM_uint32 qop_check;
216 XDR *in_xdrs;
217 bool_t (*xdr_func)();
218 caddr_t xdr_ptr;
220 gss_buffer_desc in_buf, out_buf;
221 XDR temp_xdrs;
222 u_int seq_num2;
223 bool_t conf;
224 OM_uint32 major = GSS_S_COMPLETE, minor = 0;
225 int qop;
227 in_buf.value = NULL;
228 out_buf.value = NULL;
231 * Pull out wrapped data. For privacy service, this is the
232 * encrypted data. For integrity service, this is the data
233 * followed by a checksum.
235 if (!__xdr_gss_buf(in_xdrs, &in_buf))
236 return (FALSE);
238 if (service == rpc_gss_svc_privacy) {
239 major = gss_unseal(&minor, context, &in_buf, &out_buf, &conf,
240 &qop);
241 free(in_buf.value);
242 if (major != GSS_S_COMPLETE)
243 return (FALSE);
245 * Keep the returned token (unencrypted data) in in_buf.
247 in_buf.length = out_buf.length;
248 in_buf.value = out_buf.value;
251 * If privacy was not used, or if QOP is not what we are
252 * expecting, fail.
254 if (!conf || qop != qop_check)
255 goto fail;
257 } else if (service == rpc_gss_svc_integrity) {
258 if (!__xdr_gss_buf(in_xdrs, &out_buf))
259 return (FALSE);
260 major = gss_verify(&minor, context, &in_buf, &out_buf, &qop);
261 free(out_buf.value);
262 if (major != GSS_S_COMPLETE) {
263 free(in_buf.value);
264 return (FALSE);
268 * If QOP is not what we are expecting, fail.
270 if (qop != qop_check)
271 goto fail;
274 xdrmem_create(&temp_xdrs, in_buf.value, in_buf.length, XDR_DECODE);
277 * The data consists of the sequence number followed by the
278 * arguments. Make sure sequence number is what we are
279 * expecting (i.e., the value in the header).
281 if (!xdr_u_int(&temp_xdrs, &seq_num2))
282 goto fail;
283 if (seq_num2 != seq_num)
284 goto fail;
287 * Deserialize the arguments into xdr_ptr, and release in_buf.
289 if (!(*xdr_func)(&temp_xdrs, xdr_ptr))
290 goto fail;
292 if (service == rpc_gss_svc_privacy)
293 (void) gss_release_buffer(&minor, &in_buf);
294 else
295 free(in_buf.value);
296 XDR_DESTROY(&temp_xdrs);
297 return (TRUE);
298 fail:
299 XDR_DESTROY(&temp_xdrs);
300 if (service == rpc_gss_svc_privacy)
301 (void) gss_release_buffer(&minor, &in_buf);
302 else
303 free(in_buf.value);
304 return (FALSE);
307 /*ARGSUSED*/
309 __find_max_data_length(service, context, qop, max_tp_unit_len)
310 rpc_gss_service_t service;
311 gss_ctx_id_t context;
312 OM_uint32 qop;
313 int max_tp_unit_len;
315 int conf;
316 OM_uint32 maj_stat = GSS_S_COMPLETE, min_stat = 0;
317 OM_uint32 max_input_size;
318 int ret_val = 0;
320 if (service == rpc_gss_svc_integrity || service == rpc_gss_svc_default)
321 conf = 0;
322 else if (service == rpc_gss_svc_privacy)
323 conf = 1;
324 else if (service == rpc_gss_svc_none)
325 return (max_tp_unit_len);
327 maj_stat = gss_wrap_size_limit(&min_stat,
328 context, conf, qop,
329 max_tp_unit_len, &max_input_size);
332 * max_input_size may result in negative value
334 if (maj_stat == GSS_S_COMPLETE) {
335 if ((int)max_input_size <= 0)
336 ret_val = 0;
337 else
338 ret_val = (int)(max_input_size);
339 } else {
340 fprintf(stderr, dgettext(TEXT_DOMAIN,
341 "gss_wrap_size_limit failed in "
342 "__find_max_data_length\n"));
345 return (ret_val);