4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
28 * GSSAPI library stub module for gssd.
31 #include <mechglueP.h>
32 #include "gssd_prot.h"
35 #include <sys/systm.h>
36 #include <sys/types.h>
37 #include <sys/cmn_err.h>
39 #include <gssapi/kgssapi_defs.h>
40 #include <sys/debug.h>
44 * Kernel kgssd module debugging aid. The global variable "gss_log"
45 * is a bit mask which allows various types of debugging messages
48 * gss_log & 1 will cause actual failures to be printed.
49 * gss_log & 2 will cause informational messages to be
50 * printed on the client side of kgssd.
51 * gss_log & 4 will cause informational messages to be
52 * printed on the server side of kgssd.
53 * gss_log & 8 will cause informational messages to be
54 * printed on both client and server side of kgssd.
62 extern void prom_printf(const char *, ...);
65 char *server
= "localhost";
67 static OM_uint32
kgss_sign_wrapped(void *, OM_uint32
*, gss_ctx_id_t
, int,
68 gss_buffer_t
, gss_buffer_t
, OM_uint32
);
70 static OM_uint32
kgss_verify_wrapped(void *, OM_uint32
*, gss_ctx_id_t
,
71 gss_buffer_t
, gss_buffer_t
, int *qop_state
, OM_uint32
);
73 static OM_uint32
kgss_seal_wrapped(void *, OM_uint32
*, gss_ctx_id_t
,
74 int, int, gss_buffer_t
, int *, gss_buffer_t
, OM_uint32
);
76 static OM_uint32
kgss_unseal_wrapped(void *, OM_uint32
*, gss_ctx_id_t
,
77 gss_buffer_t
, gss_buffer_t
, int *conf_state
, int *qop_state
,
80 static OM_uint32
kgss_delete_sec_context_wrapped(void *, OM_uint32
*,
81 gssd_ctx_id_t
*, gss_buffer_t
, OM_uint32
);
83 static void __kgss_reset_mech(gss_mechanism
*, gss_OID
);
85 #define DEFAULT_MINOR_STAT ((OM_uint32) ~0)
88 kgss_acquire_cred_wrapped(
89 OM_uint32
*minor_status
,
90 const gss_name_t desired_name
,
92 const gss_OID_set desired_mechs
,
94 gssd_cred_id_t
*output_cred_handle
,
95 gss_OID_set
*actual_mechs
,
98 OM_uint32
*gssd_cred_verifier
)
102 OM_uint32 minor_status_temp
;
103 gss_buffer_desc external_name
;
105 enum clnt_stat client_stat
;
108 gss_acquire_cred_arg arg
;
109 gss_acquire_cred_res res
;
111 /* get the client handle to GSSD */
113 if ((clnt
= getgssd_handle()) == NULL
) {
114 GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n",
116 return (GSS_S_FAILURE
);
119 /* convert the desired name from internal to external format */
121 if (gss_display_name(&minor_status_temp
, desired_name
, &external_name
,
122 &name_type
) != GSS_S_COMPLETE
) {
124 *minor_status
= (OM_uint32
) minor_status_temp
;
125 killgssd_handle(clnt
);
126 GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
127 return ((OM_uint32
) GSS_S_FAILURE
);
131 /* copy the procedure arguments into the rpc arg parameter */
133 arg
.uid
= (OM_uint32
) uid
;
135 arg
.desired_name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
136 arg
.desired_name
.GSS_BUFFER_T_val
= (char *)external_name
.value
;
138 arg
.name_type
.GSS_OID_len
=
139 name_type
== GSS_C_NULL_OID
? 0 : (uint_t
)name_type
->length
;
141 arg
.name_type
.GSS_OID_val
=
142 name_type
== GSS_C_NULL_OID
?
143 NULL
: (char *)name_type
->elements
;
145 arg
.time_req
= time_req
;
147 if (desired_mechs
!= GSS_C_NULL_OID_SET
) {
148 arg
.desired_mechs
.GSS_OID_SET_len
=
149 (uint_t
)desired_mechs
->count
;
150 arg
.desired_mechs
.GSS_OID_SET_val
= (GSS_OID
*)
151 MALLOC(sizeof (GSS_OID
) * desired_mechs
->count
);
153 for (i
= 0; i
< desired_mechs
->count
; i
++) {
154 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
=
155 (uint_t
)desired_mechs
->elements
[i
].length
;
156 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
=
157 (char *)MALLOC(desired_mechs
->elements
[i
].length
);
159 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
160 desired_mechs
->elements
[i
].elements
,
161 desired_mechs
->elements
[i
].length
);
164 arg
.desired_mechs
.GSS_OID_SET_len
= 0;
166 arg
.cred_usage
= cred_usage
;
168 /* call the remote procedure */
170 bzero((caddr_t
)&res
, sizeof (res
));
171 client_stat
= gss_acquire_cred_1(&arg
, &res
, clnt
);
173 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
174 if (desired_mechs
!= GSS_C_NULL_OID_SET
) {
175 for (i
= 0; i
< desired_mechs
->count
; i
++)
176 FREE(arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
177 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
);
178 FREE(arg
.desired_mechs
.GSS_OID_SET_val
,
179 arg
.desired_mechs
.GSS_OID_SET_len
* sizeof (GSS_OID
));
182 if (client_stat
!= RPC_SUCCESS
) {
185 * if the RPC call times out, null out all return arguments,
186 * set minor_status to its maximum value, and return
190 if (minor_status
!= NULL
)
191 *minor_status
= DEFAULT_MINOR_STAT
;
192 if (output_cred_handle
!= NULL
)
193 *output_cred_handle
= 0;
194 if (actual_mechs
!= NULL
)
195 *actual_mechs
= NULL
;
196 if (time_rec
!= NULL
)
199 killgssd_handle(clnt
);
200 GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n");
201 return (GSS_S_FAILURE
);
204 /* copy the rpc results into the return arguments */
206 if (minor_status
!= NULL
)
207 *minor_status
= res
.minor_status
;
209 if (output_cred_handle
!= NULL
&& (res
.status
== GSS_S_COMPLETE
)) {
210 *output_cred_handle
=
211 *((gssd_cred_id_t
*)res
.output_cred_handle
213 *gssd_cred_verifier
= res
.gssd_cred_verifier
;
216 if (res
.status
== GSS_S_COMPLETE
&&
217 res
.actual_mechs
.GSS_OID_SET_len
!= 0 &&
218 actual_mechs
!= NULL
) {
219 *actual_mechs
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
220 (*actual_mechs
)->count
=
221 (int)res
.actual_mechs
.GSS_OID_SET_len
;
222 (*actual_mechs
)->elements
= (gss_OID
)
223 MALLOC(sizeof (gss_OID_desc
) * (*actual_mechs
)->count
);
225 for (i
= 0; i
< (*actual_mechs
)->count
; i
++) {
226 (*actual_mechs
)->elements
[i
].length
= (OM_uint32
)
227 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
;
228 (*actual_mechs
)->elements
[i
].elements
=
229 (void *) MALLOC((*actual_mechs
)->elements
[i
]
231 (void) memcpy((*actual_mechs
)->elements
[i
].elements
,
232 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
233 (*actual_mechs
)->elements
[i
].length
);
236 if (res
.status
== GSS_S_COMPLETE
&& actual_mechs
!= NULL
)
237 (*actual_mechs
) = NULL
;
240 if (time_rec
!= NULL
)
241 *time_rec
= res
.time_rec
;
244 * free the memory allocated for the results and return with the status
245 * received in the rpc call
248 clnt_freeres(clnt
, xdr_gss_acquire_cred_res
, (caddr_t
)&res
);
249 killgssd_handle(clnt
);
256 OM_uint32
*minor_status
,
257 const gss_name_t desired_name
,
259 const gss_OID_set desired_mechs
,
261 gss_cred_id_t
*output_cred_handle
,
262 gss_OID_set
*actual_mechs
,
268 struct kgss_cred
*kcred
;
270 kcred
= KGSS_CRED_ALLOC();
271 *output_cred_handle
= (gss_cred_id_t
)kcred
;
272 err
= kgss_acquire_cred_wrapped(minor_status
, desired_name
, time_req
,
273 desired_mechs
, cred_usage
, &kcred
->gssd_cred
, actual_mechs
,
274 time_rec
, uid
, &kcred
->gssd_cred_verifier
);
275 if (GSS_ERROR(err
)) {
276 KGSS_CRED_FREE(kcred
);
277 *output_cred_handle
= GSS_C_NO_CREDENTIAL
;
283 kgss_add_cred_wrapped(
284 OM_uint32
*minor_status
,
285 gssd_cred_id_t input_cred_handle
,
286 OM_uint32 gssd_cred_verifier
,
287 gss_name_t desired_name
,
288 gss_OID desired_mech_type
,
290 int initiator_time_req
,
291 int acceptor_time_req
,
292 gss_OID_set
*actual_mechs
,
293 OM_uint32
*initiator_time_rec
,
294 OM_uint32
*acceptor_time_rec
,
299 OM_uint32 minor_status_temp
;
300 gss_buffer_desc external_name
;
304 gss_add_cred_arg arg
;
305 gss_add_cred_res res
;
309 * NULL the params here once
310 * If there are errors then we won't
311 * have to do it for every error
315 if (minor_status
!= NULL
)
316 *minor_status
= DEFAULT_MINOR_STAT
;
317 if (actual_mechs
!= NULL
)
318 *actual_mechs
= NULL
;
319 if (initiator_time_rec
!= NULL
)
320 *initiator_time_rec
= 0;
321 if (acceptor_time_rec
!= NULL
)
322 *acceptor_time_rec
= 0;
323 /* get the client handle to GSSD */
325 if ((clnt
= getgssd_handle()) == NULL
) {
326 GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n",
328 return (GSS_S_FAILURE
);
332 /* convert the desired name from internal to external format */
334 if (gss_display_name(&minor_status_temp
, desired_name
, &external_name
,
335 &name_type
) != GSS_S_COMPLETE
) {
337 *minor_status
= (OM_uint32
) minor_status_temp
;
338 killgssd_handle(clnt
);
339 GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
340 return ((OM_uint32
) GSS_S_FAILURE
);
344 /* copy the procedure arguments into the rpc arg parameter */
346 arg
.uid
= (OM_uint32
)uid
;
347 arg
.input_cred_handle
.GSS_CRED_ID_T_len
=
348 input_cred_handle
== GSSD_NO_CREDENTIAL
?
349 0 : (uint_t
)sizeof (gssd_cred_id_t
);
350 arg
.input_cred_handle
.GSS_CRED_ID_T_val
= (char *)&input_cred_handle
;
351 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
352 arg
.desired_name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
353 arg
.desired_name
.GSS_BUFFER_T_val
= (char *)external_name
.value
;
354 arg
.name_type
.GSS_OID_len
=
355 name_type
== GSS_C_NULL_OID
?
356 0 : (uint_t
)name_type
->length
;
357 arg
.name_type
.GSS_OID_val
=
358 name_type
== GSS_C_NULL_OID
?
359 NULL
: (char *)name_type
->elements
;
361 arg
.desired_mech_type
.GSS_OID_len
=
362 (uint_t
)(desired_mech_type
!= GSS_C_NULL_OID
?
363 desired_mech_type
->length
: 0);
364 arg
.desired_mech_type
.GSS_OID_val
=
365 (char *)(desired_mech_type
!= GSS_C_NULL_OID
?
366 desired_mech_type
->elements
: 0);
367 arg
.cred_usage
= cred_usage
;
368 arg
.initiator_time_req
= initiator_time_req
;
369 arg
.acceptor_time_req
= acceptor_time_req
;
371 /* call the remote procedure */
373 bzero((caddr_t
)&res
, sizeof (res
));
374 if (gss_add_cred_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
377 * if the RPC call times out, null out all return arguments,
378 * set minor_status to its maximum value, and return
382 killgssd_handle(clnt
);
383 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
384 GSSLOG0(1, "kgss_add_cred: RPC call times out\n");
385 return (GSS_S_FAILURE
);
388 /* free the allocated memory for the flattened name */
390 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
392 /* copy the rpc results into the return arguments */
394 if (minor_status
!= NULL
)
395 *minor_status
= res
.minor_status
;
397 if (res
.status
== GSS_S_COMPLETE
&&
398 res
.actual_mechs
.GSS_OID_SET_len
!= 0 &&
399 actual_mechs
!= NULL
) {
400 *actual_mechs
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
401 (*actual_mechs
)->count
= (int)res
.actual_mechs
.GSS_OID_SET_len
;
402 (*actual_mechs
)->elements
= (gss_OID
)
403 MALLOC(sizeof (gss_OID_desc
) * (*actual_mechs
)->count
);
405 for (i
= 0; i
< (*actual_mechs
)->count
; i
++) {
406 (*actual_mechs
)->elements
[i
].length
= (OM_uint32
)
407 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
;
408 (*actual_mechs
)->elements
[i
].elements
=
409 (void *) MALLOC((*actual_mechs
)->
411 (void) memcpy((*actual_mechs
)->elements
[i
].elements
,
412 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
413 (*actual_mechs
)->elements
[i
].length
);
416 if (res
.status
== GSS_S_COMPLETE
&& actual_mechs
!= NULL
)
417 (*actual_mechs
) = NULL
;
419 if (initiator_time_rec
!= NULL
)
420 *initiator_time_rec
= res
.acceptor_time_rec
;
421 if (acceptor_time_rec
!= NULL
)
422 *acceptor_time_rec
= res
.acceptor_time_rec
;
425 * free the memory allocated for the results and return with the status
426 * received in the rpc call
429 clnt_freeres(clnt
, xdr_gss_add_cred_res
, (caddr_t
)&res
);
430 killgssd_handle(clnt
);
437 OM_uint32
*minor_status
,
438 gss_cred_id_t input_cred_handle
,
439 gss_name_t desired_name
,
440 gss_OID desired_mech_type
,
442 int initiator_time_req
,
443 int acceptor_time_req
,
444 gss_OID_set
*actual_mechs
,
445 OM_uint32
*initiator_time_rec
,
446 OM_uint32
*acceptor_time_rec
,
451 OM_uint32 gssd_cred_verifier
;
452 gssd_cred_id_t gssd_input_cred_handle
;
454 if (input_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
455 gssd_cred_verifier
= KCRED_TO_CREDV(input_cred_handle
);
456 gssd_input_cred_handle
= KCRED_TO_CRED(input_cred_handle
);
458 gssd_input_cred_handle
= GSSD_NO_CREDENTIAL
;
461 err
= kgss_add_cred_wrapped(minor_status
, gssd_input_cred_handle
,
462 gssd_cred_verifier
, desired_name
, desired_mech_type
,
463 cred_usage
, initiator_time_req
, acceptor_time_req
,
464 actual_mechs
, initiator_time_rec
,
465 acceptor_time_rec
, uid
);
471 kgss_release_cred_wrapped(
472 OM_uint32
*minor_status
,
473 gssd_cred_id_t
*cred_handle
,
475 OM_uint32 gssd_cred_verifier
)
479 gss_release_cred_arg arg
;
480 gss_release_cred_res res
;
483 /* get the client handle to GSSD */
485 if ((clnt
= getgssd_handle()) == NULL
) {
486 GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n",
488 return (GSS_S_FAILURE
);
491 /* copy the procedure arguments into the rpc arg parameter */
493 arg
.uid
= (OM_uint32
)uid
;
494 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
496 if (cred_handle
!= NULL
) {
497 arg
.cred_handle
.GSS_CRED_ID_T_len
=
498 (uint_t
)sizeof (gssd_cred_id_t
);
499 arg
.cred_handle
.GSS_CRED_ID_T_val
= (char *)cred_handle
;
501 arg
.cred_handle
.GSS_CRED_ID_T_len
= 0;
503 /* call the remote procedure */
505 bzero((caddr_t
)&res
, sizeof (res
));
506 if (gss_release_cred_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
509 * if the RPC call times out, null out all return arguments, set
510 * minor_status to its maximum value, and return GSS_S_FAILURE
513 if (minor_status
!= NULL
)
514 *minor_status
= DEFAULT_MINOR_STAT
;
515 if (cred_handle
!= NULL
)
518 killgssd_handle(clnt
);
519 GSSLOG0(1, "kgss_release_cred: RPC call times out\n");
520 return (GSS_S_FAILURE
);
523 /* if the release succeeded, null out the cred_handle */
525 if (res
.status
== GSS_S_COMPLETE
&& cred_handle
!= NULL
)
528 /* copy the rpc results into the return arguments */
530 if (minor_status
!= NULL
)
531 *minor_status
= res
.minor_status
;
533 /* return with status returned in rpc call */
535 killgssd_handle(clnt
);
543 OM_uint32
*minor_status
,
544 gss_cred_id_t
*cred_handle
,
549 struct kgss_cred
*kcred
;
551 if (*cred_handle
== GSS_C_NO_CREDENTIAL
)
552 return (GSS_S_COMPLETE
);
554 kcred
= KCRED_TO_KGSS_CRED(*cred_handle
);
556 err
= kgss_release_cred_wrapped(minor_status
, &kcred
->gssd_cred
,
557 uid
, kcred
->gssd_cred_verifier
);
558 KGSS_CRED_FREE(kcred
);
559 *cred_handle
= GSS_C_NO_CREDENTIAL
;
564 kgss_init_sec_context_wrapped(
565 OM_uint32
*minor_status
,
566 const gssd_cred_id_t claimant_cred_handle
,
567 OM_uint32 gssd_cred_verifier
,
568 gssd_ctx_id_t
*context_handle
,
569 OM_uint32
*gssd_context_verifier
,
570 const gss_name_t target_name
,
571 const gss_OID mech_type
,
574 const gss_channel_bindings_t input_chan_bindings
,
575 const gss_buffer_t input_token
,
576 gss_OID
*actual_mech_type
,
577 gss_buffer_t output_token
,
584 OM_uint32 minor_status_temp
;
585 gss_buffer_desc external_name
;
588 gss_init_sec_context_arg arg
;
589 gss_init_sec_context_res res
;
591 /* get the client handle to GSSD */
593 if ((clnt
= getgssd_handle()) == NULL
) {
595 "kgss_init_sec_context: can't connect to server on %s\n",
597 return (GSS_S_FAILURE
);
600 /* convert the target name from internal to external format */
602 if (gss_display_name(&minor_status_temp
, target_name
,
603 &external_name
, &name_type
) != GSS_S_COMPLETE
) {
605 *minor_status
= (OM_uint32
) minor_status_temp
;
606 killgssd_handle(clnt
);
607 GSSLOG0(1, "kgss_init_sec_context: can't display name\n");
608 return ((OM_uint32
) GSS_S_FAILURE
);
612 /* copy the procedure arguments into the rpc arg parameter */
614 arg
.uid
= (OM_uint32
)uid
;
616 arg
.context_handle
.GSS_CTX_ID_T_len
=
617 *context_handle
== GSSD_NO_CONTEXT
?
618 0 : (uint_t
)sizeof (gssd_ctx_id_t
);
619 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
621 arg
.gssd_context_verifier
= *gssd_context_verifier
;
623 arg
.claimant_cred_handle
.GSS_CRED_ID_T_len
=
624 claimant_cred_handle
== GSSD_NO_CREDENTIAL
?
625 0 : (uint_t
)sizeof (gssd_cred_id_t
);
626 arg
.claimant_cred_handle
.GSS_CRED_ID_T_val
=
627 (char *)&claimant_cred_handle
;
628 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
630 arg
.target_name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
631 arg
.target_name
.GSS_BUFFER_T_val
= (char *)external_name
.value
;
633 arg
.name_type
.GSS_OID_len
=
634 name_type
== GSS_C_NULL_OID
? 0 : (uint_t
)name_type
->length
;
636 arg
.name_type
.GSS_OID_val
=
637 name_type
== GSS_C_NULL_OID
?
638 NULL
: (char *)name_type
->elements
;
640 arg
.mech_type
.GSS_OID_len
= (uint_t
)(mech_type
!= GSS_C_NULL_OID
?
641 mech_type
->length
: 0);
642 arg
.mech_type
.GSS_OID_val
= (char *)(mech_type
!= GSS_C_NULL_OID
?
643 mech_type
->elements
: 0);
645 arg
.req_flags
= req_flags
;
647 arg
.time_req
= time_req
;
649 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
) {
650 arg
.input_chan_bindings
.present
= YES
;
651 arg
.input_chan_bindings
.initiator_addrtype
=
652 input_chan_bindings
->initiator_addrtype
;
653 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
=
654 (uint_t
)input_chan_bindings
->initiator_address
.length
;
655 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
=
656 (void *)input_chan_bindings
->initiator_address
.value
;
657 arg
.input_chan_bindings
.acceptor_addrtype
=
658 input_chan_bindings
->acceptor_addrtype
;
659 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
=
660 (uint_t
)input_chan_bindings
->acceptor_address
.length
;
661 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
=
662 (void *)input_chan_bindings
->acceptor_address
.value
;
663 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
=
664 (uint_t
)input_chan_bindings
->application_data
.length
;
665 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
=
666 (void *)input_chan_bindings
->application_data
.value
;
668 arg
.input_chan_bindings
.present
= NO
;
669 arg
.input_chan_bindings
.initiator_addrtype
= 0;
670 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
= 0;
671 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
= 0;
672 arg
.input_chan_bindings
.acceptor_addrtype
= 0;
673 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
= 0;
674 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
= 0;
675 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
= 0;
676 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
= 0;
679 arg
.input_token
.GSS_BUFFER_T_len
=
680 (uint_t
)(input_token
!= GSS_C_NO_BUFFER
? input_token
->length
: 0);
681 arg
.input_token
.GSS_BUFFER_T_val
=
682 (char *)(input_token
!= GSS_C_NO_BUFFER
? input_token
->value
: 0);
684 /* call the remote procedure */
686 bzero((caddr_t
)&res
, sizeof (res
));
687 if (gss_init_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
690 * if the RPC call times out, null out all return arguments, set
691 * minor_status to its maximum value, and return GSS_S_FAILURE
694 if (minor_status
!= NULL
)
695 *minor_status
= DEFAULT_MINOR_STAT
;
696 if (actual_mech_type
!= NULL
)
697 *actual_mech_type
= NULL
;
698 if (output_token
!= NULL
)
699 output_token
->length
= 0;
700 if (ret_flags
!= NULL
)
702 if (time_rec
!= NULL
)
705 killgssd_handle(clnt
);
706 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
707 GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n");
708 return (GSS_S_FAILURE
);
711 /* free the allocated memory for the flattened name */
713 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
715 if (minor_status
!= NULL
)
716 *minor_status
= res
.minor_status
;
718 if (output_token
!= NULL
&& res
.output_token
.GSS_BUFFER_T_val
!= NULL
) {
719 output_token
->length
=
720 (size_t)res
.output_token
.GSS_BUFFER_T_len
;
721 output_token
->value
=
722 (void *)MALLOC(output_token
->length
);
723 (void) memcpy(output_token
->value
,
724 res
.output_token
.GSS_BUFFER_T_val
, output_token
->length
);
727 /* if the call was successful, copy out the results */
728 if (res
.status
== (OM_uint32
) GSS_S_COMPLETE
||
729 res
.status
== (OM_uint32
) GSS_S_CONTINUE_NEEDED
) {
731 * if the return code is GSS_S_CONTINUE_NEEDED
732 * ignore all return parameters except for
733 * status codes, output token and context handle.
736 *((gssd_ctx_id_t
*)res
.context_handle
.GSS_CTX_ID_T_val
);
737 *gssd_context_verifier
= res
.gssd_context_verifier
;
739 if (res
.status
== GSS_S_COMPLETE
) {
740 if (actual_mech_type
!= NULL
) {
742 (gss_OID
) MALLOC(sizeof (gss_OID_desc
));
743 (*actual_mech_type
)->length
=
744 (OM_UINT32
)res
.actual_mech_type
.GSS_OID_len
;
745 (*actual_mech_type
)->elements
=
746 (void *)MALLOC((*actual_mech_type
)->length
);
747 (void) memcpy((*actual_mech_type
)->elements
,
748 (void *)res
.actual_mech_type
.GSS_OID_val
,
749 (*actual_mech_type
)->length
);
753 if (ret_flags
!= NULL
)
754 *ret_flags
= res
.ret_flags
;
756 if (time_rec
!= NULL
)
757 *time_rec
= res
.time_rec
;
762 * free the memory allocated for the results and return with the status
763 * received in the rpc call
766 clnt_freeres(clnt
, xdr_gss_init_sec_context_res
, (caddr_t
)&res
);
767 killgssd_handle(clnt
);
772 static struct gss_config default_gc
= {
778 NULL
, /* kgss_delete_sec_context_wrapped */
780 NULL
, /* kgss_import_sec_context */
786 kgss_free_oid(gss_OID oid
)
788 FREE(oid
->elements
, oid
->length
);
789 FREE(oid
, sizeof (gss_OID_desc
));
793 kgss_init_sec_context(
794 OM_uint32
*minor_status
,
795 const gss_cred_id_t claimant_cred_handle
,
796 gss_ctx_id_t
*context_handle
,
797 const gss_name_t target_name
,
798 const gss_OID mech_type
,
801 const gss_channel_bindings_t input_chan_bindings
,
802 const gss_buffer_t input_token
,
803 gss_OID
*actual_mech_type
,
804 gss_buffer_t output_token
,
810 struct kgss_ctx
*kctx
;
812 gssd_cred_id_t gssd_cl_cred_handle
;
813 OM_uint32 gssd_cred_verifier
;
816 * If this is an initial call, we'll need to create the
817 * wrapper struct that contains kernel state information, and
818 * a reference to the handle from gssd.
820 if (*context_handle
== GSS_C_NO_CONTEXT
) {
823 * The default gss-mechanism struct as pointers to
824 * the sign/seal/verify/unseal routines that make
827 kctx
->mech
= &default_gc
;
828 kctx
->gssd_ctx
= GSSD_NO_CONTEXT
;
829 *context_handle
= (gss_ctx_id_t
)kctx
;
831 kctx
= (struct kgss_ctx
*)*context_handle
;
833 if (claimant_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
834 gssd_cred_verifier
= KCRED_TO_CREDV(claimant_cred_handle
);
835 gssd_cl_cred_handle
= KCRED_TO_CRED(claimant_cred_handle
);
837 gssd_cl_cred_handle
= GSSD_NO_CREDENTIAL
;
841 * We need to know the resulting mechanism oid, so allocate
842 * it if the caller won't.
844 if (actual_mech_type
== NULL
)
845 actual_mech_type
= &amt
;
847 err
= kgss_init_sec_context_wrapped(minor_status
, gssd_cl_cred_handle
,
848 gssd_cred_verifier
, &kctx
->gssd_ctx
, &kctx
->gssd_ctx_verifier
,
849 target_name
, mech_type
, req_flags
, time_req
,
850 input_chan_bindings
, input_token
, actual_mech_type
,
851 output_token
, ret_flags
, time_rec
, uid
);
853 if (GSS_ERROR(err
)) {
855 *context_handle
= GSS_C_NO_CONTEXT
;
856 } else if (err
== GSS_S_COMPLETE
) {
858 * Now check if there is a kernel module for this
859 * mechanism OID. If so, set the gss_mechanism structure
860 * in the wrapper context to point to the kernel mech.
862 __kgss_reset_mech(&kctx
->mech
, *actual_mech_type
);
865 * If the mech oid was allocated for us, free it.
867 if (&amt
== actual_mech_type
) {
875 kgss_accept_sec_context_wrapped(
876 OM_uint32
*minor_status
,
877 gssd_ctx_id_t
*context_handle
,
878 OM_uint32
*gssd_context_verifier
,
879 const gssd_cred_id_t verifier_cred_handle
,
880 OM_uint32 gssd_cred_verifier
,
881 const gss_buffer_t input_token
,
882 const gss_channel_bindings_t input_chan_bindings
,
883 gss_buffer_t src_name
,
885 gss_buffer_t output_token
,
888 gss_cred_id_t
*delegated_cred_handle
,
893 gss_accept_sec_context_arg arg
;
894 gss_accept_sec_context_res res
;
895 struct kgss_cred
*kcred
;
897 /* get the client handle to GSSD */
899 if ((clnt
= getgssd_handle()) == NULL
) {
901 "kgss_accept_sec_context: can't connect to server on %s\n",
903 return (GSS_S_FAILURE
);
906 /* copy the procedure arguments into the rpc arg parameter */
908 arg
.uid
= (OM_uint32
)uid
;
910 arg
.context_handle
.GSS_CTX_ID_T_len
=
911 *context_handle
== GSSD_NO_CONTEXT
?
912 0 : (uint_t
)sizeof (gssd_ctx_id_t
);
913 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
914 arg
.gssd_context_verifier
= *gssd_context_verifier
;
916 arg
.verifier_cred_handle
.GSS_CRED_ID_T_len
=
917 verifier_cred_handle
== GSSD_NO_CREDENTIAL
?
918 0 : (uint_t
)sizeof (gssd_cred_id_t
);
919 arg
.verifier_cred_handle
.GSS_CRED_ID_T_val
=
920 (char *)&verifier_cred_handle
;
921 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
923 arg
.input_token_buffer
.GSS_BUFFER_T_len
=
924 (uint_t
)(input_token
!= GSS_C_NO_BUFFER
? input_token
->length
: 0);
925 arg
.input_token_buffer
.GSS_BUFFER_T_val
=
926 (char *)(input_token
!= GSS_C_NO_BUFFER
? input_token
->value
: 0);
928 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
) {
929 arg
.input_chan_bindings
.present
= YES
;
930 arg
.input_chan_bindings
.initiator_addrtype
=
931 input_chan_bindings
->initiator_addrtype
;
932 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
=
933 (uint_t
)input_chan_bindings
->initiator_address
.length
;
934 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
=
935 (void *)input_chan_bindings
->initiator_address
.value
;
936 arg
.input_chan_bindings
.acceptor_addrtype
=
937 input_chan_bindings
->acceptor_addrtype
;
938 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
=
939 (uint_t
)input_chan_bindings
->acceptor_address
.length
;
940 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
=
941 (void *)input_chan_bindings
->acceptor_address
.value
;
942 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
=
943 (uint_t
)input_chan_bindings
->application_data
.length
;
944 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
=
945 (void *)input_chan_bindings
->application_data
.value
;
948 arg
.input_chan_bindings
.present
= NO
;
949 arg
.input_chan_bindings
.initiator_addrtype
= 0;
950 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
= 0;
951 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
= 0;
952 arg
.input_chan_bindings
.acceptor_addrtype
= 0;
953 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
= 0;
954 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
= 0;
955 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
= 0;
956 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
= 0;
959 /* set the return parameters in case of errors.... */
960 if (minor_status
!= NULL
)
961 *minor_status
= DEFAULT_MINOR_STAT
;
962 if (src_name
!= NULL
) {
963 src_name
->length
= 0;
964 src_name
->value
= NULL
;
966 if (mech_type
!= NULL
)
968 if (output_token
!= NULL
)
969 output_token
->length
= 0;
970 if (ret_flags
!= NULL
)
972 if (time_rec
!= NULL
)
974 if (delegated_cred_handle
!= NULL
)
975 *delegated_cred_handle
= NULL
;
977 /* call the remote procedure */
979 bzero((caddr_t
)&res
, sizeof (res
));
980 if (gss_accept_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
981 killgssd_handle(clnt
);
982 GSSLOG0(1, "kgss_accept_sec_context: RPC call times out\n");
983 return (GSS_S_FAILURE
);
986 if (minor_status
!= NULL
)
987 *minor_status
= res
.minor_status
;
989 if (output_token
!= NULL
&& res
.output_token
.GSS_BUFFER_T_val
!= NULL
) {
990 output_token
->length
= res
.output_token
.GSS_BUFFER_T_len
;
991 output_token
->value
= (void *)MALLOC(output_token
->length
);
992 (void) memcpy(output_token
->value
,
993 res
.output_token
.GSS_BUFFER_T_val
, output_token
->length
);
996 /* if the call was successful, copy out the results */
998 if (res
.status
== (OM_uint32
)GSS_S_COMPLETE
||
999 res
.status
== (OM_uint32
)GSS_S_CONTINUE_NEEDED
) {
1002 * the only parameters that are ready when we
1003 * get GSS_S_CONTINUE_NEEDED are: minor, ctxt_handle,
1004 * and the output token to send to the peer.
1007 *context_handle
= *((gssd_ctx_id_t
*)
1008 res
.context_handle
.GSS_CTX_ID_T_val
);
1009 *gssd_context_verifier
= res
.gssd_context_verifier
;
1011 /* these other parameters are only ready upon GSS_S_COMPLETE */
1012 if (res
.status
== (OM_uint32
)GSS_S_COMPLETE
) {
1014 if (src_name
!= NULL
) {
1016 res
.src_name
.GSS_BUFFER_T_len
;
1017 src_name
->value
= res
.src_name
.GSS_BUFFER_T_val
;
1018 res
.src_name
.GSS_BUFFER_T_val
= NULL
;
1019 res
.src_name
.GSS_BUFFER_T_len
= 0;
1023 * move mech type returned to mech_type
1024 * for gss_import_name_for_mech()
1026 if (mech_type
!= NULL
) {
1028 (gss_OID
)MALLOC(sizeof (gss_OID_desc
));
1029 (*mech_type
)->length
=
1030 (OM_UINT32
)res
.mech_type
.GSS_OID_len
;
1031 (*mech_type
)->elements
=
1032 (void *)MALLOC((*mech_type
)->length
);
1033 (void) memcpy((*mech_type
)->elements
,
1034 res
.mech_type
.GSS_OID_val
,
1035 (*mech_type
)->length
);
1038 if (ret_flags
!= NULL
)
1039 *ret_flags
= res
.ret_flags
;
1041 if (time_rec
!= NULL
)
1042 *time_rec
= res
.time_rec
;
1044 if ((delegated_cred_handle
!= NULL
) &&
1045 (res
.delegated_cred_handle
.GSS_CRED_ID_T_len
1047 kcred
= KGSS_CRED_ALLOC();
1049 *((gssd_cred_id_t
*)
1050 res
.delegated_cred_handle
1051 .GSS_CRED_ID_T_val
);
1052 kcred
->gssd_cred_verifier
=
1053 res
.gssd_context_verifier
;
1054 *delegated_cred_handle
= (gss_cred_id_t
)kcred
;
1062 * free the memory allocated for the results and return with the status
1063 * received in the rpc call
1066 clnt_freeres(clnt
, xdr_gss_accept_sec_context_res
, (caddr_t
)&res
);
1067 killgssd_handle(clnt
);
1068 return (res
.status
);
1073 kgss_accept_sec_context(
1074 OM_uint32
*minor_status
,
1075 gss_ctx_id_t
*context_handle
,
1076 const gss_cred_id_t verifier_cred_handle
,
1077 const gss_buffer_t input_token
,
1078 const gss_channel_bindings_t input_chan_bindings
,
1079 gss_buffer_t src_name
,
1081 gss_buffer_t output_token
,
1083 OM_uint32
*time_rec
,
1084 gss_cred_id_t
*delegated_cred_handle
,
1088 struct kgss_ctx
*kctx
;
1090 OM_uint32 gssd_cred_verifier
;
1091 gssd_cred_id_t gssd_ver_cred_handle
;
1095 * See kgss_init_sec_context() to get an idea of what is going
1098 if (mech_type
== NULL
)
1101 if (*context_handle
== GSS_C_NO_CONTEXT
) {
1102 kctx
= KGSS_ALLOC();
1103 kctx
->mech
= &default_gc
;
1104 kctx
->gssd_ctx
= GSSD_NO_CONTEXT
;
1105 *context_handle
= (gss_ctx_id_t
)kctx
;
1107 kctx
= (struct kgss_ctx
*)*context_handle
;
1109 if (verifier_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
1110 gssd_cred_verifier
= KCRED_TO_CREDV(verifier_cred_handle
);
1111 gssd_ver_cred_handle
= KCRED_TO_CRED(verifier_cred_handle
);
1113 gssd_ver_cred_handle
= GSSD_NO_CREDENTIAL
;
1116 err
= kgss_accept_sec_context_wrapped(minor_status
,
1117 &kctx
->gssd_ctx
, &kctx
->gssd_ctx_verifier
,
1118 gssd_ver_cred_handle
, gssd_cred_verifier
,
1119 input_token
, input_chan_bindings
, src_name
,
1120 mech_type
, output_token
, ret_flags
,
1121 time_rec
, delegated_cred_handle
, uid
);
1123 if (GSS_ERROR(err
)) {
1125 *context_handle
= GSS_C_NO_CONTEXT
;
1127 } else if (err
== GSS_S_COMPLETE
) {
1128 __kgss_reset_mech(&kctx
->mech
, *mech_type
);
1131 * If the mech oid was allocated for us, free it.
1133 if (&mt
== mech_type
) {
1142 kgss_process_context_token(
1143 OM_uint32
*minor_status
,
1144 const gss_ctx_id_t context_handle
,
1145 gss_buffer_t token_buffer
,
1149 OM_uint32 gssd_context_verifier
;
1150 gssd_ctx_id_t gssd_ctx_handle
;
1151 gss_process_context_token_arg arg
;
1152 gss_process_context_token_res res
;
1154 gssd_context_verifier
= KGSS_CTX_TO_GSSD_CTXV(context_handle
);
1155 gssd_ctx_handle
= (gssd_ctx_id_t
)KGSS_CTX_TO_GSSD_CTX(context_handle
);
1157 /* get the client handle to GSSD */
1159 if ((clnt
= getgssd_handle()) == NULL
) {
1161 "kgss_process_context_token: "
1162 "can't connect to server on %s\n",
1164 return (GSS_S_FAILURE
);
1167 /* copy the procedure arguments into the rpc arg parameter */
1169 arg
.uid
= (OM_uint32
) uid
;
1171 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1172 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&gssd_ctx_handle
;
1173 arg
.gssd_context_verifier
= gssd_context_verifier
;
1174 arg
.token_buffer
.GSS_BUFFER_T_len
= (uint_t
)token_buffer
->length
;
1175 arg
.token_buffer
.GSS_BUFFER_T_val
= (char *)token_buffer
->value
;
1177 /* call the remote procedure */
1179 bzero(&res
, sizeof (res
));
1181 if (gss_process_context_token_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1184 * if the RPC call times out, null out all return arguments, set
1185 * minor_status to its maximum value, and return GSS_S_FAILURE
1188 if (minor_status
!= NULL
)
1189 *minor_status
= DEFAULT_MINOR_STAT
;
1190 GSSLOG0(1, "kgss_process_context_token: RPC call times out\n");
1191 killgssd_handle(clnt
);
1192 return (GSS_S_FAILURE
);
1195 /* copy the rpc results into the return arguments */
1197 if (minor_status
!= NULL
)
1198 *minor_status
= res
.minor_status
;
1200 /* return with status returned in rpc call */
1202 killgssd_handle(clnt
);
1203 return (res
.status
);
1209 kgss_delete_sec_context_wrapped(void *private,
1210 OM_uint32
*minor_status
,
1211 gssd_ctx_id_t
*context_handle
,
1212 gss_buffer_t output_token
,
1213 OM_uint32 gssd_context_verifier
)
1217 gss_delete_sec_context_arg arg
;
1218 gss_delete_sec_context_res res
;
1221 /* get the client handle to GSSD */
1223 if ((clnt
= getgssd_handle()) == NULL
) {
1225 "kgss_delete_sec_context: can't connect to server on %s\n",
1227 return (GSS_S_FAILURE
);
1230 /* copy the procedure arguments into the rpc arg parameter */
1232 arg
.context_handle
.GSS_CTX_ID_T_len
=
1233 *context_handle
== GSSD_NO_CONTEXT
?
1234 0 : (uint_t
)sizeof (gssd_ctx_id_t
);
1235 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
1237 arg
.gssd_context_verifier
= gssd_context_verifier
;
1239 /* call the remote procedure */
1241 bzero((caddr_t
)&res
, sizeof (res
));
1242 if (gss_delete_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1245 * if the RPC call times out, null out all return arguments, set
1246 * minor_status to its maximum value, and return GSS_S_FAILURE
1249 if (minor_status
!= NULL
)
1250 *minor_status
= DEFAULT_MINOR_STAT
;
1251 if (context_handle
!= NULL
)
1252 *context_handle
= 0;
1253 if (output_token
!= NULL
)
1254 output_token
->length
= 0;
1256 killgssd_handle(clnt
);
1257 GSSLOG0(1, "kgssd_delete_sec_context: RPC call times out\n");
1258 return (GSS_S_FAILURE
);
1261 /* copy the rpc results into the return arguments */
1263 if (minor_status
!= NULL
)
1264 *minor_status
= res
.minor_status
;
1266 if (res
.context_handle
.GSS_CTX_ID_T_len
== 0)
1267 *context_handle
= 0;
1270 *((gssd_ctx_id_t
*)res
.context_handle
.GSS_CTX_ID_T_val
);
1272 if (output_token
!= NULL
) {
1273 output_token
->length
= res
.output_token
.GSS_BUFFER_T_len
;
1274 output_token
->value
= res
.output_token
.GSS_BUFFER_T_val
;
1275 res
.output_token
.GSS_BUFFER_T_len
= 0;
1276 res
.output_token
.GSS_BUFFER_T_val
= NULL
;
1280 * free the memory allocated for the results and return with the status
1281 * received in the rpc call
1284 clnt_freeres(clnt
, xdr_gss_delete_sec_context_res
, (caddr_t
)&res
);
1285 killgssd_handle(clnt
);
1286 return (res
.status
);
1291 kgss_delete_sec_context(
1292 OM_uint32
*minor_status
,
1293 gss_ctx_id_t
*context_handle
,
1294 gss_buffer_t output_token
)
1297 struct kgss_ctx
*kctx
;
1299 if (*context_handle
== GSS_C_NO_CONTEXT
) {
1300 GSSLOG0(8, "kgss_delete_sec_context: Null context handle \n");
1301 return (GSS_S_COMPLETE
);
1303 kctx
= (struct kgss_ctx
*)*context_handle
;
1305 if (kctx
->ctx_imported
== FALSE
) {
1306 if (kctx
->gssd_ctx
== GSSD_NO_CONTEXT
) {
1308 *context_handle
= GSS_C_NO_CONTEXT
;
1309 return (GSS_S_COMPLETE
);
1311 err
= kgss_delete_sec_context_wrapped(
1312 KCTX_TO_PRIVATE(*context_handle
),
1316 kctx
->gssd_ctx_verifier
);
1318 if (kctx
->gssd_i_ctx
== (gss_ctx_id_t
)GSS_C_NO_CONTEXT
) {
1320 *context_handle
= GSS_C_NO_CONTEXT
;
1321 return (GSS_S_COMPLETE
);
1323 err
= KGSS_DELETE_SEC_CONTEXT(minor_status
, kctx
,
1324 &kctx
->gssd_i_ctx
, output_token
);
1327 *context_handle
= GSS_C_NO_CONTEXT
;
1334 kgss_export_sec_context_wrapped(
1335 OM_uint32
*minor_status
,
1336 gssd_ctx_id_t
*context_handle
,
1337 gss_buffer_t output_token
,
1338 OM_uint32 gssd_context_verifier
)
1341 gss_export_sec_context_arg arg
;
1342 gss_export_sec_context_res res
;
1345 /* get the client handle to GSSD */
1347 if ((clnt
= getgssd_handle()) == NULL
) {
1348 GSSLOG(1, "kgss_export_sec_context_wrapped :"
1349 " can't connect to server on %s\n", server
);
1350 return (GSS_S_FAILURE
);
1353 /* copy the procedure arguments into the rpc arg parameter */
1355 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1356 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
1357 arg
.gssd_context_verifier
= gssd_context_verifier
;
1359 /* call the remote procedure */
1361 (void) memset(&res
, 0, sizeof (res
));
1362 if (gss_export_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1365 * if the RPC call times out, null out all return arguments,
1366 * set minor_status to its maximum value, and return
1370 if (minor_status
!= NULL
)
1371 *minor_status
= DEFAULT_MINOR_STAT
;
1372 if (context_handle
!= NULL
)
1373 *context_handle
= 0;
1374 if (output_token
!= NULL
)
1375 output_token
->length
= 0;
1376 killgssd_handle(clnt
);
1378 "kgss_export_sec_context_wrapped: RPC call times out\n");
1379 return (GSS_S_FAILURE
);
1382 /* copy the rpc results into the return arguments */
1384 if (minor_status
!= NULL
)
1385 *minor_status
= res
.minor_status
;
1387 if (res
.context_handle
.GSS_CTX_ID_T_len
== 0)
1388 *context_handle
= 0;
1391 *((gssd_ctx_id_t
*)res
.context_handle
.GSS_CTX_ID_T_val
);
1393 if (output_token
!= NULL
) {
1394 output_token
->length
= res
.output_token
.GSS_BUFFER_T_len
;
1395 output_token
->value
=
1396 (void *) MALLOC(output_token
->length
);
1397 (void) memcpy(output_token
->value
,
1398 res
.output_token
.GSS_BUFFER_T_val
,
1399 output_token
->length
);
1403 * free the memory allocated for the results and return with the status
1404 * received in the rpc call
1407 clnt_freeres(clnt
, xdr_gss_export_sec_context_res
, (caddr_t
)&res
);
1408 killgssd_handle(clnt
);
1409 return (res
.status
);
1414 kgss_export_sec_context(
1415 OM_uint32
*minor_status
,
1416 gss_ctx_id_t context_handle
,
1417 gss_buffer_t output_token
)
1419 struct kgss_ctx
*kctx
;
1421 if (context_handle
== GSS_C_NO_CONTEXT
)
1422 return (GSS_S_FAILURE
);
1424 kctx
= (struct kgss_ctx
*)context_handle
;
1429 * If there is a kernel module then import_sec context must be
1430 * supported and we make an upcall to export_sec_context.
1431 * If there is no kernel module then we return an error
1436 if (kctx
->mech
->gss_import_sec_context
) {
1437 GSSLOG0(8, "kgss_export_sec_context: Kernel mod available \n");
1438 return (kgss_export_sec_context_wrapped(minor_status
,
1441 kctx
->gssd_ctx_verifier
));
1446 * This is not the right error value; instead of
1447 * inventing new error we return GSS_S_NAME_NOT_MN
1448 * This error is not returned by the export routine
1451 GSSLOG0(8, "kgss_export_sec_context: Kernel mod "
1453 return (GSS_S_NAME_NOT_MN
);
1459 kgss_import_sec_context(
1460 OM_uint32
* minor_status
,
1461 const gss_buffer_t interprocess_token
,
1462 gss_ctx_id_t context_handle
)
1465 struct kgss_ctx
*kctx
;
1469 gss_buffer_desc token
;
1470 gss_ctx_id_t internal_ctx_id
;
1471 kctx
= (struct kgss_ctx
*)context_handle
;
1473 if (kctx
->gssd_ctx
!= GSSD_NO_CONTEXT
) {
1474 return (GSS_S_FAILURE
);
1477 if (!(KCTX_TO_MECH(context_handle
)->gss_import_sec_context
)) {
1480 * This should never happen
1481 * If Kernel import sec context does not exist the export
1482 * sec context should have caught this and returned an error
1483 * and the caller should not have called this routine
1485 GSSLOG0(1, "import_sec_context called improperly\n");
1486 return (GSS_S_FAILURE
);
1490 if (interprocess_token
->length
== 0 || interprocess_token
->value
== 0)
1491 return (GSS_S_DEFECTIVE_TOKEN
);
1493 status
= GSS_S_FAILURE
;
1495 p
= interprocess_token
->value
;
1497 length
= (length
<< 8) + *p
++;
1498 length
= (length
<< 8) + *p
++;
1499 length
= (length
<< 8) + *p
++;
1503 token
.length
= interprocess_token
->length
- 4 - length
;
1507 * select the approprate underlying mechanism routine and
1511 status
= KGSS_IMPORT_SEC_CONTEXT(minor_status
, &token
, kctx
,
1514 if (status
== GSS_S_COMPLETE
) {
1515 KCTX_TO_I_CTX(kctx
) = internal_ctx_id
;
1516 kctx
->ctx_imported
= TRUE
;
1517 return (GSS_S_COMPLETE
);
1525 OM_uint32
*minor_status
,
1526 const gss_ctx_id_t context_handle
,
1527 OM_uint32
*time_rec
,
1530 return (GSS_S_FAILURE
);
1537 OM_uint32
*minor_status
,
1538 const gss_ctx_id_t ctx_handle
,
1540 const gss_buffer_t message_buffer
,
1541 gss_buffer_t msg_token
,
1542 OM_uint32 gssd_context_verifier
)
1545 gssd_ctx_id_t context_handle
;
1549 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1550 /* get the client handle to GSSD */
1552 if ((clnt
= getgssd_handle()) == NULL
) {
1553 GSSLOG(1, "kgss_sign: can't connect to server on %s\n", server
);
1554 return (GSS_S_FAILURE
);
1557 /* copy the procedure arguments into the rpc arg parameter */
1559 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1560 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1562 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1563 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1564 arg
.gssd_context_verifier
= gssd_context_verifier
;
1566 arg
.qop_req
= qop_req
;
1568 arg
.message_buffer
.GSS_BUFFER_T_len
= (uint_t
)message_buffer
->length
;
1569 arg
.message_buffer
.GSS_BUFFER_T_val
= (char *)message_buffer
->value
;
1571 /* call the remote procedure */
1573 bzero((caddr_t
)&res
, sizeof (res
));
1574 if (gss_sign_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1577 * if the RPC call times out, null out all return arguments, set
1578 * minor_status to its maximum value, and return GSS_S_FAILURE
1581 if (minor_status
!= NULL
)
1582 *minor_status
= DEFAULT_MINOR_STAT
;
1583 if (msg_token
!= NULL
)
1584 msg_token
->length
= 0;
1586 killgssd_handle(clnt
);
1587 GSSLOG0(1, "kgss_sign: RPC call times out\n");
1588 return (GSS_S_FAILURE
);
1591 /* copy the rpc results into the return arguments */
1593 if (minor_status
!= NULL
)
1594 *minor_status
= res
.minor_status
;
1596 if (msg_token
!= NULL
) {
1597 msg_token
->length
= res
.msg_token
.GSS_BUFFER_T_len
;
1598 msg_token
->value
= (void *) MALLOC(msg_token
->length
);
1599 (void) memcpy(msg_token
->value
, res
.msg_token
.GSS_BUFFER_T_val
,
1604 * free the memory allocated for the results and return with the status
1605 * received in the rpc call
1608 clnt_freeres(clnt
, xdr_gss_sign_res
, (caddr_t
)&res
);
1609 killgssd_handle(clnt
);
1610 return (res
.status
);
1616 OM_uint32
*minor_status
,
1617 const gss_ctx_id_t context_handle
,
1619 const gss_buffer_t message_buffer
,
1620 gss_buffer_t msg_token
)
1622 if (context_handle
== GSS_C_NO_CONTEXT
)
1623 return (GSS_S_FAILURE
);
1624 return (KGSS_SIGN(minor_status
, context_handle
, qop_req
,
1625 message_buffer
, msg_token
));
1630 kgss_verify_wrapped(
1632 OM_uint32
*minor_status
,
1633 const gss_ctx_id_t ctx_handle
,
1634 const gss_buffer_t message_buffer
,
1635 const gss_buffer_t token_buffer
,
1637 OM_uint32 gssd_context_verifier
)
1641 gssd_ctx_id_t context_handle
;
1645 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1647 /* get the client handle to GSSD */
1649 if ((clnt
= getgssd_handle()) == NULL
) {
1650 GSSLOG(1, "kgss_verify: can't connect to server on %s\n",
1652 return (GSS_S_FAILURE
);
1655 /* copy the procedure arguments into the rpc arg parameter */
1657 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gss_ctx_id_t
);
1658 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1660 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1661 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1662 arg
.gssd_context_verifier
= gssd_context_verifier
;
1664 arg
.message_buffer
.GSS_BUFFER_T_len
= (uint_t
)message_buffer
->length
;
1665 arg
.message_buffer
.GSS_BUFFER_T_val
= (char *)message_buffer
->value
;
1667 arg
.token_buffer
.GSS_BUFFER_T_len
= (uint_t
)token_buffer
->length
;
1668 arg
.token_buffer
.GSS_BUFFER_T_val
= (char *)token_buffer
->value
;
1670 /* call the remote procedure */
1672 bzero((caddr_t
)&res
, sizeof (res
));
1673 if (gss_verify_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1676 * if the RPC call times out, null out all return arguments, set
1677 * minor_status to its maximum value, and return GSS_S_FAILURE
1680 if (minor_status
!= NULL
)
1681 *minor_status
= DEFAULT_MINOR_STAT
;
1682 if (qop_state
!= NULL
)
1685 killgssd_handle(clnt
);
1686 GSSLOG0(1, "kgss_verify: RPC call times out\n");
1687 return (GSS_S_FAILURE
);
1690 /* copy the rpc results into the return arguments */
1692 if (minor_status
!= NULL
)
1693 *minor_status
= res
.minor_status
;
1695 if (qop_state
!= NULL
)
1696 *qop_state
= res
.qop_state
;
1698 /* return with status returned in rpc call */
1700 killgssd_handle(clnt
);
1701 return (res
.status
);
1707 OM_uint32
*minor_status
,
1708 const gss_ctx_id_t context_handle
,
1709 const gss_buffer_t message_buffer
,
1710 const gss_buffer_t token_buffer
,
1713 if (context_handle
== GSS_C_NO_CONTEXT
)
1714 return (GSS_S_FAILURE
);
1715 return (KGSS_VERIFY(minor_status
, context_handle
,
1716 message_buffer
, token_buffer
, qop_state
));
1723 OM_uint32
*minor_status
,
1724 const gss_ctx_id_t ctx_handle
,
1727 const gss_buffer_t input_message_buffer
,
1729 gss_buffer_t output_message_buffer
,
1730 OM_uint32 gssd_context_verifier
)
1733 gssd_ctx_id_t context_handle
;
1738 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1740 /* get the client handle to GSSD */
1742 if ((clnt
= getgssd_handle()) == NULL
) {
1743 GSSLOG(1, "kgss_seal: can't connect to server on %s\n", server
);
1744 return (GSS_S_FAILURE
);
1747 /* copy the procedure arguments into the rpc arg parameter */
1749 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gss_ctx_id_t
);
1750 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1752 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (OM_uint32
);
1753 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1754 arg
.gssd_context_verifier
= gssd_context_verifier
;
1756 arg
.conf_req_flag
= conf_req_flag
;
1758 arg
.qop_req
= qop_req
;
1760 arg
.input_message_buffer
.GSS_BUFFER_T_len
=
1761 (uint_t
)input_message_buffer
->length
;
1763 arg
.input_message_buffer
.GSS_BUFFER_T_val
=
1764 (char *)input_message_buffer
->value
;
1766 /* call the remote procedure */
1768 bzero((caddr_t
)&res
, sizeof (res
));
1769 if (gss_seal_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1772 * if the RPC call times out, null out all return arguments, set
1773 * minor_status to its maximum value, and return GSS_S_FAILURE
1776 if (minor_status
!= NULL
)
1777 *minor_status
= DEFAULT_MINOR_STAT
;
1778 if (conf_state
!= NULL
)
1780 if (output_message_buffer
!= NULL
)
1781 output_message_buffer
->length
= 0;
1783 killgssd_handle(clnt
);
1784 GSSLOG0(1, "kgss_seal: RPC call times out\n");
1785 return (GSS_S_FAILURE
);
1788 /* copy the rpc results into the return arguments */
1790 if (minor_status
!= NULL
)
1791 *minor_status
= res
.minor_status
;
1793 if (conf_state
!= NULL
)
1794 *conf_state
= res
.conf_state
;
1796 if (output_message_buffer
!= NULL
) {
1797 output_message_buffer
->length
=
1798 res
.output_message_buffer
.GSS_BUFFER_T_len
;
1800 output_message_buffer
->value
=
1801 (void *) MALLOC(output_message_buffer
->length
);
1802 (void) memcpy(output_message_buffer
->value
,
1803 res
.output_message_buffer
.GSS_BUFFER_T_val
,
1804 output_message_buffer
->length
);
1808 * free the memory allocated for the results and return with the status
1809 * received in the rpc call
1812 clnt_freeres(clnt
, xdr_gss_seal_res
, (caddr_t
)&res
);
1813 killgssd_handle(clnt
);
1814 return (res
.status
);
1820 OM_uint32
*minor_status
,
1821 const gss_ctx_id_t context_handle
,
1824 const gss_buffer_t input_message_buffer
,
1826 gss_buffer_t output_message_buffer
)
1828 if (context_handle
== GSS_C_NO_CONTEXT
)
1829 return (GSS_S_FAILURE
);
1830 return (KGSS_SEAL(minor_status
, context_handle
,
1831 conf_req_flag
, qop_req
,
1832 input_message_buffer
, conf_state
,
1833 output_message_buffer
));
1838 kgss_unseal_wrapped(
1840 OM_uint32
*minor_status
,
1841 const gss_ctx_id_t ctx_handle
,
1842 const gss_buffer_t input_message_buffer
,
1843 gss_buffer_t output_message_buffer
,
1846 OM_uint32 gssd_context_verifier
)
1852 gssd_ctx_id_t context_handle
;
1854 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1856 /* get the client handle to GSSD */
1858 if ((clnt
= getgssd_handle()) == NULL
) {
1859 GSSLOG(1, "kgss_unseal: can't connect to server on %s\n",
1861 return (GSS_S_FAILURE
);
1864 /* copy the procedure arguments into the rpc arg parameter */
1866 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gss_ctx_id_t
);
1867 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1869 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1870 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1871 arg
.gssd_context_verifier
= gssd_context_verifier
;
1873 arg
.input_message_buffer
.GSS_BUFFER_T_len
=
1874 (uint_t
)input_message_buffer
->length
;
1876 arg
.input_message_buffer
.GSS_BUFFER_T_val
=
1877 (char *)input_message_buffer
->value
;
1879 /* call the remote procedure */
1881 bzero((caddr_t
)&res
, sizeof (res
));
1882 if (gss_unseal_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1885 * if the RPC call times out, null out all return arguments, set
1886 * minor_status to its maximum value, and return GSS_S_FAILURE
1889 if (minor_status
!= NULL
)
1890 *minor_status
= DEFAULT_MINOR_STAT
;
1891 if (output_message_buffer
!= NULL
)
1892 output_message_buffer
->length
= 0;
1893 if (conf_state
!= NULL
)
1895 if (qop_state
!= NULL
)
1898 killgssd_handle(clnt
);
1899 GSSLOG0(1, "kgss_unseal: RPC call times out\n");
1900 return (GSS_S_FAILURE
);
1903 /* copy the rpc results into the return arguments */
1905 if (minor_status
!= NULL
)
1906 *minor_status
= res
.minor_status
;
1908 if (output_message_buffer
!= NULL
) {
1909 output_message_buffer
->length
=
1910 res
.output_message_buffer
.GSS_BUFFER_T_len
;
1912 output_message_buffer
->value
=
1913 (void *) MALLOC(output_message_buffer
->length
);
1914 (void) memcpy(output_message_buffer
->value
,
1915 res
.output_message_buffer
.GSS_BUFFER_T_val
,
1916 output_message_buffer
->length
);
1919 if (conf_state
!= NULL
)
1920 *conf_state
= res
.conf_state
;
1922 if (qop_state
!= NULL
)
1923 *qop_state
= res
.qop_state
;
1926 * free the memory allocated for the results and return with the
1927 * status received in the rpc call
1930 clnt_freeres(clnt
, xdr_gss_unseal_res
, (caddr_t
)&res
);
1931 killgssd_handle(clnt
);
1932 return (res
.status
);
1937 OM_uint32
*minor_status
,
1938 const gss_ctx_id_t context_handle
,
1939 const gss_buffer_t input_message_buffer
,
1940 const gss_buffer_t output_message_buffer
,
1945 if (context_handle
== GSS_C_NO_CONTEXT
)
1946 return (GSS_S_FAILURE
);
1948 return (KGSS_UNSEAL(minor_status
, context_handle
, input_message_buffer
,
1949 output_message_buffer
, conf_state
, qop_state
));
1953 kgss_display_status(
1954 OM_uint32
*minor_status
,
1955 OM_uint32 status_value
,
1957 const gss_OID mech_type
,
1958 int *message_context
,
1959 gss_buffer_t status_string
,
1964 gss_display_status_arg arg
;
1965 gss_display_status_res res
;
1967 /* get the client handle to GSSD */
1969 if ((clnt
= getgssd_handle()) == NULL
) {
1970 GSSLOG(1, "kgss_display_status: can't connect to server on %s\n",
1972 return (GSS_S_FAILURE
);
1975 /* copy the procedure arguments into the rpc arg parameter */
1977 arg
.uid
= (OM_uint32
) uid
;
1979 arg
.status_value
= status_value
;
1980 arg
.status_type
= status_type
;
1982 arg
.mech_type
.GSS_OID_len
= (uint_t
)(mech_type
!= GSS_C_NULL_OID
?
1983 mech_type
->length
: 0);
1984 arg
.mech_type
.GSS_OID_val
= (char *)(mech_type
!= GSS_C_NULL_OID
?
1985 mech_type
->elements
: 0);
1987 arg
.message_context
= *message_context
;
1989 /* call the remote procedure */
1991 if (message_context
!= NULL
)
1992 *message_context
= 0;
1993 if (status_string
!= NULL
) {
1994 status_string
->length
= 0;
1995 status_string
->value
= NULL
;
1998 bzero((caddr_t
)&res
, sizeof (res
));
1999 if (gss_display_status_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2002 * if the RPC call times out, null out all return arguments, set
2003 * minor_status to its maximum value, and return GSS_S_FAILURE
2006 if (minor_status
!= NULL
)
2007 *minor_status
= DEFAULT_MINOR_STAT
;
2009 killgssd_handle(clnt
);
2010 GSSLOG0(1, "kgss_display_status: RPC call time out\n");
2011 return (GSS_S_FAILURE
);
2015 /* now process the results and pass them back to the caller */
2017 if (res
.status
== GSS_S_COMPLETE
) {
2018 if (minor_status
!= NULL
)
2019 *minor_status
= res
.minor_status
;
2020 if (message_context
!= NULL
)
2021 *message_context
= res
.message_context
;
2022 if (status_string
!= NULL
) {
2023 status_string
->length
=
2024 (size_t)res
.status_string
.GSS_BUFFER_T_len
;
2025 status_string
->value
=
2026 (void *) MALLOC(status_string
->length
);
2027 (void) memcpy(status_string
->value
,
2028 res
.status_string
.GSS_BUFFER_T_val
,
2029 status_string
->length
);
2033 clnt_freeres(clnt
, xdr_gss_display_status_res
, (caddr_t
)&res
);
2034 killgssd_handle(clnt
);
2035 return (res
.status
);
2040 kgss_indicate_mechs(
2041 OM_uint32
*minor_status
,
2042 gss_OID_set
*mech_set
,
2047 gss_indicate_mechs_res res
;
2050 /* get the client handle to GSSD */
2052 if ((clnt
= getgssd_handle()) == NULL
) {
2053 GSSLOG(1, "kgss_indicate_mechs: can't connect to server on %s\n",
2055 return (GSS_S_FAILURE
);
2058 bzero((caddr_t
)&res
, sizeof (res
));
2059 if (gss_indicate_mechs_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2062 * if the RPC call times out, null out all return arguments, set
2063 * minor_status to its maximum value, and return GSS_S_FAILURE
2066 if (minor_status
!= NULL
)
2067 *minor_status
= DEFAULT_MINOR_STAT
;
2068 if (mech_set
!= NULL
)
2071 killgssd_handle(clnt
);
2072 GSSLOG0(1, "kgss_indicate_mechs: RPC call times out\n");
2073 return (GSS_S_FAILURE
);
2076 /* copy the rpc results into the return arguments */
2078 if (minor_status
!= NULL
)
2079 *minor_status
= res
.minor_status
;
2081 if (mech_set
!= NULL
) {
2082 *mech_set
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
2083 (*mech_set
)->count
= res
.mech_set
.GSS_OID_SET_len
;
2084 (*mech_set
)->elements
= (void *)
2085 MALLOC ((*mech_set
)->count
* sizeof (gss_OID_desc
));
2086 for (i
= 0; i
< (*mech_set
)->count
; i
++) {
2087 (*mech_set
)->elements
[i
].length
=
2088 res
.mech_set
.GSS_OID_SET_val
[i
].GSS_OID_len
;
2089 (*mech_set
)->elements
[i
].elements
= (void *)
2090 MALLOC ((*mech_set
)->elements
[i
].length
);
2091 (void) memcpy((*mech_set
)->elements
[i
].elements
,
2092 res
.mech_set
.GSS_OID_SET_val
[i
].GSS_OID_val
,
2093 (*mech_set
)->elements
[i
].length
);
2098 * free the memory allocated for the results and return with the status
2099 * received in the rpc call
2102 clnt_freeres(clnt
, xdr_gss_indicate_mechs_res
, (caddr_t
)&res
);
2103 killgssd_handle(clnt
);
2104 return (res
.status
);
2109 kgss_inquire_cred_wrapped(
2110 OM_uint32
*minor_status
,
2111 const gssd_cred_id_t cred_handle
,
2112 OM_uint32 gssd_cred_verifier
,
2114 OM_uint32
*lifetime
,
2116 gss_OID_set
*mechanisms
,
2121 OM_uint32 minor_status_temp
;
2122 gss_buffer_desc external_name
;
2123 gss_OID_desc name_type
;
2126 gss_inquire_cred_arg arg
;
2127 gss_inquire_cred_res res
;
2130 * NULL the params here once
2131 * If there are errors then we won't
2132 * have to do it for every error
2135 if (minor_status
!= NULL
)
2136 *minor_status
= DEFAULT_MINOR_STAT
;
2139 if (lifetime
!= NULL
)
2141 if (cred_usage
!= NULL
)
2143 if (mechanisms
!= NULL
)
2146 /* get the client handle to GSSD */
2148 if ((clnt
= getgssd_handle()) == NULL
) {
2149 GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
2151 return (GSS_S_FAILURE
);
2155 /* copy the procedure arguments into the rpc arg parameter */
2157 arg
.uid
= (OM_uint32
) uid
;
2159 arg
.cred_handle
.GSS_CRED_ID_T_len
=
2160 cred_handle
== GSSD_NO_CREDENTIAL
?
2161 0 : (uint_t
)sizeof (gssd_cred_id_t
);
2162 arg
.cred_handle
.GSS_CRED_ID_T_val
= (char *)&cred_handle
;
2163 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
2165 /* call the remote procedure */
2167 bzero((caddr_t
)&res
, sizeof (res
));
2168 if (gss_inquire_cred_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2171 * if the RPC call times out
2172 * kill the handle and return GSS_S_FAILURE
2173 * the parameters have been set to NULL already
2176 killgssd_handle(clnt
);
2177 GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
2178 return (GSS_S_FAILURE
);
2181 /* copy the rpc results into the return arguments */
2183 if (minor_status
!= NULL
)
2184 *minor_status
= res
.minor_status
;
2186 /* convert name from external to internal format */
2189 external_name
.length
= res
.name
.GSS_BUFFER_T_len
;
2190 external_name
.value
= res
.name
.GSS_BUFFER_T_val
;
2193 * we can pass a pointer to res structure
2194 * since gss_import_name treats the name_type
2195 * parameter as read only and performs a copy
2198 name_type
.length
= res
.name_type
.GSS_OID_len
;
2199 name_type
.elements
= (void *)res
.name_type
.GSS_OID_val
;
2201 if (gss_import_name(&minor_status_temp
, &external_name
,
2202 &name_type
, name
) != GSS_S_COMPLETE
) {
2204 *minor_status
= (OM_uint32
) minor_status_temp
;
2205 clnt_freeres(clnt
, xdr_gss_inquire_cred_res
,
2207 killgssd_handle(clnt
);
2208 GSSLOG0(1, "kgss_inquire_cred: import name fails\n");
2209 return ((OM_uint32
) GSS_S_FAILURE
);
2213 if (lifetime
!= NULL
)
2214 *lifetime
= res
.lifetime
;
2216 if (cred_usage
!= NULL
)
2217 *cred_usage
= res
.cred_usage
;
2219 if (res
.status
== GSS_S_COMPLETE
&&
2220 res
.mechanisms
.GSS_OID_SET_len
!= 0 &&
2221 mechanisms
!= NULL
) {
2222 *mechanisms
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
2223 (*mechanisms
)->count
=
2224 (int)res
.mechanisms
.GSS_OID_SET_len
;
2225 (*mechanisms
)->elements
= (gss_OID
)
2226 MALLOC(sizeof (gss_OID_desc
) * (*mechanisms
)->count
);
2228 for (i
= 0; i
< (*mechanisms
)->count
; i
++) {
2229 (*mechanisms
)->elements
[i
].length
= (OM_uint32
)
2230 res
.mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_len
;
2231 (*mechanisms
)->elements
[i
].elements
=
2232 (void *) MALLOC((*mechanisms
)->elements
[i
].length
);
2233 (void) memcpy((*mechanisms
)->elements
[i
].elements
,
2234 res
.mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_val
,
2235 (*mechanisms
)->elements
[i
].length
);
2238 if (res
.status
== GSS_S_COMPLETE
&& mechanisms
!= NULL
)
2239 (*mechanisms
) = NULL
;
2242 * free the memory allocated for the results and return with the status
2243 * received in the rpc call
2246 clnt_freeres(clnt
, xdr_gss_inquire_cred_res
, (caddr_t
)&res
);
2247 killgssd_handle(clnt
);
2248 return (res
.status
);
2254 OM_uint32
*minor_status
,
2255 const gss_cred_id_t cred_handle
,
2257 OM_uint32
*lifetime
,
2259 gss_OID_set
* mechanisms
,
2263 OM_uint32 gssd_cred_verifier
;
2264 OM_uint32 gssd_cred_handle
;
2266 gssd_cred_verifier
= KCRED_TO_CREDV(cred_handle
);
2267 gssd_cred_handle
= KCRED_TO_CRED(cred_handle
);
2269 return (kgss_inquire_cred_wrapped(minor_status
,
2270 gssd_cred_handle
, gssd_cred_verifier
,
2271 name
, lifetime
, cred_usage
, mechanisms
, uid
));
2275 kgss_inquire_cred_by_mech_wrapped(
2276 OM_uint32
*minor_status
,
2277 gssd_cred_id_t cred_handle
,
2278 OM_uint32 gssd_cred_verifier
,
2284 gss_inquire_cred_by_mech_arg arg
;
2285 gss_inquire_cred_by_mech_res res
;
2287 /* get the client handle to GSSD */
2289 if ((clnt
= getgssd_handle()) == NULL
) {
2290 GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
2292 return (GSS_S_FAILURE
);
2296 /* copy the procedure arguments into the rpc arg parameter */
2298 arg
.uid
= (OM_uint32
) uid
;
2300 arg
.cred_handle
.GSS_CRED_ID_T_len
=
2301 cred_handle
== GSSD_NO_CREDENTIAL
?
2302 0 : (uint_t
)sizeof (gssd_cred_id_t
);
2303 arg
.cred_handle
.GSS_CRED_ID_T_val
= (char *)&cred_handle
;
2304 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
2306 arg
.mech_type
.GSS_OID_len
=
2307 (uint_t
)(mech_type
!= GSS_C_NULL_OID
?
2308 mech_type
->length
: 0);
2309 arg
.mech_type
.GSS_OID_val
=
2310 (char *)(mech_type
!= GSS_C_NULL_OID
?
2311 mech_type
->elements
: 0);
2312 /* call the remote procedure */
2314 bzero((caddr_t
)&res
, sizeof (res
));
2315 if (gss_inquire_cred_by_mech_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2318 * if the RPC call times out, null out all return arguments, set
2319 * minor_status to its maximum value, and return GSS_S_FAILURE
2322 if (minor_status
!= NULL
)
2323 *minor_status
= DEFAULT_MINOR_STAT
;
2324 killgssd_handle(clnt
);
2325 GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
2326 return (GSS_S_FAILURE
);
2329 /* copy the rpc results into the return arguments */
2331 if (minor_status
!= NULL
)
2332 *minor_status
= res
.minor_status
;
2334 clnt_freeres(clnt
, xdr_gss_inquire_cred_by_mech_res
, (caddr_t
)&res
);
2335 killgssd_handle(clnt
);
2336 return (res
.status
);
2341 kgss_inquire_cred_by_mech(
2342 OM_uint32
*minor_status
,
2343 gss_cred_id_t cred_handle
,
2348 OM_uint32 gssd_cred_verifier
;
2349 OM_uint32 gssd_cred_handle
;
2351 gssd_cred_verifier
= KCRED_TO_CREDV(cred_handle
);
2352 gssd_cred_handle
= KCRED_TO_CRED(cred_handle
);
2354 return (kgss_inquire_cred_by_mech_wrapped(minor_status
,
2355 gssd_cred_handle
, gssd_cred_verifier
,
2360 kgsscred_expname_to_unix_cred(
2361 const gss_buffer_t expName
,
2369 gsscred_expname_to_unix_cred_arg args
;
2370 gsscred_expname_to_unix_cred_res res
;
2372 /* check input/output parameters */
2373 if (expName
== NULL
|| expName
->value
== NULL
)
2374 return (GSS_S_CALL_INACCESSIBLE_READ
);
2377 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
2379 /* NULL out output parameters */
2380 *uidOut
= UID_NOBODY
;
2387 /* get the client handle to gssd */
2388 if ((clnt
= getgssd_handle()) == NULL
) {
2389 GSSLOG(1, "kgsscred_expname_to_unix_cred:"
2390 " can't connect to server on %s\n", server
);
2391 return (GSS_S_FAILURE
);
2394 /* copy the procedure arguments */
2396 args
.expname
.GSS_BUFFER_T_val
= expName
->value
;
2397 args
.expname
.GSS_BUFFER_T_len
= expName
->length
;
2399 /* null out the return buffer and call the remote proc */
2400 bzero(&res
, sizeof (res
));
2402 if (gsscred_expname_to_unix_cred_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2403 killgssd_handle(clnt
);
2405 "kgsscred_expname_to_unix_cred: RPC call times out\n");
2406 return (GSS_S_FAILURE
);
2409 /* copy the results into the result parameters */
2410 if (res
.major
== GSS_S_COMPLETE
) {
2414 if (gids
&& gidsLen
) {
2415 *gids
= res
.gids
.GSSCRED_GIDS_val
;
2416 *gidsLen
= res
.gids
.GSSCRED_GIDS_len
;
2417 res
.gids
.GSSCRED_GIDS_val
= NULL
;
2418 res
.gids
.GSSCRED_GIDS_len
= 0;
2422 /* free RPC results */
2423 clnt_freeres(clnt
, xdr_gsscred_expname_to_unix_cred_res
, (caddr_t
)&res
);
2424 killgssd_handle(clnt
);
2427 } /* kgsscred_expname_to_unix_cred */
2430 kgsscred_name_to_unix_cred(
2431 const gss_name_t intName
,
2432 const gss_OID mechType
,
2440 gsscred_name_to_unix_cred_arg args
;
2441 gsscred_name_to_unix_cred_res res
;
2442 OM_uint32 major
, minor
;
2444 gss_buffer_desc flatName
= GSS_C_EMPTY_BUFFER
;
2446 /* check the input/output parameters */
2447 if (intName
== NULL
|| mechType
== NULL
)
2448 return (GSS_S_CALL_INACCESSIBLE_READ
);
2451 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
2453 /* NULL out the output parameters */
2454 *uidOut
= UID_NOBODY
;
2461 /* get the client handle to gssd */
2462 if ((clnt
= getgssd_handle()) == NULL
) {
2464 "kgsscred_name_to_unix_cred: can't connect to server %s\n",
2466 return (GSS_S_FAILURE
);
2469 /* convert the name to flat representation */
2470 if ((major
= gss_display_name(&minor
, intName
, &flatName
, &nameOid
))
2471 != GSS_S_COMPLETE
) {
2472 killgssd_handle(clnt
);
2473 GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n");
2477 /* set the rpc parameters */
2479 args
.pname
.GSS_BUFFER_T_len
= flatName
.length
;
2480 args
.pname
.GSS_BUFFER_T_val
= flatName
.value
;
2481 args
.name_type
.GSS_OID_len
= nameOid
->length
;
2482 args
.name_type
.GSS_OID_val
= nameOid
->elements
;
2483 args
.mech_type
.GSS_OID_len
= mechType
->length
;
2484 args
.mech_type
.GSS_OID_val
= mechType
->elements
;
2486 /* call the remote procedure */
2487 bzero(&res
, sizeof (res
));
2488 if (gsscred_name_to_unix_cred_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2489 killgssd_handle(clnt
);
2490 (void) gss_release_buffer(&minor
, &flatName
);
2491 GSSLOG0(1, "kgsscred_name_to_unix_cred: RPC call times out\n");
2492 return (GSS_S_FAILURE
);
2495 /* delete the flat name buffer */
2496 (void) gss_release_buffer(&minor
, &flatName
);
2498 /* copy the output parameters on output */
2499 if (res
.major
== GSS_S_COMPLETE
) {
2504 if (gids
&& gidsLen
) {
2505 *gids
= res
.gids
.GSSCRED_GIDS_val
;
2506 *gidsLen
= res
.gids
.GSSCRED_GIDS_len
;
2507 res
.gids
.GSSCRED_GIDS_val
= NULL
;
2508 res
.gids
.GSSCRED_GIDS_len
= 0;
2512 /* delete RPC allocated memory */
2513 clnt_freeres(clnt
, xdr_gsscred_name_to_unix_cred_res
, (caddr_t
)&res
);
2514 killgssd_handle(clnt
);
2517 } /* kgsscred_name_to_unix_cred */
2520 kgss_get_group_info(
2528 gss_get_group_info_arg args
;
2529 gss_get_group_info_res res
;
2532 /* check the output parameters */
2533 if (gidOut
== NULL
|| gids
== NULL
|| gidsLen
== NULL
)
2534 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
2536 /* get the client GSSD handle */
2537 if ((clnt
= getgssd_handle()) == NULL
) {
2539 "kgss_get_group_info: can't connect to server on %s\n",
2541 return (GSS_S_FAILURE
);
2544 /* set the input parameters */
2548 /* call the remote procedure */
2549 bzero(&res
, sizeof (res
));
2550 if (gss_get_group_info_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2551 killgssd_handle(clnt
);
2552 GSSLOG0(1, "kgss_get_group_info: RPC call times out\n");
2553 return (GSS_S_FAILURE
);
2556 /* copy the results */
2557 if (res
.major
== GSS_S_COMPLETE
) {
2559 *gids
= res
.gids
.GSSCRED_GIDS_val
;
2560 *gidsLen
= res
.gids
.GSSCRED_GIDS_len
;
2561 res
.gids
.GSSCRED_GIDS_val
= NULL
;
2562 res
.gids
.GSSCRED_GIDS_len
= 0;
2565 /* no results to free */
2566 killgssd_handle(clnt
);
2569 } /* kgss_get_group_info */
2572 kgss_get_kmod(gss_OID mech_oid
)
2575 gss_get_kmod_arg args
;
2576 gss_get_kmod_res res
;
2579 /* get the client GSSD handle */
2580 if ((clnt
= getgssd_handle()) == NULL
) {
2581 GSSLOG(1, "kgss_get_kmod: can't connect to server on %s\n",
2586 /* set the input parameters */
2587 args
.mech_oid
.GSS_OID_len
= mech_oid
->length
;
2588 args
.mech_oid
.GSS_OID_val
= mech_oid
->elements
;
2590 /* call the remote procedure */
2591 bzero(&res
, sizeof (res
));
2592 if (gss_get_kmod_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2593 killgssd_handle(clnt
);
2594 GSSLOG0(1, "gss_get_kmod_1: RPC call times out\n");
2597 /* no results to free */
2598 killgssd_handle(clnt
);
2600 if (res
.module_follow
== TRUE
) {
2601 return (res
.gss_get_kmod_res_u
.modname
);
2604 } /* kgss_get_kmod */
2606 static gss_mechanism kgss_mech_head
;
2607 static gss_mechanism kgss_mech_tail
;
2608 kmutex_t __kgss_mech_lock
;
2611 * See if there is kernel mechanism module, and if so, attempt to
2612 * load it and reset the pointer (gss_mechanism) to the sign/seal/etc.
2613 * entry points to that of the kernel module.
2616 __kgss_reset_mech(gss_mechanism
*mechp
, gss_OID mech_oid
)
2622 * We can search the list without a mutex, becuase the list never
2623 * shrinks and we always add to the end.
2625 mech
= __kgss_get_mechanism(mech_oid
);
2632 * Get the module name from the kernel.
2634 kmod
= kgss_get_kmod(mech_oid
);
2637 extern int modload(const char *, const char *);
2638 if (modload("misc/kgss", kmod
) < 0) {
2640 * Modload of 'kmod' failed, so log an
2641 * appropriate comment
2643 cmn_err(CE_NOTE
, "kgss_reset_mech: Algorithm modload "
2644 "(%s) failed. Userland gssd will now handle "
2645 "all GSSAPI calls, which may result in "
2646 "reduced performance.\n", kmod
);
2650 * Allocated in the XDR routine called by gss_get_kmod_1().
2652 FREE(kmod
, strlen(kmod
)+1);
2654 mech
= __kgss_get_mechanism(mech_oid
);
2660 * If for some reason the module load didn't take,
2661 * we return anyway and hope that the next context
2662 * creation succeeds.
2669 * No kernel module, so enter this mech oid into the list
2670 * using the default sign/seal/etc. operations that upcall to
2673 mutex_enter(&__kgss_mech_lock
);
2674 mech
= __kgss_get_mechanism(mech_oid
);
2676 mutex_exit(&__kgss_mech_lock
);
2682 * Allocate space for the mechanism entry.
2684 mech
= kmem_zalloc(sizeof (struct gss_config
), KM_SLEEP
);
2687 * Copy basic information from default mechanism struct.
2692 * Record the real mech OID.
2694 mech
->mech_type
.length
= mech_oid
->length
;
2695 mech
->mech_type
.elements
= MALLOC(mech_oid
->length
);
2696 bcopy(mech_oid
->elements
, mech
->mech_type
.elements
, mech_oid
->length
);
2699 * Add it to the table.
2701 __kgss_add_mechanism(mech
);
2702 mutex_exit(&__kgss_mech_lock
);
2707 * Called with __kgss_mech_lock held.
2710 __kgss_add_mechanism(gss_mechanism mech
)
2714 tmp
= kgss_mech_tail
;
2715 kgss_mech_tail
= mech
;
2720 if (kgss_mech_head
== NULL
)
2721 kgss_mech_head
= mech
;
2725 * given the mechs_array and a mechanism OID, return the
2726 * pointer to the mechanism, or NULL if that mechanism is
2730 __kgss_get_mechanism(gss_OID type
)
2734 mech
= kgss_mech_head
;
2737 * Note that a reader can scan this list without the mutex held.
2738 * This is safe because we always append, and never shrink the list.
2739 * Moreover, the entry is fully initialized before it is ever
2740 * added to the list.
2742 while (mech
!= NULL
) {
2743 if ((mech
->mech_type
.length
== type
->length
) &&
2744 (bcmp(mech
->mech_type
.elements
, type
->elements
,
2745 type
->length
) == 0))