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
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]
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.
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 $
38 #include <gssapi/gssapi.h>
40 #include <rpc/rpcsec_defs.h>
43 * Miscellaneous XDR routines.
46 __xdr_gss_buf(xdrs
, 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
;
60 bound_len
= (u_int
)-1;
63 if (xdr_bytes(xdrs
, (char **)&buf
->value
, &cast_len
,
65 if (xdrs
->x_op
== XDR_DECODE
)
66 buf
->length
= cast_len
;
75 __xdr_rpc_gss_creds(xdrs
, 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
))
89 __xdr_rpc_gss_init_arg(xdrs
, init_arg
)
91 rpc_gss_init_arg
*init_arg
;
93 if (!__xdr_gss_buf(xdrs
, init_arg
))
99 __xdr_rpc_gss_init_res(xdrs
, init_res
)
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
))
113 * Generic routine to wrap data used by client and server sides.
116 __rpc_gss_wrap_data(service
, qop
, context
, seq_num
, out_xdrs
, xdr_func
,
119 rpc_gss_service_t service
;
120 gss_ctx_id_t context
;
123 bool_t (*xdr_func
)();
127 gss_buffer_desc in_buf
, out_buf
;
135 * Create a temporary XDR/buffer to hold the data to be wrapped.
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"));
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
))
154 * serialize the arguments into tmp memory
156 if (!(*xdr_func
)(&temp_xdrs
, xdr_ptr
))
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
;
169 case rpc_gss_svc_privacy
:
170 if (gss_seal(&minor
, context
, TRUE
, qop
, &in_buf
,
171 &conf_state
, &out_buf
) != GSS_S_COMPLETE
)
173 in_buf
.length
= 0; /* in_buf not needed */
177 case rpc_gss_svc_integrity
:
178 if (gss_sign(&minor
, context
, qop
, &in_buf
,
179 &out_buf
) != GSS_S_COMPLETE
)
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
))
194 if (!__xdr_gss_buf(out_xdrs
, &out_buf
))
198 XDR_DESTROY(&temp_xdrs
);
201 if (out_buf
.length
!= 0)
202 (void) gss_release_buffer(&minor
, &out_buf
);
207 * Generic routine to unwrap data used by client and server sides.
210 __rpc_gss_unwrap_data(service
, context
, seq_num
, qop_check
, in_xdrs
, xdr_func
,
212 rpc_gss_service_t service
;
213 gss_ctx_id_t context
;
217 bool_t (*xdr_func
)();
220 gss_buffer_desc in_buf
, out_buf
;
224 OM_uint32 major
= GSS_S_COMPLETE
, minor
= 0;
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
))
238 if (service
== rpc_gss_svc_privacy
) {
239 major
= gss_unseal(&minor
, context
, &in_buf
, &out_buf
, &conf
,
242 if (major
!= GSS_S_COMPLETE
)
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
254 if (!conf
|| qop
!= qop_check
)
257 } else if (service
== rpc_gss_svc_integrity
) {
258 if (!__xdr_gss_buf(in_xdrs
, &out_buf
))
260 major
= gss_verify(&minor
, context
, &in_buf
, &out_buf
, &qop
);
262 if (major
!= GSS_S_COMPLETE
) {
268 * If QOP is not what we are expecting, fail.
270 if (qop
!= qop_check
)
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
))
283 if (seq_num2
!= seq_num
)
287 * Deserialize the arguments into xdr_ptr, and release in_buf.
289 if (!(*xdr_func
)(&temp_xdrs
, xdr_ptr
))
292 if (service
== rpc_gss_svc_privacy
)
293 (void) gss_release_buffer(&minor
, &in_buf
);
296 XDR_DESTROY(&temp_xdrs
);
299 XDR_DESTROY(&temp_xdrs
);
300 if (service
== rpc_gss_svc_privacy
)
301 (void) gss_release_buffer(&minor
, &in_buf
);
309 __find_max_data_length(service
, context
, qop
, max_tp_unit_len
)
310 rpc_gss_service_t service
;
311 gss_ctx_id_t context
;
316 OM_uint32 maj_stat
= GSS_S_COMPLETE
, min_stat
= 0;
317 OM_uint32 max_input_size
;
320 if (service
== rpc_gss_svc_integrity
|| service
== rpc_gss_svc_default
)
322 else if (service
== rpc_gss_svc_privacy
)
324 else if (service
== rpc_gss_svc_none
)
325 return (max_tp_unit_len
);
327 maj_stat
= gss_wrap_size_limit(&min_stat
,
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)
338 ret_val
= (int)(max_input_size
);
340 fprintf(stderr
, dgettext(TEXT_DOMAIN
,
341 "gss_wrap_size_limit failed in "
342 "__find_max_data_length\n"));