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(minor_status
,
98 OM_uint32
*minor_status
;
99 const gss_name_t desired_name
;
101 const gss_OID_set desired_mechs
;
103 gssd_cred_id_t
*output_cred_handle
;
104 gss_OID_set
*actual_mechs
;
107 OM_uint32
*gssd_cred_verifier
;
111 OM_uint32 minor_status_temp
;
112 gss_buffer_desc external_name
;
114 enum clnt_stat client_stat
;
117 gss_acquire_cred_arg arg
;
118 gss_acquire_cred_res res
;
120 /* get the client handle to GSSD */
122 if ((clnt
= getgssd_handle()) == NULL
) {
123 GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n",
125 return (GSS_S_FAILURE
);
128 /* convert the desired name from internal to external format */
130 if (gss_display_name(&minor_status_temp
, desired_name
, &external_name
,
131 &name_type
) != GSS_S_COMPLETE
) {
133 *minor_status
= (OM_uint32
) minor_status_temp
;
134 killgssd_handle(clnt
);
135 GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
136 return ((OM_uint32
) GSS_S_FAILURE
);
140 /* copy the procedure arguments into the rpc arg parameter */
142 arg
.uid
= (OM_uint32
) uid
;
144 arg
.desired_name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
145 arg
.desired_name
.GSS_BUFFER_T_val
= (char *)external_name
.value
;
147 arg
.name_type
.GSS_OID_len
=
148 name_type
== GSS_C_NULL_OID
?
149 0 : (uint_t
)name_type
->length
;
151 arg
.name_type
.GSS_OID_val
=
152 name_type
== GSS_C_NULL_OID
?
153 (char *)NULL
: (char *)name_type
->elements
;
155 arg
.time_req
= time_req
;
157 if (desired_mechs
!= GSS_C_NULL_OID_SET
) {
158 arg
.desired_mechs
.GSS_OID_SET_len
=
159 (uint_t
)desired_mechs
->count
;
160 arg
.desired_mechs
.GSS_OID_SET_val
= (GSS_OID
*)
161 MALLOC(sizeof (GSS_OID
) * desired_mechs
->count
);
163 for (i
= 0; i
< desired_mechs
->count
; i
++) {
164 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
=
165 (uint_t
)desired_mechs
->elements
[i
].length
;
166 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
=
167 (char *)MALLOC(desired_mechs
->elements
[i
].length
);
169 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
170 desired_mechs
->elements
[i
].elements
,
171 desired_mechs
->elements
[i
].length
);
174 arg
.desired_mechs
.GSS_OID_SET_len
= 0;
176 arg
.cred_usage
= cred_usage
;
178 /* call the remote procedure */
180 bzero((caddr_t
)&res
, sizeof (res
));
181 client_stat
= gss_acquire_cred_1(&arg
, &res
, clnt
);
183 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
184 if (desired_mechs
!= GSS_C_NULL_OID_SET
) {
185 for (i
= 0; i
< desired_mechs
->count
; i
++)
186 FREE(arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
187 arg
.desired_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
);
188 FREE(arg
.desired_mechs
.GSS_OID_SET_val
,
189 arg
.desired_mechs
.GSS_OID_SET_len
* sizeof (GSS_OID
));
192 if (client_stat
!= RPC_SUCCESS
) {
195 * if the RPC call times out, null out all return arguments,
196 * set minor_status to its maximum value, and return
200 if (minor_status
!= NULL
)
201 *minor_status
= DEFAULT_MINOR_STAT
;
202 if (output_cred_handle
!= NULL
)
203 *output_cred_handle
= NULL
;
204 if (actual_mechs
!= NULL
)
205 *actual_mechs
= NULL
;
206 if (time_rec
!= NULL
)
209 killgssd_handle(clnt
);
210 GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n");
211 return (GSS_S_FAILURE
);
214 /* copy the rpc results into the return arguments */
216 if (minor_status
!= NULL
)
217 *minor_status
= res
.minor_status
;
219 if (output_cred_handle
!= NULL
&&
220 (res
.status
== GSS_S_COMPLETE
)) {
221 *output_cred_handle
=
222 *((gssd_cred_id_t
*)res
.output_cred_handle
.GSS_CRED_ID_T_val
);
223 *gssd_cred_verifier
= res
.gssd_cred_verifier
;
226 if (res
.status
== GSS_S_COMPLETE
&&
227 res
.actual_mechs
.GSS_OID_SET_len
!= 0 &&
228 actual_mechs
!= NULL
) {
229 *actual_mechs
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
230 (*actual_mechs
)->count
=
231 (int)res
.actual_mechs
.GSS_OID_SET_len
;
232 (*actual_mechs
)->elements
= (gss_OID
)
233 MALLOC(sizeof (gss_OID_desc
) * (*actual_mechs
)->count
);
235 for (i
= 0; i
< (*actual_mechs
)->count
; i
++) {
236 (*actual_mechs
)->elements
[i
].length
= (OM_uint32
)
237 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
;
238 (*actual_mechs
)->elements
[i
].elements
=
239 (void *) MALLOC((*actual_mechs
)->elements
[i
].length
);
240 (void) memcpy((*actual_mechs
)->elements
[i
].elements
,
241 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
242 (*actual_mechs
)->elements
[i
].length
);
245 if (res
.status
== GSS_S_COMPLETE
&&
246 actual_mechs
!= NULL
)
247 (*actual_mechs
) = NULL
;
250 if (time_rec
!= NULL
)
251 *time_rec
= res
.time_rec
;
254 * free the memory allocated for the results and return with the status
255 * received in the rpc call
258 clnt_freeres(clnt
, xdr_gss_acquire_cred_res
, (caddr_t
)&res
);
259 killgssd_handle(clnt
);
265 kgss_acquire_cred(minor_status
,
274 OM_uint32
*minor_status
;
275 const gss_name_t desired_name
;
277 const gss_OID_set desired_mechs
;
279 gss_cred_id_t
*output_cred_handle
;
280 gss_OID_set
*actual_mechs
;
286 struct kgss_cred
*kcred
;
288 kcred
= KGSS_CRED_ALLOC();
289 *output_cred_handle
= (gss_cred_id_t
)kcred
;
290 err
= kgss_acquire_cred_wrapped(minor_status
, desired_name
, time_req
,
291 desired_mechs
, cred_usage
, &kcred
->gssd_cred
, actual_mechs
,
292 time_rec
, uid
, &kcred
->gssd_cred_verifier
);
293 if (GSS_ERROR(err
)) {
294 KGSS_CRED_FREE(kcred
);
295 *output_cred_handle
= GSS_C_NO_CREDENTIAL
;
301 kgss_add_cred_wrapped(minor_status
,
313 OM_uint32
*minor_status
;
314 gssd_cred_id_t input_cred_handle
;
315 OM_uint32 gssd_cred_verifier
;
316 gss_name_t desired_name
;
317 gss_OID desired_mech_type
;
319 int initiator_time_req
;
320 int acceptor_time_req
;
321 gss_OID_set
*actual_mechs
;
322 OM_uint32
*initiator_time_rec
;
323 OM_uint32
*acceptor_time_rec
;
328 OM_uint32 minor_status_temp
;
329 gss_buffer_desc external_name
;
333 gss_add_cred_arg arg
;
334 gss_add_cred_res res
;
338 * NULL the params here once
339 * If there are errors then we won't
340 * have to do it for every error
344 if (minor_status
!= NULL
)
345 *minor_status
= DEFAULT_MINOR_STAT
;
346 if (actual_mechs
!= NULL
)
347 *actual_mechs
= NULL
;
348 if (initiator_time_rec
!= NULL
)
349 *initiator_time_rec
= 0;
350 if (acceptor_time_rec
!= NULL
)
351 *acceptor_time_rec
= 0;
352 /* get the client handle to GSSD */
354 if ((clnt
= getgssd_handle()) == NULL
) {
355 GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n",
357 return (GSS_S_FAILURE
);
361 /* convert the desired name from internal to external format */
363 if (gss_display_name(&minor_status_temp
, desired_name
, &external_name
,
364 &name_type
) != GSS_S_COMPLETE
) {
366 *minor_status
= (OM_uint32
) minor_status_temp
;
367 killgssd_handle(clnt
);
368 GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
369 return ((OM_uint32
) GSS_S_FAILURE
);
373 /* copy the procedure arguments into the rpc arg parameter */
375 arg
.uid
= (OM_uint32
)uid
;
376 arg
.input_cred_handle
.GSS_CRED_ID_T_len
=
377 input_cred_handle
== GSSD_NO_CREDENTIAL
?
378 0 : (uint_t
)sizeof (gssd_cred_id_t
);
379 arg
.input_cred_handle
.GSS_CRED_ID_T_val
= (char *)&input_cred_handle
;
380 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
381 arg
.desired_name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
382 arg
.desired_name
.GSS_BUFFER_T_val
= (char *)external_name
.value
;
383 arg
.name_type
.GSS_OID_len
=
384 name_type
== GSS_C_NULL_OID
?
385 0 : (uint_t
)name_type
->length
;
386 arg
.name_type
.GSS_OID_val
=
387 name_type
== GSS_C_NULL_OID
?
388 (char *)NULL
: (char *)name_type
->elements
;
390 arg
.desired_mech_type
.GSS_OID_len
=
391 (uint_t
)(desired_mech_type
!= GSS_C_NULL_OID
?
392 desired_mech_type
->length
: 0);
393 arg
.desired_mech_type
.GSS_OID_val
=
394 (char *)(desired_mech_type
!= GSS_C_NULL_OID
?
395 desired_mech_type
->elements
: 0);
396 arg
.cred_usage
= cred_usage
;
397 arg
.initiator_time_req
= initiator_time_req
;
398 arg
.acceptor_time_req
= acceptor_time_req
;
400 /* call the remote procedure */
402 bzero((caddr_t
)&res
, sizeof (res
));
403 if (gss_add_cred_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
406 * if the RPC call times out, null out all return arguments,
407 * set minor_status to its maximum value, and return
411 killgssd_handle(clnt
);
412 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
413 GSSLOG0(1, "kgss_add_cred: RPC call times out\n");
414 return (GSS_S_FAILURE
);
417 /* free the allocated memory for the flattened name */
419 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
421 /* copy the rpc results into the return arguments */
423 if (minor_status
!= NULL
)
424 *minor_status
= res
.minor_status
;
426 if (res
.status
== GSS_S_COMPLETE
&&
427 res
.actual_mechs
.GSS_OID_SET_len
!= 0 &&
428 actual_mechs
!= NULL
) {
429 *actual_mechs
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
430 (*actual_mechs
)->count
=
431 (int)res
.actual_mechs
.GSS_OID_SET_len
;
432 (*actual_mechs
)->elements
= (gss_OID
)
433 MALLOC(sizeof (gss_OID_desc
) * (*actual_mechs
)->count
);
435 for (i
= 0; i
< (*actual_mechs
)->count
; i
++) {
436 (*actual_mechs
)->elements
[i
].length
= (OM_uint32
)
437 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
;
438 (*actual_mechs
)->elements
[i
].elements
=
439 (void *) MALLOC((*actual_mechs
)->elements
[i
].length
);
440 (void) memcpy((*actual_mechs
)->elements
[i
].elements
,
441 res
.actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
442 (*actual_mechs
)->elements
[i
].length
);
445 if (res
.status
== GSS_S_COMPLETE
&& actual_mechs
!= NULL
)
446 (*actual_mechs
) = NULL
;
448 if (initiator_time_rec
!= NULL
)
449 *initiator_time_rec
= res
.acceptor_time_rec
;
450 if (acceptor_time_rec
!= NULL
)
451 *acceptor_time_rec
= res
.acceptor_time_rec
;
454 * free the memory allocated for the results and return with the status
455 * received in the rpc call
458 clnt_freeres(clnt
, xdr_gss_add_cred_res
, (caddr_t
)&res
);
459 killgssd_handle(clnt
);
465 kgss_add_cred(minor_status
,
476 OM_uint32
*minor_status
;
477 gss_cred_id_t input_cred_handle
;
478 gss_name_t desired_name
;
479 gss_OID desired_mech_type
;
481 int initiator_time_req
;
482 int acceptor_time_req
;
483 gss_OID_set
*actual_mechs
;
484 OM_uint32
*initiator_time_rec
;
485 OM_uint32
*acceptor_time_rec
;
490 OM_uint32 gssd_cred_verifier
;
491 gssd_cred_id_t gssd_input_cred_handle
;
493 if (input_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
494 gssd_cred_verifier
= KCRED_TO_CREDV(input_cred_handle
);
495 gssd_input_cred_handle
= KCRED_TO_CRED(input_cred_handle
);
497 gssd_input_cred_handle
= GSSD_NO_CREDENTIAL
;
500 err
= kgss_add_cred_wrapped(minor_status
, gssd_input_cred_handle
,
501 gssd_cred_verifier
, desired_name
, desired_mech_type
,
502 cred_usage
, initiator_time_req
, acceptor_time_req
,
503 actual_mechs
, initiator_time_rec
,
504 acceptor_time_rec
, uid
);
510 kgss_release_cred_wrapped(minor_status
,
514 OM_uint32
*minor_status
;
515 gssd_cred_id_t
*cred_handle
;
517 OM_uint32 gssd_cred_verifier
;
521 gss_release_cred_arg arg
;
522 gss_release_cred_res res
;
525 /* get the client handle to GSSD */
527 if ((clnt
= getgssd_handle()) == NULL
) {
528 GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n",
530 return (GSS_S_FAILURE
);
533 /* copy the procedure arguments into the rpc arg parameter */
535 arg
.uid
= (OM_uint32
)uid
;
536 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
538 if (cred_handle
!= NULL
) {
539 arg
.cred_handle
.GSS_CRED_ID_T_len
=
540 (uint_t
)sizeof (gssd_cred_id_t
);
541 arg
.cred_handle
.GSS_CRED_ID_T_val
= (char *)cred_handle
;
543 arg
.cred_handle
.GSS_CRED_ID_T_len
= 0;
545 /* call the remote procedure */
547 bzero((caddr_t
)&res
, sizeof (res
));
548 if (gss_release_cred_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
551 * if the RPC call times out, null out all return arguments, set
552 * minor_status to its maximum value, and return GSS_S_FAILURE
555 if (minor_status
!= NULL
)
556 *minor_status
= DEFAULT_MINOR_STAT
;
557 if (cred_handle
!= NULL
)
560 killgssd_handle(clnt
);
561 GSSLOG0(1, "kgss_release_cred: RPC call times out\n");
562 return (GSS_S_FAILURE
);
565 /* if the release succeeded, null out the cred_handle */
567 if (res
.status
== GSS_S_COMPLETE
&& cred_handle
!= NULL
)
570 /* copy the rpc results into the return arguments */
572 if (minor_status
!= NULL
)
573 *minor_status
= res
.minor_status
;
575 /* return with status returned in rpc call */
577 killgssd_handle(clnt
);
584 kgss_release_cred(minor_status
,
587 OM_uint32
*minor_status
;
588 gss_cred_id_t
*cred_handle
;
594 struct kgss_cred
*kcred
;
596 if (*cred_handle
== GSS_C_NO_CREDENTIAL
)
597 return (GSS_S_COMPLETE
);
599 kcred
= KCRED_TO_KGSS_CRED(*cred_handle
);
601 err
= kgss_release_cred_wrapped(minor_status
, &kcred
->gssd_cred
,
602 uid
, kcred
->gssd_cred_verifier
);
603 KGSS_CRED_FREE(kcred
);
604 *cred_handle
= GSS_C_NO_CREDENTIAL
;
609 kgss_init_sec_context_wrapped(
610 OM_uint32
*minor_status
,
611 const gssd_cred_id_t claimant_cred_handle
,
612 OM_uint32 gssd_cred_verifier
,
613 gssd_ctx_id_t
*context_handle
,
614 OM_uint32
*gssd_context_verifier
,
615 const gss_name_t target_name
,
616 const gss_OID mech_type
,
619 const gss_channel_bindings_t input_chan_bindings
,
620 const gss_buffer_t input_token
,
621 gss_OID
*actual_mech_type
,
622 gss_buffer_t output_token
,
629 OM_uint32 minor_status_temp
;
630 gss_buffer_desc external_name
;
633 gss_init_sec_context_arg arg
;
634 gss_init_sec_context_res res
;
636 /* get the client handle to GSSD */
638 if ((clnt
= getgssd_handle()) == NULL
) {
640 "kgss_init_sec_context: can't connect to server on %s\n",
642 return (GSS_S_FAILURE
);
645 /* convert the target name from internal to external format */
647 if (gss_display_name(&minor_status_temp
, target_name
,
648 &external_name
, &name_type
) != GSS_S_COMPLETE
) {
650 *minor_status
= (OM_uint32
) minor_status_temp
;
651 killgssd_handle(clnt
);
652 GSSLOG0(1, "kgss_init_sec_context: can't display name\n");
653 return ((OM_uint32
) GSS_S_FAILURE
);
657 /* copy the procedure arguments into the rpc arg parameter */
659 arg
.uid
= (OM_uint32
)uid
;
661 arg
.context_handle
.GSS_CTX_ID_T_len
=
662 *context_handle
== GSSD_NO_CONTEXT
?
663 0 : (uint_t
)sizeof (gssd_ctx_id_t
);
664 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
666 arg
.gssd_context_verifier
= *gssd_context_verifier
;
668 arg
.claimant_cred_handle
.GSS_CRED_ID_T_len
=
669 claimant_cred_handle
== GSSD_NO_CREDENTIAL
?
670 0 : (uint_t
)sizeof (gssd_cred_id_t
);
671 arg
.claimant_cred_handle
.GSS_CRED_ID_T_val
=
672 (char *)&claimant_cred_handle
;
673 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
675 arg
.target_name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
676 arg
.target_name
.GSS_BUFFER_T_val
= (char *)external_name
.value
;
678 arg
.name_type
.GSS_OID_len
=
679 name_type
== GSS_C_NULL_OID
? 0 : (uint_t
)name_type
->length
;
681 arg
.name_type
.GSS_OID_val
=
682 name_type
== GSS_C_NULL_OID
?
683 (char *)NULL
: (char *)name_type
->elements
;
685 arg
.mech_type
.GSS_OID_len
= (uint_t
)(mech_type
!= GSS_C_NULL_OID
?
686 mech_type
->length
: 0);
687 arg
.mech_type
.GSS_OID_val
= (char *)(mech_type
!= GSS_C_NULL_OID
?
688 mech_type
->elements
: 0);
690 arg
.req_flags
= req_flags
;
692 arg
.time_req
= time_req
;
694 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
) {
695 arg
.input_chan_bindings
.present
= YES
;
696 arg
.input_chan_bindings
.initiator_addrtype
=
697 input_chan_bindings
->initiator_addrtype
;
698 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
=
699 (uint_t
)input_chan_bindings
->initiator_address
.length
;
700 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
=
701 (void *)input_chan_bindings
->initiator_address
.value
;
702 arg
.input_chan_bindings
.acceptor_addrtype
=
703 input_chan_bindings
->acceptor_addrtype
;
704 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
=
705 (uint_t
)input_chan_bindings
->acceptor_address
.length
;
706 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
=
707 (void *)input_chan_bindings
->acceptor_address
.value
;
708 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
=
709 (uint_t
)input_chan_bindings
->application_data
.length
;
710 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
=
711 (void *)input_chan_bindings
->application_data
.value
;
713 arg
.input_chan_bindings
.present
= NO
;
714 arg
.input_chan_bindings
.initiator_addrtype
= 0;
715 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
= 0;
716 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
= 0;
717 arg
.input_chan_bindings
.acceptor_addrtype
= 0;
718 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
= 0;
719 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
= 0;
720 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
= 0;
721 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
= 0;
724 arg
.input_token
.GSS_BUFFER_T_len
=
725 (uint_t
)(input_token
!= GSS_C_NO_BUFFER
? input_token
->length
: 0);
726 arg
.input_token
.GSS_BUFFER_T_val
=
727 (char *)(input_token
!= GSS_C_NO_BUFFER
? input_token
->value
: 0);
729 /* call the remote procedure */
731 bzero((caddr_t
)&res
, sizeof (res
));
732 if (gss_init_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
735 * if the RPC call times out, null out all return arguments, set
736 * minor_status to its maximum value, and return GSS_S_FAILURE
739 if (minor_status
!= NULL
)
740 *minor_status
= DEFAULT_MINOR_STAT
;
741 if (actual_mech_type
!= NULL
)
742 *actual_mech_type
= NULL
;
743 if (output_token
!= NULL
)
744 output_token
->length
= 0;
745 if (ret_flags
!= NULL
)
747 if (time_rec
!= NULL
)
750 killgssd_handle(clnt
);
751 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
752 GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n");
753 return (GSS_S_FAILURE
);
756 /* free the allocated memory for the flattened name */
758 (void) gss_release_buffer(&minor_status_temp
, &external_name
);
760 if (minor_status
!= NULL
)
761 *minor_status
= res
.minor_status
;
763 if (output_token
!= NULL
&& res
.output_token
.GSS_BUFFER_T_val
!= NULL
) {
764 output_token
->length
=
765 (size_t)res
.output_token
.GSS_BUFFER_T_len
;
766 output_token
->value
=
767 (void *)MALLOC(output_token
->length
);
768 (void) memcpy(output_token
->value
,
769 res
.output_token
.GSS_BUFFER_T_val
, output_token
->length
);
772 /* if the call was successful, copy out the results */
773 if (res
.status
== (OM_uint32
) GSS_S_COMPLETE
||
774 res
.status
== (OM_uint32
) GSS_S_CONTINUE_NEEDED
) {
776 * if the return code is GSS_S_CONTINUE_NEEDED
777 * ignore all return parameters except for
778 * status codes, output token and context handle.
781 *((gssd_ctx_id_t
*)res
.context_handle
.GSS_CTX_ID_T_val
);
782 *gssd_context_verifier
= res
.gssd_context_verifier
;
784 if (res
.status
== GSS_S_COMPLETE
) {
785 if (actual_mech_type
!= NULL
) {
787 (gss_OID
) MALLOC(sizeof (gss_OID_desc
));
788 (*actual_mech_type
)->length
=
789 (OM_UINT32
)res
.actual_mech_type
.GSS_OID_len
;
790 (*actual_mech_type
)->elements
=
791 (void *)MALLOC((*actual_mech_type
)->length
);
792 (void) memcpy((*actual_mech_type
)->elements
,
793 (void *)res
.actual_mech_type
.GSS_OID_val
,
794 (*actual_mech_type
)->length
);
798 if (ret_flags
!= NULL
)
799 *ret_flags
= res
.ret_flags
;
801 if (time_rec
!= NULL
)
802 *time_rec
= res
.time_rec
;
807 * free the memory allocated for the results and return with the status
808 * received in the rpc call
811 clnt_freeres(clnt
, xdr_gss_init_sec_context_res
, (caddr_t
)&res
);
812 killgssd_handle(clnt
);
817 static struct gss_config default_gc
= {
823 NULL
, /* kgss_delete_sec_context_wrapped */
825 NULL
, /* kgss_import_sec_context */
831 kgss_free_oid(gss_OID oid
)
833 FREE(oid
->elements
, oid
->length
);
834 FREE(oid
, sizeof (gss_OID_desc
));
838 kgss_init_sec_context(
839 OM_uint32
*minor_status
,
840 const gss_cred_id_t claimant_cred_handle
,
841 gss_ctx_id_t
*context_handle
,
842 const gss_name_t target_name
,
843 const gss_OID mech_type
,
846 const gss_channel_bindings_t input_chan_bindings
,
847 const gss_buffer_t input_token
,
848 gss_OID
*actual_mech_type
,
849 gss_buffer_t output_token
,
855 struct kgss_ctx
*kctx
;
857 gssd_cred_id_t gssd_cl_cred_handle
;
858 OM_uint32 gssd_cred_verifier
;
861 * If this is an initial call, we'll need to create the
862 * wrapper struct that contains kernel state information, and
863 * a reference to the handle from gssd.
865 if (*context_handle
== GSS_C_NO_CONTEXT
) {
868 * The default gss-mechanism struct as pointers to
869 * the sign/seal/verify/unseal routines that make
872 kctx
->mech
= &default_gc
;
873 kctx
->gssd_ctx
= GSSD_NO_CONTEXT
;
874 *context_handle
= (gss_ctx_id_t
)kctx
;
876 kctx
= (struct kgss_ctx
*)*context_handle
;
878 if (claimant_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
879 gssd_cred_verifier
= KCRED_TO_CREDV(claimant_cred_handle
);
880 gssd_cl_cred_handle
= KCRED_TO_CRED(claimant_cred_handle
);
882 gssd_cl_cred_handle
= GSSD_NO_CREDENTIAL
;
886 * We need to know the resulting mechanism oid, so allocate
887 * it if the caller won't.
889 if (actual_mech_type
== NULL
)
890 actual_mech_type
= &amt
;
892 err
= kgss_init_sec_context_wrapped(minor_status
, gssd_cl_cred_handle
,
893 gssd_cred_verifier
, &kctx
->gssd_ctx
, &kctx
->gssd_ctx_verifier
,
894 target_name
, mech_type
, req_flags
, time_req
,
895 input_chan_bindings
, input_token
, actual_mech_type
,
896 output_token
, ret_flags
, time_rec
, uid
);
898 if (GSS_ERROR(err
)) {
900 *context_handle
= GSS_C_NO_CONTEXT
;
901 } else if (err
== GSS_S_COMPLETE
) {
903 * Now check if there is a kernel module for this
904 * mechanism OID. If so, set the gss_mechanism structure
905 * in the wrapper context to point to the kernel mech.
907 __kgss_reset_mech(&kctx
->mech
, *actual_mech_type
);
910 * If the mech oid was allocated for us, free it.
912 if (&amt
== actual_mech_type
) {
920 kgss_accept_sec_context_wrapped(
921 OM_uint32
*minor_status
,
922 gssd_ctx_id_t
*context_handle
,
923 OM_uint32
*gssd_context_verifier
,
924 const gssd_cred_id_t verifier_cred_handle
,
925 OM_uint32 gssd_cred_verifier
,
926 const gss_buffer_t input_token
,
927 const gss_channel_bindings_t input_chan_bindings
,
928 gss_buffer_t src_name
,
930 gss_buffer_t output_token
,
933 gss_cred_id_t
*delegated_cred_handle
,
938 gss_accept_sec_context_arg arg
;
939 gss_accept_sec_context_res res
;
940 struct kgss_cred
*kcred
;
942 /* get the client handle to GSSD */
944 if ((clnt
= getgssd_handle()) == NULL
) {
946 "kgss_accept_sec_context: can't connect to server on %s\n",
948 return (GSS_S_FAILURE
);
951 /* copy the procedure arguments into the rpc arg parameter */
953 arg
.uid
= (OM_uint32
)uid
;
955 arg
.context_handle
.GSS_CTX_ID_T_len
=
956 *context_handle
== GSSD_NO_CONTEXT
?
957 0 : (uint_t
)sizeof (gssd_ctx_id_t
);
958 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
959 arg
.gssd_context_verifier
= *gssd_context_verifier
;
961 arg
.verifier_cred_handle
.GSS_CRED_ID_T_len
=
962 verifier_cred_handle
== GSSD_NO_CREDENTIAL
?
963 0 : (uint_t
)sizeof (gssd_cred_id_t
);
964 arg
.verifier_cred_handle
.GSS_CRED_ID_T_val
=
965 (char *)&verifier_cred_handle
;
966 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
968 arg
.input_token_buffer
.GSS_BUFFER_T_len
=
969 (uint_t
)(input_token
!= GSS_C_NO_BUFFER
? input_token
->length
: 0);
970 arg
.input_token_buffer
.GSS_BUFFER_T_val
=
971 (char *)(input_token
!= GSS_C_NO_BUFFER
? input_token
->value
: 0);
973 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
) {
974 arg
.input_chan_bindings
.present
= YES
;
975 arg
.input_chan_bindings
.initiator_addrtype
=
976 input_chan_bindings
->initiator_addrtype
;
977 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
=
978 (uint_t
)input_chan_bindings
->initiator_address
.length
;
979 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
=
980 (void *)input_chan_bindings
->initiator_address
.value
;
981 arg
.input_chan_bindings
.acceptor_addrtype
=
982 input_chan_bindings
->acceptor_addrtype
;
983 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
=
984 (uint_t
)input_chan_bindings
->acceptor_address
.length
;
985 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
=
986 (void *)input_chan_bindings
->acceptor_address
.value
;
987 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
=
988 (uint_t
)input_chan_bindings
->application_data
.length
;
989 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
=
990 (void *)input_chan_bindings
->application_data
.value
;
993 arg
.input_chan_bindings
.present
= NO
;
994 arg
.input_chan_bindings
.initiator_addrtype
= 0;
995 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_len
= 0;
996 arg
.input_chan_bindings
.initiator_address
.GSS_BUFFER_T_val
= 0;
997 arg
.input_chan_bindings
.acceptor_addrtype
= 0;
998 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_len
= 0;
999 arg
.input_chan_bindings
.acceptor_address
.GSS_BUFFER_T_val
= 0;
1000 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_len
= 0;
1001 arg
.input_chan_bindings
.application_data
.GSS_BUFFER_T_val
= 0;
1004 /* set the return parameters in case of errors.... */
1005 if (minor_status
!= NULL
)
1006 *minor_status
= DEFAULT_MINOR_STAT
;
1007 if (src_name
!= NULL
) {
1008 src_name
->length
= 0;
1009 src_name
->value
= NULL
;
1011 if (mech_type
!= NULL
)
1013 if (output_token
!= NULL
)
1014 output_token
->length
= 0;
1015 if (ret_flags
!= NULL
)
1017 if (time_rec
!= NULL
)
1019 if (delegated_cred_handle
!= NULL
)
1020 *delegated_cred_handle
= NULL
;
1022 /* call the remote procedure */
1024 bzero((caddr_t
)&res
, sizeof (res
));
1025 if (gss_accept_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1026 killgssd_handle(clnt
);
1027 GSSLOG0(1, "kgss_accept_sec_context: RPC call times out\n");
1028 return (GSS_S_FAILURE
);
1031 if (minor_status
!= NULL
)
1032 *minor_status
= res
.minor_status
;
1034 if (output_token
!= NULL
&& res
.output_token
.GSS_BUFFER_T_val
!= NULL
) {
1035 output_token
->length
= res
.output_token
.GSS_BUFFER_T_len
;
1036 output_token
->value
= (void *)MALLOC(output_token
->length
);
1037 (void) memcpy(output_token
->value
,
1038 res
.output_token
.GSS_BUFFER_T_val
, output_token
->length
);
1041 /* if the call was successful, copy out the results */
1043 if (res
.status
== (OM_uint32
)GSS_S_COMPLETE
||
1044 res
.status
== (OM_uint32
)GSS_S_CONTINUE_NEEDED
) {
1047 * the only parameters that are ready when we
1048 * get GSS_S_CONTINUE_NEEDED are: minor, ctxt_handle,
1049 * and the output token to send to the peer.
1052 *context_handle
= *((gssd_ctx_id_t
*)
1053 res
.context_handle
.GSS_CTX_ID_T_val
);
1054 *gssd_context_verifier
= res
.gssd_context_verifier
;
1056 /* these other parameters are only ready upon GSS_S_COMPLETE */
1057 if (res
.status
== (OM_uint32
)GSS_S_COMPLETE
) {
1059 if (src_name
!= NULL
) {
1061 res
.src_name
.GSS_BUFFER_T_len
;
1062 src_name
->value
= res
.src_name
.GSS_BUFFER_T_val
;
1063 res
.src_name
.GSS_BUFFER_T_val
= NULL
;
1064 res
.src_name
.GSS_BUFFER_T_len
= 0;
1068 * move mech type returned to mech_type
1069 * for gss_import_name_for_mech()
1071 if (mech_type
!= NULL
) {
1073 (gss_OID
)MALLOC(sizeof (gss_OID_desc
));
1074 (*mech_type
)->length
=
1075 (OM_UINT32
)res
.mech_type
.GSS_OID_len
;
1076 (*mech_type
)->elements
=
1077 (void *)MALLOC((*mech_type
)->length
);
1078 (void) memcpy((*mech_type
)->elements
,
1079 res
.mech_type
.GSS_OID_val
,
1080 (*mech_type
)->length
);
1083 if (ret_flags
!= NULL
)
1084 *ret_flags
= res
.ret_flags
;
1086 if (time_rec
!= NULL
)
1087 *time_rec
= res
.time_rec
;
1089 if ((delegated_cred_handle
!= NULL
) &&
1090 (res
.delegated_cred_handle
.GSS_CRED_ID_T_len
1092 kcred
= KGSS_CRED_ALLOC();
1094 *((gssd_cred_id_t
*)
1095 res
.delegated_cred_handle
.GSS_CRED_ID_T_val
);
1096 kcred
->gssd_cred_verifier
=
1097 res
.gssd_context_verifier
;
1098 *delegated_cred_handle
= (gss_cred_id_t
)kcred
;
1106 * free the memory allocated for the results and return with the status
1107 * received in the rpc call
1110 clnt_freeres(clnt
, xdr_gss_accept_sec_context_res
, (caddr_t
)&res
);
1111 killgssd_handle(clnt
);
1112 return (res
.status
);
1117 kgss_accept_sec_context(
1118 OM_uint32
*minor_status
,
1119 gss_ctx_id_t
*context_handle
,
1120 const gss_cred_id_t verifier_cred_handle
,
1121 const gss_buffer_t input_token
,
1122 const gss_channel_bindings_t input_chan_bindings
,
1123 gss_buffer_t src_name
,
1125 gss_buffer_t output_token
,
1127 OM_uint32
*time_rec
,
1128 gss_cred_id_t
*delegated_cred_handle
,
1132 struct kgss_ctx
*kctx
;
1134 OM_uint32 gssd_cred_verifier
;
1135 gssd_cred_id_t gssd_ver_cred_handle
;
1139 * See kgss_init_sec_context() to get an idea of what is going
1142 if (mech_type
== NULL
)
1145 if (*context_handle
== GSS_C_NO_CONTEXT
) {
1146 kctx
= KGSS_ALLOC();
1147 kctx
->mech
= &default_gc
;
1148 kctx
->gssd_ctx
= GSSD_NO_CONTEXT
;
1149 *context_handle
= (gss_ctx_id_t
)kctx
;
1151 kctx
= (struct kgss_ctx
*)*context_handle
;
1153 if (verifier_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
1154 gssd_cred_verifier
= KCRED_TO_CREDV(verifier_cred_handle
);
1155 gssd_ver_cred_handle
= KCRED_TO_CRED(verifier_cred_handle
);
1157 gssd_ver_cred_handle
= GSSD_NO_CREDENTIAL
;
1160 err
= kgss_accept_sec_context_wrapped(minor_status
,
1161 &kctx
->gssd_ctx
, &kctx
->gssd_ctx_verifier
,
1162 gssd_ver_cred_handle
, gssd_cred_verifier
,
1163 input_token
, input_chan_bindings
, src_name
,
1164 mech_type
, output_token
, ret_flags
,
1165 time_rec
, delegated_cred_handle
, uid
);
1167 if (GSS_ERROR(err
)) {
1169 *context_handle
= GSS_C_NO_CONTEXT
;
1171 } else if (err
== GSS_S_COMPLETE
) {
1172 __kgss_reset_mech(&kctx
->mech
, *mech_type
);
1175 * If the mech oid was allocated for us, free it.
1177 if (&mt
== mech_type
) {
1186 kgss_process_context_token(minor_status
,
1190 OM_uint32
*minor_status
;
1191 const gss_ctx_id_t context_handle
;
1192 gss_buffer_t token_buffer
;
1196 OM_uint32 gssd_context_verifier
;
1197 gssd_ctx_id_t gssd_ctx_handle
;
1198 gss_process_context_token_arg arg
;
1199 gss_process_context_token_res res
;
1201 gssd_context_verifier
= KGSS_CTX_TO_GSSD_CTXV(context_handle
);
1202 gssd_ctx_handle
= (gssd_ctx_id_t
)KGSS_CTX_TO_GSSD_CTX(context_handle
);
1204 /* get the client handle to GSSD */
1206 if ((clnt
= getgssd_handle()) == NULL
) {
1208 "kgss_process_context_token: can't connect to server on %s\n",
1210 return (GSS_S_FAILURE
);
1213 /* copy the procedure arguments into the rpc arg parameter */
1215 arg
.uid
= (OM_uint32
) uid
;
1217 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1218 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&gssd_ctx_handle
;
1219 arg
.gssd_context_verifier
= gssd_context_verifier
;
1220 arg
.token_buffer
.GSS_BUFFER_T_len
= (uint_t
)token_buffer
->length
;
1221 arg
.token_buffer
.GSS_BUFFER_T_val
= (char *)token_buffer
->value
;
1223 /* call the remote procedure */
1225 bzero(&res
, sizeof (res
));
1227 if (gss_process_context_token_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1230 * if the RPC call times out, null out all return arguments, set
1231 * minor_status to its maximum value, and return GSS_S_FAILURE
1234 if (minor_status
!= NULL
)
1235 *minor_status
= DEFAULT_MINOR_STAT
;
1236 GSSLOG0(1, "kgss_process_context_token: RPC call times out\n");
1237 killgssd_handle(clnt
);
1238 return (GSS_S_FAILURE
);
1241 /* copy the rpc results into the return arguments */
1243 if (minor_status
!= NULL
)
1244 *minor_status
= res
.minor_status
;
1246 /* return with status returned in rpc call */
1248 killgssd_handle(clnt
);
1249 return (res
.status
);
1255 kgss_delete_sec_context_wrapped(void *private,
1256 OM_uint32
*minor_status
,
1257 gssd_ctx_id_t
*context_handle
,
1258 gss_buffer_t output_token
,
1259 OM_uint32 gssd_context_verifier
)
1265 gss_delete_sec_context_arg arg
;
1266 gss_delete_sec_context_res res
;
1269 /* get the client handle to GSSD */
1271 if ((clnt
= getgssd_handle()) == NULL
) {
1273 "kgss_delete_sec_context: can't connect to server on %s\n",
1275 return (GSS_S_FAILURE
);
1278 /* copy the procedure arguments into the rpc arg parameter */
1280 arg
.context_handle
.GSS_CTX_ID_T_len
=
1281 *context_handle
== GSSD_NO_CONTEXT
?
1282 0 : (uint_t
)sizeof (gssd_ctx_id_t
);
1283 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
1285 arg
.gssd_context_verifier
= gssd_context_verifier
;
1287 /* call the remote procedure */
1289 bzero((caddr_t
)&res
, sizeof (res
));
1290 if (gss_delete_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1293 * if the RPC call times out, null out all return arguments, set
1294 * minor_status to its maximum value, and return GSS_S_FAILURE
1297 if (minor_status
!= NULL
)
1298 *minor_status
= DEFAULT_MINOR_STAT
;
1299 if (context_handle
!= NULL
)
1300 *context_handle
= NULL
;
1301 if (output_token
!= NULL
)
1302 output_token
->length
= 0;
1304 killgssd_handle(clnt
);
1305 GSSLOG0(1, "kgssd_delete_sec_context: RPC call times out\n");
1306 return (GSS_S_FAILURE
);
1309 /* copy the rpc results into the return arguments */
1311 if (minor_status
!= NULL
)
1312 *minor_status
= res
.minor_status
;
1314 if (res
.context_handle
.GSS_CTX_ID_T_len
== 0)
1315 *context_handle
= NULL
;
1318 *((gssd_ctx_id_t
*)res
.context_handle
.GSS_CTX_ID_T_val
);
1320 if (output_token
!= NULL
) {
1321 output_token
->length
= res
.output_token
.GSS_BUFFER_T_len
;
1322 output_token
->value
= res
.output_token
.GSS_BUFFER_T_val
;
1323 res
.output_token
.GSS_BUFFER_T_len
= 0;
1324 res
.output_token
.GSS_BUFFER_T_val
= NULL
;
1328 * free the memory allocated for the results and return with the status
1329 * received in the rpc call
1332 clnt_freeres(clnt
, xdr_gss_delete_sec_context_res
, (caddr_t
)&res
);
1333 killgssd_handle(clnt
);
1334 return (res
.status
);
1339 kgss_delete_sec_context(
1340 OM_uint32
*minor_status
,
1341 gss_ctx_id_t
*context_handle
,
1342 gss_buffer_t output_token
)
1345 struct kgss_ctx
*kctx
;
1347 if (*context_handle
== GSS_C_NO_CONTEXT
) {
1348 GSSLOG0(8, "kgss_delete_sec_context: Null context handle \n");
1349 return (GSS_S_COMPLETE
);
1351 kctx
= (struct kgss_ctx
*)*context_handle
;
1353 if (kctx
->ctx_imported
== FALSE
) {
1354 if (kctx
->gssd_ctx
== GSSD_NO_CONTEXT
) {
1356 *context_handle
= GSS_C_NO_CONTEXT
;
1357 return (GSS_S_COMPLETE
);
1359 err
= kgss_delete_sec_context_wrapped(
1360 KCTX_TO_PRIVATE(*context_handle
),
1364 kctx
->gssd_ctx_verifier
);
1366 if (kctx
->gssd_i_ctx
== (gss_ctx_id_t
)GSS_C_NO_CONTEXT
) {
1368 *context_handle
= GSS_C_NO_CONTEXT
;
1369 return (GSS_S_COMPLETE
);
1371 err
= KGSS_DELETE_SEC_CONTEXT(minor_status
, kctx
,
1372 &kctx
->gssd_i_ctx
, output_token
);
1375 *context_handle
= GSS_C_NO_CONTEXT
;
1382 kgss_export_sec_context_wrapped(minor_status
,
1385 gssd_context_verifier
)
1386 OM_uint32
*minor_status
;
1387 gssd_ctx_id_t
*context_handle
;
1388 gss_buffer_t output_token
;
1389 OM_uint32 gssd_context_verifier
;
1392 gss_export_sec_context_arg arg
;
1393 gss_export_sec_context_res res
;
1396 /* get the client handle to GSSD */
1398 if ((clnt
= getgssd_handle()) == NULL
) {
1399 GSSLOG(1, "kgss_export_sec_context_wrapped :"
1400 " can't connect to server on %s\n", server
);
1401 return (GSS_S_FAILURE
);
1404 /* copy the procedure arguments into the rpc arg parameter */
1406 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1407 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)context_handle
;
1408 arg
.gssd_context_verifier
= gssd_context_verifier
;
1410 /* call the remote procedure */
1412 (void) memset(&res
, 0, sizeof (res
));
1413 if (gss_export_sec_context_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1416 * if the RPC call times out, null out all return arguments,
1417 * set minor_status to its maximum value, and return
1421 if (minor_status
!= NULL
)
1422 *minor_status
= DEFAULT_MINOR_STAT
;
1423 if (context_handle
!= NULL
)
1424 *context_handle
= NULL
;
1425 if (output_token
!= NULL
)
1426 output_token
->length
= 0;
1427 killgssd_handle(clnt
);
1429 "kgss_export_sec_context_wrapped: RPC call times out\n");
1430 return (GSS_S_FAILURE
);
1433 /* copy the rpc results into the return arguments */
1435 if (minor_status
!= NULL
)
1436 *minor_status
= res
.minor_status
;
1438 if (res
.context_handle
.GSS_CTX_ID_T_len
== 0)
1439 *context_handle
= NULL
;
1442 *((gssd_ctx_id_t
*)res
.context_handle
.GSS_CTX_ID_T_val
);
1444 if (output_token
!= NULL
) {
1445 output_token
->length
= res
.output_token
.GSS_BUFFER_T_len
;
1446 output_token
->value
=
1447 (void *) MALLOC(output_token
->length
);
1448 (void) memcpy(output_token
->value
,
1449 res
.output_token
.GSS_BUFFER_T_val
,
1450 output_token
->length
);
1454 * free the memory allocated for the results and return with the status
1455 * received in the rpc call
1458 clnt_freeres(clnt
, xdr_gss_export_sec_context_res
, (caddr_t
)&res
);
1459 killgssd_handle(clnt
);
1460 return (res
.status
);
1465 kgss_export_sec_context(minor_status
,
1468 OM_uint32
*minor_status
;
1469 gss_ctx_id_t context_handle
;
1470 gss_buffer_t output_token
;
1472 struct kgss_ctx
*kctx
;
1474 if (context_handle
== GSS_C_NO_CONTEXT
)
1475 return (GSS_S_FAILURE
);
1477 kctx
= (struct kgss_ctx
*)context_handle
;
1482 * If there is a kernel module then import_sec context must be
1483 * supported and we make an upcall to export_sec_context.
1484 * If there is no kernel module then we return an error
1489 if (kctx
->mech
->gss_import_sec_context
) {
1490 GSSLOG0(8, "kgss_export_sec_context: Kernel mod available \n");
1491 return (kgss_export_sec_context_wrapped(minor_status
,
1494 kctx
->gssd_ctx_verifier
));
1499 * This is not the right error value; instead of
1500 * inventing new error we return GSS_S_NAME_NOT_MN
1501 * This error is not returned by the export routine
1504 GSSLOG0(8, "kgss_export_sec_context: Kernel mod "
1506 return (GSS_S_NAME_NOT_MN
);
1512 kgss_import_sec_context(minor_status
,
1516 OM_uint32
* minor_status
;
1517 const gss_buffer_t interprocess_token
;
1518 gss_ctx_id_t context_handle
;
1522 struct kgss_ctx
*kctx
;
1526 gss_buffer_desc token
;
1527 gss_ctx_id_t internal_ctx_id
;
1528 kctx
= (struct kgss_ctx
*)context_handle
;
1530 if (kctx
->gssd_ctx
!= GSSD_NO_CONTEXT
) {
1531 return (GSS_S_FAILURE
);
1534 if (!(KCTX_TO_MECH(context_handle
)->gss_import_sec_context
)) {
1537 * This should never happen
1538 * If Kernel import sec context does not exist the export
1539 * sec context should have caught this and returned an error
1540 * and the caller should not have called this routine
1542 GSSLOG0(1, "import_sec_context called improperly\n");
1543 return (GSS_S_FAILURE
);
1547 if (interprocess_token
->length
== 0 || interprocess_token
->value
== 0)
1548 return (GSS_S_DEFECTIVE_TOKEN
);
1550 status
= GSS_S_FAILURE
;
1552 p
= interprocess_token
->value
;
1554 length
= (length
<< 8) + *p
++;
1555 length
= (length
<< 8) + *p
++;
1556 length
= (length
<< 8) + *p
++;
1560 token
.length
= interprocess_token
->length
- 4 - length
;
1564 * select the approprate underlying mechanism routine and
1568 status
= KGSS_IMPORT_SEC_CONTEXT(minor_status
, &token
, kctx
,
1571 if (status
== GSS_S_COMPLETE
) {
1572 KCTX_TO_I_CTX(kctx
) = internal_ctx_id
;
1573 kctx
->ctx_imported
= TRUE
;
1574 return (GSS_S_COMPLETE
);
1581 kgss_context_time(minor_status
,
1585 OM_uint32
*minor_status
;
1586 const gss_ctx_id_t context_handle
;
1587 OM_uint32
*time_rec
;
1590 return (GSS_S_FAILURE
);
1595 kgss_sign_wrapped(void *private,
1596 OM_uint32
*minor_status
,
1597 const gss_ctx_id_t ctx_handle
,
1599 const gss_buffer_t message_buffer
,
1600 gss_buffer_t msg_token
,
1601 OM_uint32 gssd_context_verifier
)
1604 gssd_ctx_id_t context_handle
;
1608 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1609 /* get the client handle to GSSD */
1611 if ((clnt
= getgssd_handle()) == NULL
) {
1612 GSSLOG(1, "kgss_sign: can't connect to server on %s\n", server
);
1613 return (GSS_S_FAILURE
);
1616 /* copy the procedure arguments into the rpc arg parameter */
1618 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1619 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1621 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1622 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1623 arg
.gssd_context_verifier
= gssd_context_verifier
;
1625 arg
.qop_req
= qop_req
;
1627 arg
.message_buffer
.GSS_BUFFER_T_len
= (uint_t
)message_buffer
->length
;
1628 arg
.message_buffer
.GSS_BUFFER_T_val
= (char *)message_buffer
->value
;
1630 /* call the remote procedure */
1632 bzero((caddr_t
)&res
, sizeof (res
));
1633 if (gss_sign_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1636 * if the RPC call times out, null out all return arguments, set
1637 * minor_status to its maximum value, and return GSS_S_FAILURE
1640 if (minor_status
!= NULL
)
1641 *minor_status
= DEFAULT_MINOR_STAT
;
1642 if (msg_token
!= NULL
)
1643 msg_token
->length
= 0;
1645 killgssd_handle(clnt
);
1646 GSSLOG0(1, "kgss_sign: RPC call times out\n");
1647 return (GSS_S_FAILURE
);
1650 /* copy the rpc results into the return arguments */
1652 if (minor_status
!= NULL
)
1653 *minor_status
= res
.minor_status
;
1655 if (msg_token
!= NULL
) {
1656 msg_token
->length
= res
.msg_token
.GSS_BUFFER_T_len
;
1657 msg_token
->value
= (void *) MALLOC(msg_token
->length
);
1658 (void) memcpy(msg_token
->value
, res
.msg_token
.GSS_BUFFER_T_val
,
1663 * free the memory allocated for the results and return with the status
1664 * received in the rpc call
1667 clnt_freeres(clnt
, xdr_gss_sign_res
, (caddr_t
)&res
);
1668 killgssd_handle(clnt
);
1669 return (res
.status
);
1675 OM_uint32
*minor_status
,
1676 const gss_ctx_id_t context_handle
,
1678 const gss_buffer_t message_buffer
,
1679 gss_buffer_t msg_token
)
1681 if (context_handle
== GSS_C_NO_CONTEXT
)
1682 return (GSS_S_FAILURE
);
1683 return (KGSS_SIGN(minor_status
, context_handle
, qop_req
,
1684 message_buffer
, msg_token
));
1689 kgss_verify_wrapped(void *private,
1690 OM_uint32
*minor_status
,
1691 const gss_ctx_id_t ctx_handle
,
1692 const gss_buffer_t message_buffer
,
1693 const gss_buffer_t token_buffer
,
1695 OM_uint32 gssd_context_verifier
)
1699 gssd_ctx_id_t context_handle
;
1703 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1705 /* get the client handle to GSSD */
1707 if ((clnt
= getgssd_handle()) == NULL
) {
1708 GSSLOG(1, "kgss_verify: can't connect to server on %s\n",
1710 return (GSS_S_FAILURE
);
1713 /* copy the procedure arguments into the rpc arg parameter */
1715 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gss_ctx_id_t
);
1716 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1718 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1719 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1720 arg
.gssd_context_verifier
= gssd_context_verifier
;
1722 arg
.message_buffer
.GSS_BUFFER_T_len
= (uint_t
)message_buffer
->length
;
1723 arg
.message_buffer
.GSS_BUFFER_T_val
= (char *)message_buffer
->value
;
1725 arg
.token_buffer
.GSS_BUFFER_T_len
= (uint_t
)token_buffer
->length
;
1726 arg
.token_buffer
.GSS_BUFFER_T_val
= (char *)token_buffer
->value
;
1728 /* call the remote procedure */
1730 bzero((caddr_t
)&res
, sizeof (res
));
1731 if (gss_verify_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1734 * if the RPC call times out, null out all return arguments, set
1735 * minor_status to its maximum value, and return GSS_S_FAILURE
1738 if (minor_status
!= NULL
)
1739 *minor_status
= DEFAULT_MINOR_STAT
;
1740 if (qop_state
!= NULL
)
1743 killgssd_handle(clnt
);
1744 GSSLOG0(1, "kgss_verify: RPC call times out\n");
1745 return (GSS_S_FAILURE
);
1748 /* copy the rpc results into the return arguments */
1750 if (minor_status
!= NULL
)
1751 *minor_status
= res
.minor_status
;
1753 if (qop_state
!= NULL
)
1754 *qop_state
= res
.qop_state
;
1756 /* return with status returned in rpc call */
1758 killgssd_handle(clnt
);
1759 return (res
.status
);
1764 kgss_verify(OM_uint32
*minor_status
,
1765 const gss_ctx_id_t context_handle
,
1766 const gss_buffer_t message_buffer
,
1767 const gss_buffer_t token_buffer
,
1770 if (context_handle
== GSS_C_NO_CONTEXT
)
1771 return (GSS_S_FAILURE
);
1772 return (KGSS_VERIFY(minor_status
, context_handle
,
1773 message_buffer
, token_buffer
, qop_state
));
1778 kgss_seal_wrapped(void *private,
1779 OM_uint32
*minor_status
,
1780 const gss_ctx_id_t ctx_handle
,
1783 const gss_buffer_t input_message_buffer
,
1785 gss_buffer_t output_message_buffer
,
1786 OM_uint32 gssd_context_verifier
)
1789 gssd_ctx_id_t context_handle
;
1794 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1796 /* get the client handle to GSSD */
1798 if ((clnt
= getgssd_handle()) == NULL
) {
1799 GSSLOG(1, "kgss_seal: can't connect to server on %s\n", server
);
1800 return (GSS_S_FAILURE
);
1803 /* copy the procedure arguments into the rpc arg parameter */
1805 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gss_ctx_id_t
);
1806 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1808 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (OM_uint32
);
1809 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1810 arg
.gssd_context_verifier
= gssd_context_verifier
;
1812 arg
.conf_req_flag
= conf_req_flag
;
1814 arg
.qop_req
= qop_req
;
1816 arg
.input_message_buffer
.GSS_BUFFER_T_len
=
1817 (uint_t
)input_message_buffer
->length
;
1819 arg
.input_message_buffer
.GSS_BUFFER_T_val
=
1820 (char *)input_message_buffer
->value
;
1822 /* call the remote procedure */
1824 bzero((caddr_t
)&res
, sizeof (res
));
1825 if (gss_seal_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1828 * if the RPC call times out, null out all return arguments, set
1829 * minor_status to its maximum value, and return GSS_S_FAILURE
1832 if (minor_status
!= NULL
)
1833 *minor_status
= DEFAULT_MINOR_STAT
;
1834 if (conf_state
!= NULL
)
1836 if (output_message_buffer
!= NULL
)
1837 output_message_buffer
->length
= 0;
1839 killgssd_handle(clnt
);
1840 GSSLOG0(1, "kgss_seal: RPC call times out\n");
1841 return (GSS_S_FAILURE
);
1844 /* copy the rpc results into the return arguments */
1846 if (minor_status
!= NULL
)
1847 *minor_status
= res
.minor_status
;
1849 if (conf_state
!= NULL
)
1850 *conf_state
= res
.conf_state
;
1852 if (output_message_buffer
!= NULL
) {
1853 output_message_buffer
->length
=
1854 res
.output_message_buffer
.GSS_BUFFER_T_len
;
1856 output_message_buffer
->value
=
1857 (void *) MALLOC(output_message_buffer
->length
);
1858 (void) memcpy(output_message_buffer
->value
,
1859 res
.output_message_buffer
.GSS_BUFFER_T_val
,
1860 output_message_buffer
->length
);
1864 * free the memory allocated for the results and return with the status
1865 * received in the rpc call
1868 clnt_freeres(clnt
, xdr_gss_seal_res
, (caddr_t
)&res
);
1869 killgssd_handle(clnt
);
1870 return (res
.status
);
1875 kgss_seal(OM_uint32
*minor_status
,
1876 const gss_ctx_id_t context_handle
,
1879 const gss_buffer_t input_message_buffer
,
1881 gss_buffer_t output_message_buffer
)
1884 if (context_handle
== GSS_C_NO_CONTEXT
)
1885 return (GSS_S_FAILURE
);
1886 return (KGSS_SEAL(minor_status
, context_handle
,
1887 conf_req_flag
, qop_req
,
1888 input_message_buffer
, conf_state
,
1889 output_message_buffer
));
1894 kgss_unseal_wrapped(void *private,
1895 OM_uint32
*minor_status
,
1896 const gss_ctx_id_t ctx_handle
,
1897 const gss_buffer_t input_message_buffer
,
1898 gss_buffer_t output_message_buffer
,
1901 OM_uint32 gssd_context_verifier
)
1907 gssd_ctx_id_t context_handle
;
1909 context_handle
= (gssd_ctx_id_t
)KCTX_TO_GSSD_CTX(ctx_handle
);
1911 /* get the client handle to GSSD */
1913 if ((clnt
= getgssd_handle()) == NULL
) {
1914 GSSLOG(1, "kgss_unseal: can't connect to server on %s\n",
1916 return (GSS_S_FAILURE
);
1919 /* copy the procedure arguments into the rpc arg parameter */
1921 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gss_ctx_id_t
);
1922 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1924 arg
.context_handle
.GSS_CTX_ID_T_len
= (uint_t
)sizeof (gssd_ctx_id_t
);
1925 arg
.context_handle
.GSS_CTX_ID_T_val
= (char *)&context_handle
;
1926 arg
.gssd_context_verifier
= gssd_context_verifier
;
1928 arg
.input_message_buffer
.GSS_BUFFER_T_len
=
1929 (uint_t
)input_message_buffer
->length
;
1931 arg
.input_message_buffer
.GSS_BUFFER_T_val
=
1932 (char *)input_message_buffer
->value
;
1934 /* call the remote procedure */
1936 bzero((caddr_t
)&res
, sizeof (res
));
1937 if (gss_unseal_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
1940 * if the RPC call times out, null out all return arguments, set
1941 * minor_status to its maximum value, and return GSS_S_FAILURE
1944 if (minor_status
!= NULL
)
1945 *minor_status
= DEFAULT_MINOR_STAT
;
1946 if (output_message_buffer
!= NULL
)
1947 output_message_buffer
->length
= 0;
1948 if (conf_state
!= NULL
)
1950 if (qop_state
!= NULL
)
1953 killgssd_handle(clnt
);
1954 GSSLOG0(1, "kgss_unseal: RPC call times out\n");
1955 return (GSS_S_FAILURE
);
1958 /* copy the rpc results into the return arguments */
1960 if (minor_status
!= NULL
)
1961 *minor_status
= res
.minor_status
;
1963 if (output_message_buffer
!= NULL
) {
1964 output_message_buffer
->length
=
1965 res
.output_message_buffer
.GSS_BUFFER_T_len
;
1967 output_message_buffer
->value
=
1968 (void *) MALLOC(output_message_buffer
->length
);
1969 (void) memcpy(output_message_buffer
->value
,
1970 res
.output_message_buffer
.GSS_BUFFER_T_val
,
1971 output_message_buffer
->length
);
1974 if (conf_state
!= NULL
)
1975 *conf_state
= res
.conf_state
;
1977 if (qop_state
!= NULL
)
1978 *qop_state
= res
.qop_state
;
1981 * free the memory allocated for the results and return with the
1982 * status received in the rpc call
1985 clnt_freeres(clnt
, xdr_gss_unseal_res
, (caddr_t
)&res
);
1986 killgssd_handle(clnt
);
1987 return (res
.status
);
1991 kgss_unseal(OM_uint32
*minor_status
,
1992 const gss_ctx_id_t context_handle
,
1993 const gss_buffer_t input_message_buffer
,
1994 const gss_buffer_t output_message_buffer
,
1999 if (context_handle
== GSS_C_NO_CONTEXT
)
2000 return (GSS_S_FAILURE
);
2002 return (KGSS_UNSEAL(minor_status
, context_handle
, input_message_buffer
,
2003 output_message_buffer
, conf_state
, qop_state
));
2007 kgss_display_status(minor_status
,
2014 OM_uint32
*minor_status
;
2015 OM_uint32 status_value
;
2017 const gss_OID mech_type
;
2018 int *message_context
;
2019 gss_buffer_t status_string
;
2024 gss_display_status_arg arg
;
2025 gss_display_status_res res
;
2027 /* get the client handle to GSSD */
2029 if ((clnt
= getgssd_handle()) == NULL
) {
2030 GSSLOG(1, "kgss_display_status: can't connect to server on %s\n",
2032 return (GSS_S_FAILURE
);
2035 /* copy the procedure arguments into the rpc arg parameter */
2037 arg
.uid
= (OM_uint32
) uid
;
2039 arg
.status_value
= status_value
;
2040 arg
.status_type
= status_type
;
2042 arg
.mech_type
.GSS_OID_len
= (uint_t
)(mech_type
!= GSS_C_NULL_OID
?
2043 mech_type
->length
: 0);
2044 arg
.mech_type
.GSS_OID_val
= (char *)(mech_type
!= GSS_C_NULL_OID
?
2045 mech_type
->elements
: 0);
2047 arg
.message_context
= *message_context
;
2049 /* call the remote procedure */
2051 if (message_context
!= NULL
)
2052 *message_context
= 0;
2053 if (status_string
!= NULL
) {
2054 status_string
->length
= 0;
2055 status_string
->value
= NULL
;
2058 bzero((caddr_t
)&res
, sizeof (res
));
2059 if (gss_display_status_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
;
2069 killgssd_handle(clnt
);
2070 GSSLOG0(1, "kgss_display_status: RPC call time out\n");
2071 return (GSS_S_FAILURE
);
2075 /* now process the results and pass them back to the caller */
2077 if (res
.status
== GSS_S_COMPLETE
) {
2078 if (minor_status
!= NULL
)
2079 *minor_status
= res
.minor_status
;
2080 if (message_context
!= NULL
)
2081 *message_context
= res
.message_context
;
2082 if (status_string
!= NULL
) {
2083 status_string
->length
=
2084 (size_t)res
.status_string
.GSS_BUFFER_T_len
;
2085 status_string
->value
=
2086 (void *) MALLOC(status_string
->length
);
2087 (void) memcpy(status_string
->value
,
2088 res
.status_string
.GSS_BUFFER_T_val
,
2089 status_string
->length
);
2093 clnt_freeres(clnt
, xdr_gss_display_status_res
, (caddr_t
)&res
);
2094 killgssd_handle(clnt
);
2095 return (res
.status
);
2100 kgss_indicate_mechs(minor_status
,
2103 OM_uint32
*minor_status
;
2104 gss_OID_set
*mech_set
;
2109 gss_indicate_mechs_res res
;
2112 /* get the client handle to GSSD */
2114 if ((clnt
= getgssd_handle()) == NULL
) {
2115 GSSLOG(1, "kgss_indicate_mechs: can't connect to server on %s\n",
2117 return (GSS_S_FAILURE
);
2120 bzero((caddr_t
)&res
, sizeof (res
));
2121 if (gss_indicate_mechs_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2124 * if the RPC call times out, null out all return arguments, set
2125 * minor_status to its maximum value, and return GSS_S_FAILURE
2128 if (minor_status
!= NULL
)
2129 *minor_status
= DEFAULT_MINOR_STAT
;
2130 if (mech_set
!= NULL
)
2133 killgssd_handle(clnt
);
2134 GSSLOG0(1, "kgss_indicate_mechs: RPC call times out\n");
2135 return (GSS_S_FAILURE
);
2138 /* copy the rpc results into the return arguments */
2140 if (minor_status
!= NULL
)
2141 *minor_status
= res
.minor_status
;
2143 if (mech_set
!= NULL
) {
2144 *mech_set
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
2145 (*mech_set
)->count
= res
.mech_set
.GSS_OID_SET_len
;
2146 (*mech_set
)->elements
= (void *)
2147 MALLOC ((*mech_set
)->count
* sizeof (gss_OID_desc
));
2148 for (i
= 0; i
< (*mech_set
)->count
; i
++) {
2149 (*mech_set
)->elements
[i
].length
=
2150 res
.mech_set
.GSS_OID_SET_val
[i
].GSS_OID_len
;
2151 (*mech_set
)->elements
[i
].elements
= (void *)
2152 MALLOC ((*mech_set
)->elements
[i
].length
);
2153 (void) memcpy((*mech_set
)->elements
[i
].elements
,
2154 res
.mech_set
.GSS_OID_SET_val
[i
].GSS_OID_val
,
2155 (*mech_set
)->elements
[i
].length
);
2160 * free the memory allocated for the results and return with the status
2161 * received in the rpc call
2164 clnt_freeres(clnt
, xdr_gss_indicate_mechs_res
, (caddr_t
)&res
);
2165 killgssd_handle(clnt
);
2166 return (res
.status
);
2171 kgss_inquire_cred_wrapped(minor_status
,
2179 OM_uint32
*minor_status
;
2180 const gssd_cred_id_t cred_handle
;
2181 OM_uint32 gssd_cred_verifier
;
2183 OM_uint32
*lifetime
;
2185 gss_OID_set
*mechanisms
;
2190 OM_uint32 minor_status_temp
;
2191 gss_buffer_desc external_name
;
2192 gss_OID_desc name_type
;
2195 gss_inquire_cred_arg arg
;
2196 gss_inquire_cred_res res
;
2199 * NULL the params here once
2200 * If there are errors then we won't
2201 * have to do it for every error
2204 if (minor_status
!= NULL
)
2205 *minor_status
= DEFAULT_MINOR_STAT
;
2208 if (lifetime
!= NULL
)
2210 if (cred_usage
!= NULL
)
2212 if (mechanisms
!= NULL
)
2215 /* get the client handle to GSSD */
2217 if ((clnt
= getgssd_handle()) == NULL
) {
2218 GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
2220 return (GSS_S_FAILURE
);
2224 /* copy the procedure arguments into the rpc arg parameter */
2226 arg
.uid
= (OM_uint32
) uid
;
2228 arg
.cred_handle
.GSS_CRED_ID_T_len
=
2229 cred_handle
== GSSD_NO_CREDENTIAL
?
2230 0 : (uint_t
)sizeof (gssd_cred_id_t
);
2231 arg
.cred_handle
.GSS_CRED_ID_T_val
= (char *)&cred_handle
;
2232 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
2234 /* call the remote procedure */
2236 bzero((caddr_t
)&res
, sizeof (res
));
2237 if (gss_inquire_cred_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2240 * if the RPC call times out
2241 * kill the handle and return GSS_S_FAILURE
2242 * the parameters have been set to NULL already
2245 killgssd_handle(clnt
);
2246 GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
2247 return (GSS_S_FAILURE
);
2250 /* copy the rpc results into the return arguments */
2252 if (minor_status
!= NULL
)
2253 *minor_status
= res
.minor_status
;
2255 /* convert name from external to internal format */
2258 external_name
.length
= res
.name
.GSS_BUFFER_T_len
;
2259 external_name
.value
= res
.name
.GSS_BUFFER_T_val
;
2262 * we can pass a pointer to res structure
2263 * since gss_import_name treats the name_type
2264 * parameter as read only and performs a copy
2267 name_type
.length
= res
.name_type
.GSS_OID_len
;
2268 name_type
.elements
= (void *)res
.name_type
.GSS_OID_val
;
2270 if (gss_import_name(&minor_status_temp
, &external_name
,
2271 &name_type
, name
) != GSS_S_COMPLETE
) {
2273 *minor_status
= (OM_uint32
) minor_status_temp
;
2274 clnt_freeres(clnt
, xdr_gss_inquire_cred_res
,
2276 killgssd_handle(clnt
);
2277 GSSLOG0(1, "kgss_inquire_cred: import name fails\n");
2278 return ((OM_uint32
) GSS_S_FAILURE
);
2282 if (lifetime
!= NULL
)
2283 *lifetime
= res
.lifetime
;
2285 if (cred_usage
!= NULL
)
2286 *cred_usage
= res
.cred_usage
;
2288 if (res
.status
== GSS_S_COMPLETE
&&
2289 res
.mechanisms
.GSS_OID_SET_len
!= 0 &&
2290 mechanisms
!= NULL
) {
2291 *mechanisms
= (gss_OID_set
) MALLOC(sizeof (gss_OID_set_desc
));
2292 (*mechanisms
)->count
=
2293 (int)res
.mechanisms
.GSS_OID_SET_len
;
2294 (*mechanisms
)->elements
= (gss_OID
)
2295 MALLOC(sizeof (gss_OID_desc
) * (*mechanisms
)->count
);
2297 for (i
= 0; i
< (*mechanisms
)->count
; i
++) {
2298 (*mechanisms
)->elements
[i
].length
= (OM_uint32
)
2299 res
.mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_len
;
2300 (*mechanisms
)->elements
[i
].elements
=
2301 (void *) MALLOC((*mechanisms
)->elements
[i
].length
);
2302 (void) memcpy((*mechanisms
)->elements
[i
].elements
,
2303 res
.mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_val
,
2304 (*mechanisms
)->elements
[i
].length
);
2307 if (res
.status
== GSS_S_COMPLETE
&&
2309 (*mechanisms
) = NULL
;
2312 * free the memory allocated for the results and return with the status
2313 * received in the rpc call
2316 clnt_freeres(clnt
, xdr_gss_inquire_cred_res
, (caddr_t
)&res
);
2317 killgssd_handle(clnt
);
2318 return (res
.status
);
2323 kgss_inquire_cred(minor_status
,
2330 OM_uint32
*minor_status
;
2331 const gss_cred_id_t cred_handle
;
2333 OM_uint32
*lifetime
;
2335 gss_OID_set
* mechanisms
;
2339 OM_uint32 gssd_cred_verifier
;
2340 OM_uint32 gssd_cred_handle
;
2342 gssd_cred_verifier
= KCRED_TO_CREDV(cred_handle
);
2343 gssd_cred_handle
= KCRED_TO_CRED(cred_handle
);
2345 return (kgss_inquire_cred_wrapped(minor_status
,
2346 gssd_cred_handle
, gssd_cred_verifier
,
2347 name
, lifetime
, cred_usage
, mechanisms
, uid
));
2351 kgss_inquire_cred_by_mech_wrapped(minor_status
,
2356 OM_uint32
*minor_status
;
2357 gssd_cred_id_t cred_handle
;
2358 OM_uint32 gssd_cred_verifier
;
2364 gss_inquire_cred_by_mech_arg arg
;
2365 gss_inquire_cred_by_mech_res res
;
2367 /* get the client handle to GSSD */
2369 if ((clnt
= getgssd_handle()) == NULL
) {
2370 GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
2372 return (GSS_S_FAILURE
);
2376 /* copy the procedure arguments into the rpc arg parameter */
2378 arg
.uid
= (OM_uint32
) uid
;
2380 arg
.cred_handle
.GSS_CRED_ID_T_len
=
2381 cred_handle
== GSSD_NO_CREDENTIAL
?
2382 0 : (uint_t
)sizeof (gssd_cred_id_t
);
2383 arg
.cred_handle
.GSS_CRED_ID_T_val
= (char *)&cred_handle
;
2384 arg
.gssd_cred_verifier
= gssd_cred_verifier
;
2386 arg
.mech_type
.GSS_OID_len
=
2387 (uint_t
)(mech_type
!= GSS_C_NULL_OID
?
2388 mech_type
->length
: 0);
2389 arg
.mech_type
.GSS_OID_val
=
2390 (char *)(mech_type
!= GSS_C_NULL_OID
?
2391 mech_type
->elements
: 0);
2392 /* call the remote procedure */
2394 bzero((caddr_t
)&res
, sizeof (res
));
2395 if (gss_inquire_cred_by_mech_1(&arg
, &res
, clnt
) != RPC_SUCCESS
) {
2398 * if the RPC call times out, null out all return arguments, set
2399 * minor_status to its maximum value, and return GSS_S_FAILURE
2402 if (minor_status
!= NULL
)
2403 *minor_status
= DEFAULT_MINOR_STAT
;
2404 killgssd_handle(clnt
);
2405 GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
2406 return (GSS_S_FAILURE
);
2409 /* copy the rpc results into the return arguments */
2411 if (minor_status
!= NULL
)
2412 *minor_status
= res
.minor_status
;
2414 clnt_freeres(clnt
, xdr_gss_inquire_cred_by_mech_res
, (caddr_t
)&res
);
2415 killgssd_handle(clnt
);
2416 return (res
.status
);
2421 kgss_inquire_cred_by_mech(minor_status
,
2425 OM_uint32
*minor_status
;
2426 gss_cred_id_t cred_handle
;
2431 OM_uint32 gssd_cred_verifier
;
2432 OM_uint32 gssd_cred_handle
;
2434 gssd_cred_verifier
= KCRED_TO_CREDV(cred_handle
);
2435 gssd_cred_handle
= KCRED_TO_CRED(cred_handle
);
2437 return (kgss_inquire_cred_by_mech_wrapped(minor_status
,
2438 gssd_cred_handle
, gssd_cred_verifier
,
2443 kgsscred_expname_to_unix_cred(expName
, uidOut
, gidOut
, gids
, gidsLen
, uid
)
2444 const gss_buffer_t expName
;
2452 gsscred_expname_to_unix_cred_arg args
;
2453 gsscred_expname_to_unix_cred_res res
;
2455 /* check input/output parameters */
2456 if (expName
== NULL
|| expName
->value
== NULL
)
2457 return (GSS_S_CALL_INACCESSIBLE_READ
);
2460 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
2462 /* NULL out output parameters */
2463 *uidOut
= UID_NOBODY
;
2470 /* get the client handle to gssd */
2471 if ((clnt
= getgssd_handle()) == NULL
)
2473 GSSLOG(1, "kgsscred_expname_to_unix_cred:"
2474 " can't connect to server on %s\n", server
);
2475 return (GSS_S_FAILURE
);
2478 /* copy the procedure arguments */
2480 args
.expname
.GSS_BUFFER_T_val
= expName
->value
;
2481 args
.expname
.GSS_BUFFER_T_len
= expName
->length
;
2483 /* null out the return buffer and call the remote proc */
2484 bzero(&res
, sizeof (res
));
2486 if (gsscred_expname_to_unix_cred_1(&args
, &res
, clnt
) != RPC_SUCCESS
)
2488 killgssd_handle(clnt
);
2490 "kgsscred_expname_to_unix_cred: RPC call times out\n");
2491 return (GSS_S_FAILURE
);
2494 /* copy the results into the result parameters */
2495 if (res
.major
== GSS_S_COMPLETE
)
2500 if (gids
&& gidsLen
)
2502 *gids
= res
.gids
.GSSCRED_GIDS_val
;
2503 *gidsLen
= res
.gids
.GSSCRED_GIDS_len
;
2504 res
.gids
.GSSCRED_GIDS_val
= NULL
;
2505 res
.gids
.GSSCRED_GIDS_len
= 0;
2509 /* free RPC results */
2510 clnt_freeres(clnt
, xdr_gsscred_expname_to_unix_cred_res
, (caddr_t
)&res
);
2511 killgssd_handle(clnt
);
2514 } /* kgsscred_expname_to_unix_cred */
2517 kgsscred_name_to_unix_cred(intName
, mechType
, uidOut
, gidOut
, gids
,
2519 const gss_name_t intName
;
2520 const gss_OID mechType
;
2528 gsscred_name_to_unix_cred_arg args
;
2529 gsscred_name_to_unix_cred_res res
;
2530 OM_uint32 major
, minor
;
2532 gss_buffer_desc flatName
= GSS_C_EMPTY_BUFFER
;
2534 /* check the input/output parameters */
2535 if (intName
== NULL
|| mechType
== NULL
)
2536 return (GSS_S_CALL_INACCESSIBLE_READ
);
2539 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
2541 /* NULL out the output parameters */
2542 *uidOut
= UID_NOBODY
;
2549 /* get the client handle to gssd */
2550 if ((clnt
= getgssd_handle()) == NULL
)
2553 "kgsscred_name_to_unix_cred: can't connect to server %s\n",
2555 return (GSS_S_FAILURE
);
2558 /* convert the name to flat representation */
2559 if ((major
= gss_display_name(&minor
, intName
, &flatName
, &nameOid
))
2562 killgssd_handle(clnt
);
2563 GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n");
2567 /* set the rpc parameters */
2569 args
.pname
.GSS_BUFFER_T_len
= flatName
.length
;
2570 args
.pname
.GSS_BUFFER_T_val
= flatName
.value
;
2571 args
.name_type
.GSS_OID_len
= nameOid
->length
;
2572 args
.name_type
.GSS_OID_val
= nameOid
->elements
;
2573 args
.mech_type
.GSS_OID_len
= mechType
->length
;
2574 args
.mech_type
.GSS_OID_val
= mechType
->elements
;
2576 /* call the remote procedure */
2577 bzero(&res
, sizeof (res
));
2578 if (gsscred_name_to_unix_cred_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2579 killgssd_handle(clnt
);
2580 (void) gss_release_buffer(&minor
, &flatName
);
2581 GSSLOG0(1, "kgsscred_name_to_unix_cred: RPC call times out\n");
2582 return (GSS_S_FAILURE
);
2585 /* delete the flat name buffer */
2586 (void) gss_release_buffer(&minor
, &flatName
);
2588 /* copy the output parameters on output */
2589 if (res
.major
== GSS_S_COMPLETE
) {
2594 if (gids
&& gidsLen
) {
2595 *gids
= res
.gids
.GSSCRED_GIDS_val
;
2596 *gidsLen
= res
.gids
.GSSCRED_GIDS_len
;
2597 res
.gids
.GSSCRED_GIDS_val
= NULL
;
2598 res
.gids
.GSSCRED_GIDS_len
= 0;
2602 /* delete RPC allocated memory */
2603 clnt_freeres(clnt
, xdr_gsscred_name_to_unix_cred_res
, (caddr_t
)&res
);
2604 killgssd_handle(clnt
);
2607 } /* kgsscred_name_to_unix_cred */
2610 kgss_get_group_info(puid
, gidOut
, gids
, gidsLen
, uid
)
2618 gss_get_group_info_arg args
;
2619 gss_get_group_info_res res
;
2622 /* check the output parameters */
2623 if (gidOut
== NULL
|| gids
== NULL
|| gidsLen
== NULL
)
2624 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
2626 /* get the client GSSD handle */
2627 if ((clnt
= getgssd_handle()) == NULL
) {
2629 "kgss_get_group_info: can't connect to server on %s\n",
2631 return (GSS_S_FAILURE
);
2634 /* set the input parameters */
2638 /* call the remote procedure */
2639 bzero(&res
, sizeof (res
));
2640 if (gss_get_group_info_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2641 killgssd_handle(clnt
);
2642 GSSLOG0(1, "kgss_get_group_info: RPC call times out\n");
2643 return (GSS_S_FAILURE
);
2646 /* copy the results */
2647 if (res
.major
== GSS_S_COMPLETE
) {
2649 *gids
= res
.gids
.GSSCRED_GIDS_val
;
2650 *gidsLen
= res
.gids
.GSSCRED_GIDS_len
;
2651 res
.gids
.GSSCRED_GIDS_val
= NULL
;
2652 res
.gids
.GSSCRED_GIDS_len
= 0;
2655 /* no results to free */
2656 killgssd_handle(clnt
);
2659 } /* kgss_get_group_info */
2662 kgss_get_kmod(gss_OID mech_oid
)
2665 gss_get_kmod_arg args
;
2666 gss_get_kmod_res res
;
2669 /* get the client GSSD handle */
2670 if ((clnt
= getgssd_handle()) == NULL
) {
2671 GSSLOG(1, "kgss_get_kmod: can't connect to server on %s\n",
2676 /* set the input parameters */
2677 args
.mech_oid
.GSS_OID_len
= mech_oid
->length
;
2678 args
.mech_oid
.GSS_OID_val
= mech_oid
->elements
;
2680 /* call the remote procedure */
2681 bzero(&res
, sizeof (res
));
2682 if (gss_get_kmod_1(&args
, &res
, clnt
) != RPC_SUCCESS
) {
2683 killgssd_handle(clnt
);
2684 GSSLOG0(1, "gss_get_kmod_1: RPC call times out\n");
2687 /* no results to free */
2688 killgssd_handle(clnt
);
2690 if (res
.module_follow
== TRUE
) {
2691 return (res
.gss_get_kmod_res_u
.modname
);
2694 } /* kgss_get_kmod */
2696 static gss_mechanism kgss_mech_head
;
2697 static gss_mechanism kgss_mech_tail
;
2698 kmutex_t __kgss_mech_lock
;
2701 * See if there is kernel mechanism module, and if so, attempt to
2702 * load it and reset the pointer (gss_mechanism) to the sign/seal/etc.
2703 * entry points to that of the kernel module.
2706 __kgss_reset_mech(gss_mechanism
*mechp
, gss_OID mech_oid
)
2712 * We can search the list without a mutex, becuase the list never
2713 * shrinks and we always add to the end.
2715 mech
= __kgss_get_mechanism(mech_oid
);
2722 * Get the module name from the kernel.
2724 kmod
= kgss_get_kmod(mech_oid
);
2727 extern int modload(const char *, const char *);
2728 if (modload("misc/kgss", kmod
) < 0) {
2730 * Modload of 'kmod' failed, so log an
2731 * appropriate comment
2733 cmn_err(CE_NOTE
, "kgss_reset_mech: Algorithm modload "
2734 "(%s) failed. Userland gssd will now handle "
2735 "all GSSAPI calls, which may result in "
2736 "reduced performance.\n", kmod
);
2740 * Allocated in the XDR routine called by gss_get_kmod_1().
2742 FREE(kmod
, strlen(kmod
)+1);
2744 mech
= __kgss_get_mechanism(mech_oid
);
2750 * If for some reason the module load didn't take,
2751 * we return anyway and hope that the next context
2752 * creation succeeds.
2759 * No kernel module, so enter this mech oid into the list
2760 * using the default sign/seal/etc. operations that upcall to
2763 mutex_enter(&__kgss_mech_lock
);
2764 mech
= __kgss_get_mechanism(mech_oid
);
2766 mutex_exit(&__kgss_mech_lock
);
2772 * Allocate space for the mechanism entry.
2774 mech
= kmem_zalloc(sizeof (struct gss_config
), KM_SLEEP
);
2777 * Copy basic information from default mechanism struct.
2782 * Record the real mech OID.
2784 mech
->mech_type
.length
= mech_oid
->length
;
2785 mech
->mech_type
.elements
= MALLOC(mech_oid
->length
);
2786 bcopy(mech_oid
->elements
, mech
->mech_type
.elements
, mech_oid
->length
);
2789 * Add it to the table.
2791 __kgss_add_mechanism(mech
);
2792 mutex_exit(&__kgss_mech_lock
);
2797 * Called with __kgss_mech_lock held.
2800 __kgss_add_mechanism(gss_mechanism mech
)
2804 tmp
= kgss_mech_tail
;
2805 kgss_mech_tail
= mech
;
2810 if (kgss_mech_head
== NULL
)
2811 kgss_mech_head
= mech
;
2815 * given the mechs_array and a mechanism OID, return the
2816 * pointer to the mechanism, or NULL if that mechanism is
2820 __kgss_get_mechanism(gss_OID type
)
2824 mech
= kgss_mech_head
;
2827 * Note that a reader can scan this list without the mutex held.
2828 * This is safe because we always append, and never shrink the list.
2829 * Moreover, the entry is fully initialized before it is ever
2830 * added to the list.
2832 while (mech
!= NULL
) {
2833 if ((mech
->mech_type
.length
== type
->length
) &&
2834 (bcmp(mech
->mech_type
.elements
, type
->elements
,
2835 type
->length
) == 0))