Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / gssapi / gssd_clnt_stubs.c
blob919d277a197c913c135520d21b5adc37b387cd69
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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"
33 #include <rpc/rpc.h>
35 #include <sys/systm.h>
36 #include <sys/types.h>
37 #include <sys/cmn_err.h>
38 #include <sys/kmem.h>
39 #include <gssapi/kgssapi_defs.h>
40 #include <sys/debug.h>
42 #ifdef GSSDEBUG
44 * Kernel kgssd module debugging aid. The global variable "gss_log"
45 * is a bit mask which allows various types of debugging messages
46 * to be printed out.
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.
57 uint_t gss_log = 1;
59 #endif /* GSSDEBUG */
61 #ifdef DEBUG
62 extern void prom_printf(const char *, ...);
63 #endif
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,
78 OM_uint32);
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)
87 OM_uint32
88 kgss_acquire_cred_wrapped(
89 OM_uint32 *minor_status,
90 const gss_name_t desired_name,
91 OM_uint32 time_req,
92 const gss_OID_set desired_mechs,
93 int cred_usage,
94 gssd_cred_id_t *output_cred_handle,
95 gss_OID_set *actual_mechs,
96 OM_uint32 *time_rec,
97 uid_t uid,
98 OM_uint32 *gssd_cred_verifier)
100 CLIENT *clnt;
102 OM_uint32 minor_status_temp;
103 gss_buffer_desc external_name;
104 gss_OID name_type;
105 enum clnt_stat client_stat;
106 int i;
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",
115 server);
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);
158 (void) memcpy(
159 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
160 desired_mechs->elements[i].elements,
161 desired_mechs->elements[i].length);
163 } else
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
187 * GSS_S_FAILURE
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)
197 *time_rec = 0;
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
212 .GSS_CRED_ID_T_val);
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]
230 .length);
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);
235 } else {
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);
250 return (res.status);
254 OM_uint32
255 kgss_acquire_cred(
256 OM_uint32 *minor_status,
257 const gss_name_t desired_name,
258 OM_uint32 time_req,
259 const gss_OID_set desired_mechs,
260 int cred_usage,
261 gss_cred_id_t *output_cred_handle,
262 gss_OID_set *actual_mechs,
263 OM_uint32 *time_rec,
264 uid_t uid)
267 OM_uint32 err;
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;
279 return (err);
282 OM_uint32
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,
289 int cred_usage,
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,
295 uid_t uid)
297 CLIENT *clnt;
299 OM_uint32 minor_status_temp;
300 gss_buffer_desc external_name;
301 gss_OID name_type;
302 int i;
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
312 * case
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",
327 server);
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
379 * GSS_S_FAILURE
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)->
410 elements[i].length);
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);
415 } else {
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);
431 return (res.status);
435 OM_uint32
436 kgss_add_cred(
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,
441 int cred_usage,
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,
447 uid_t uid)
450 OM_uint32 err;
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);
457 } else {
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);
466 return (err);
470 OM_uint32
471 kgss_release_cred_wrapped(
472 OM_uint32 *minor_status,
473 gssd_cred_id_t *cred_handle,
474 uid_t uid,
475 OM_uint32 gssd_cred_verifier)
477 CLIENT *clnt;
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",
487 server);
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;
500 } else
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)
516 *cred_handle = 0;
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)
526 *cred_handle = 0;
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);
537 return (res.status);
541 OM_uint32
542 kgss_release_cred(
543 OM_uint32 *minor_status,
544 gss_cred_id_t *cred_handle,
545 uid_t uid)
548 OM_uint32 err;
549 struct kgss_cred *kcred;
551 if (*cred_handle == GSS_C_NO_CREDENTIAL)
552 return (GSS_S_COMPLETE);
553 else
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;
560 return (err);
563 static OM_uint32
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,
572 int req_flags,
573 OM_uint32 time_req,
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,
578 int *ret_flags,
579 OM_uint32 *time_rec,
580 uid_t uid)
582 CLIENT *clnt;
584 OM_uint32 minor_status_temp;
585 gss_buffer_desc external_name;
586 gss_OID name_type;
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) {
594 GSSLOG(1,
595 "kgss_init_sec_context: can't connect to server on %s\n",
596 server);
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;
667 } else {
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)
701 *ret_flags = 0;
702 if (time_rec != NULL)
703 *time_rec = 0;
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.
735 *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) {
741 *actual_mech_type =
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);
768 return (res.status);
772 static struct gss_config default_gc = {
773 { 0, NULL},
774 NULL,
775 NULL,
777 kgss_unseal_wrapped,
778 NULL, /* kgss_delete_sec_context_wrapped */
779 kgss_seal_wrapped,
780 NULL, /* kgss_import_sec_context */
781 kgss_sign_wrapped,
782 kgss_verify_wrapped
785 void
786 kgss_free_oid(gss_OID oid)
788 FREE(oid->elements, oid->length);
789 FREE(oid, sizeof (gss_OID_desc));
792 OM_uint32
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,
799 int req_flags,
800 OM_uint32 time_req,
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,
805 int *ret_flags,
806 OM_uint32 *time_rec,
807 uid_t uid)
809 OM_uint32 err;
810 struct kgss_ctx *kctx;
811 gss_OID amt;
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) {
821 kctx = KGSS_ALLOC();
823 * The default gss-mechanism struct as pointers to
824 * the sign/seal/verify/unseal routines that make
825 * upcalls to gssd.
827 kctx->mech = &default_gc;
828 kctx->gssd_ctx = GSSD_NO_CONTEXT;
829 *context_handle = (gss_ctx_id_t)kctx;
830 } else
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);
836 } else {
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)) {
854 KGSS_FREE(kctx);
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) {
868 kgss_free_oid(amt);
871 return (err);
874 static OM_uint32
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,
884 gss_OID *mech_type,
885 gss_buffer_t output_token,
886 int *ret_flags,
887 OM_uint32 *time_rec,
888 gss_cred_id_t *delegated_cred_handle,
889 uid_t uid)
891 CLIENT *clnt;
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) {
900 GSSLOG(1,
901 "kgss_accept_sec_context: can't connect to server on %s\n",
902 server);
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;
946 } else {
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)
967 *mech_type = NULL;
968 if (output_token != NULL)
969 output_token->length = 0;
970 if (ret_flags != NULL)
971 *ret_flags = 0;
972 if (time_rec != NULL)
973 *time_rec = 0;
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) {
1015 src_name->length =
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) {
1027 *mech_type =
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
1046 != 0)) {
1047 kcred = KGSS_CRED_ALLOC();
1048 kcred->gssd_cred =
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);
1072 OM_uint32
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,
1080 gss_OID *mech_type,
1081 gss_buffer_t output_token,
1082 int *ret_flags,
1083 OM_uint32 *time_rec,
1084 gss_cred_id_t *delegated_cred_handle,
1085 uid_t uid)
1087 OM_uint32 err;
1088 struct kgss_ctx *kctx;
1089 gss_OID mt;
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
1096 * on here.
1098 if (mech_type == NULL)
1099 mech_type = &mt;
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;
1106 } else
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);
1112 } else {
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)) {
1124 KGSS_FREE(kctx);
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) {
1134 kgss_free_oid(mt);
1138 return (err);
1141 OM_uint32
1142 kgss_process_context_token(
1143 OM_uint32 *minor_status,
1144 const gss_ctx_id_t context_handle,
1145 gss_buffer_t token_buffer,
1146 uid_t uid)
1148 CLIENT *clnt;
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) {
1160 GSSLOG(1,
1161 "kgss_process_context_token: "
1162 "can't connect to server on %s\n",
1163 server);
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);
1207 /*ARGSUSED*/
1208 static OM_uint32
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)
1215 CLIENT *clnt;
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) {
1224 GSSLOG(1,
1225 "kgss_delete_sec_context: can't connect to server on %s\n",
1226 server);
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;
1268 else
1269 *context_handle =
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);
1290 OM_uint32
1291 kgss_delete_sec_context(
1292 OM_uint32 *minor_status,
1293 gss_ctx_id_t *context_handle,
1294 gss_buffer_t output_token)
1296 OM_uint32 err;
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);
1302 } else
1303 kctx = (struct kgss_ctx *)*context_handle;
1305 if (kctx->ctx_imported == FALSE) {
1306 if (kctx->gssd_ctx == GSSD_NO_CONTEXT) {
1307 KGSS_FREE(kctx);
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),
1313 minor_status,
1314 &kctx->gssd_ctx,
1315 output_token,
1316 kctx->gssd_ctx_verifier);
1317 } else {
1318 if (kctx->gssd_i_ctx == (gss_ctx_id_t)GSS_C_NO_CONTEXT) {
1319 KGSS_FREE(kctx);
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);
1326 KGSS_FREE(kctx);
1327 *context_handle = GSS_C_NO_CONTEXT;
1328 return (err);
1333 OM_uint32
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)
1340 CLIENT *clnt;
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
1367 * GSS_S_FAILURE
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);
1377 GSSLOG0(1,
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;
1389 else
1390 *context_handle =
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);
1413 OM_uint32
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);
1423 else
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
1434 *minor_status = 0;
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,
1439 &kctx->gssd_ctx,
1440 output_token,
1441 kctx->gssd_ctx_verifier));
1443 } else {
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 "
1452 "unavailable \n");
1453 return (GSS_S_NAME_NOT_MN);
1458 OM_uint32
1459 kgss_import_sec_context(
1460 OM_uint32 * minor_status,
1461 const gss_buffer_t interprocess_token,
1462 gss_ctx_id_t context_handle)
1464 OM_uint32 status;
1465 struct kgss_ctx *kctx;
1467 size_t length;
1468 char *p;
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);
1488 *minor_status = 0;
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;
1496 length = *p++;
1497 length = (length << 8) + *p++;
1498 length = (length << 8) + *p++;
1499 length = (length << 8) + *p++;
1501 p += length;
1503 token.length = interprocess_token->length - 4 - length;
1504 token.value = p;
1507 * select the approprate underlying mechanism routine and
1508 * call it.
1511 status = KGSS_IMPORT_SEC_CONTEXT(minor_status, &token, kctx,
1512 &internal_ctx_id);
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);
1518 } else
1519 return (status);
1522 /*ARGSUSED*/
1523 OM_uint32
1524 kgss_context_time(
1525 OM_uint32 *minor_status,
1526 const gss_ctx_id_t context_handle,
1527 OM_uint32 *time_rec,
1528 uid_t uid)
1530 return (GSS_S_FAILURE);
1533 /*ARGSUSED*/
1534 static OM_uint32
1535 kgss_sign_wrapped(
1536 void *private,
1537 OM_uint32 *minor_status,
1538 const gss_ctx_id_t ctx_handle,
1539 int qop_req,
1540 const gss_buffer_t message_buffer,
1541 gss_buffer_t msg_token,
1542 OM_uint32 gssd_context_verifier)
1544 CLIENT *clnt;
1545 gssd_ctx_id_t context_handle;
1547 gss_sign_arg arg;
1548 gss_sign_res res;
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,
1600 msg_token->length);
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);
1614 OM_uint32
1615 kgss_sign(
1616 OM_uint32 *minor_status,
1617 const gss_ctx_id_t context_handle,
1618 int qop_req,
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));
1628 /*ARGSUSED*/
1629 static OM_uint32
1630 kgss_verify_wrapped(
1631 void *private,
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,
1636 int *qop_state,
1637 OM_uint32 gssd_context_verifier)
1639 CLIENT *clnt;
1641 gssd_ctx_id_t context_handle;
1642 gss_verify_arg arg;
1643 gss_verify_res res;
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",
1651 server);
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)
1683 *qop_state = 0;
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);
1705 OM_uint32
1706 kgss_verify(
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,
1711 int *qop_state)
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));
1719 /*ARGSUSED*/
1720 static OM_uint32
1721 kgss_seal_wrapped(
1722 void *private,
1723 OM_uint32 *minor_status,
1724 const gss_ctx_id_t ctx_handle,
1725 int conf_req_flag,
1726 int qop_req,
1727 const gss_buffer_t input_message_buffer,
1728 int *conf_state,
1729 gss_buffer_t output_message_buffer,
1730 OM_uint32 gssd_context_verifier)
1732 CLIENT *clnt;
1733 gssd_ctx_id_t context_handle;
1735 gss_seal_arg arg;
1736 gss_seal_res res;
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)
1779 *conf_state = 0;
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);
1817 /*ARGSUSED*/
1818 OM_uint32
1819 kgss_seal(
1820 OM_uint32 *minor_status,
1821 const gss_ctx_id_t context_handle,
1822 int conf_req_flag,
1823 int qop_req,
1824 const gss_buffer_t input_message_buffer,
1825 int *conf_state,
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));
1836 /*ARGSUSED*/
1837 static OM_uint32
1838 kgss_unseal_wrapped(
1839 void *private,
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,
1844 int *conf_state,
1845 int *qop_state,
1846 OM_uint32 gssd_context_verifier)
1848 CLIENT *clnt;
1850 gss_unseal_arg arg;
1851 gss_unseal_res res;
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",
1860 server);
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)
1894 *conf_state = 0;
1895 if (qop_state != NULL)
1896 *qop_state = 0;
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);
1935 OM_uint32
1936 kgss_unseal(
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,
1941 int *conf_state,
1942 int *qop_state)
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));
1952 OM_uint32
1953 kgss_display_status(
1954 OM_uint32 *minor_status,
1955 OM_uint32 status_value,
1956 int status_type,
1957 const gss_OID mech_type,
1958 int *message_context,
1959 gss_buffer_t status_string,
1960 uid_t uid)
1962 CLIENT *clnt;
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",
1971 server);
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);
2038 /*ARGSUSED*/
2039 OM_uint32
2040 kgss_indicate_mechs(
2041 OM_uint32 *minor_status,
2042 gss_OID_set *mech_set,
2043 uid_t uid)
2045 CLIENT *clnt;
2046 void *arg;
2047 gss_indicate_mechs_res res;
2048 int i;
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",
2054 server);
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)
2069 *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);
2108 OM_uint32
2109 kgss_inquire_cred_wrapped(
2110 OM_uint32 *minor_status,
2111 const gssd_cred_id_t cred_handle,
2112 OM_uint32 gssd_cred_verifier,
2113 gss_name_t *name,
2114 OM_uint32 *lifetime,
2115 int *cred_usage,
2116 gss_OID_set *mechanisms,
2117 uid_t uid)
2119 CLIENT *clnt;
2121 OM_uint32 minor_status_temp;
2122 gss_buffer_desc external_name;
2123 gss_OID_desc name_type;
2124 int i;
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
2133 * case
2135 if (minor_status != NULL)
2136 *minor_status = DEFAULT_MINOR_STAT;
2137 if (name != NULL)
2138 *name = NULL;
2139 if (lifetime != NULL)
2140 *lifetime = 0;
2141 if (cred_usage != NULL)
2142 *cred_usage = 0;
2143 if (mechanisms != NULL)
2144 *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",
2150 server);
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 */
2188 if (name != NULL) {
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,
2206 (caddr_t)&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);
2237 } else {
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);
2252 OM_uint32
2253 kgss_inquire_cred(
2254 OM_uint32 *minor_status,
2255 const gss_cred_id_t cred_handle,
2256 gss_name_t *name,
2257 OM_uint32 *lifetime,
2258 int *cred_usage,
2259 gss_OID_set * mechanisms,
2260 uid_t uid)
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));
2274 OM_uint32
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,
2279 gss_OID mech_type,
2280 uid_t uid)
2282 CLIENT *clnt;
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",
2291 server);
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);
2340 OM_uint32
2341 kgss_inquire_cred_by_mech(
2342 OM_uint32 *minor_status,
2343 gss_cred_id_t cred_handle,
2344 gss_OID mech_type,
2345 uid_t uid)
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,
2356 mech_type, uid));
2359 OM_uint32
2360 kgsscred_expname_to_unix_cred(
2361 const gss_buffer_t expName,
2362 uid_t *uidOut,
2363 gid_t *gidOut,
2364 gid_t *gids[],
2365 int *gidsLen,
2366 uid_t uid)
2368 CLIENT *clnt;
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);
2376 if (uidOut == NULL)
2377 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2379 /* NULL out output parameters */
2380 *uidOut = UID_NOBODY;
2381 if (gidsLen)
2382 *gidsLen = 0;
2384 if (gids)
2385 *gids = NULL;
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 */
2395 args.uid = uid;
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);
2404 GSSLOG0(1,
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) {
2411 *uidOut = res.uid;
2412 if (gidOut)
2413 *gidOut = res.gid;
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);
2426 return (res.major);
2427 } /* kgsscred_expname_to_unix_cred */
2429 OM_uint32
2430 kgsscred_name_to_unix_cred(
2431 const gss_name_t intName,
2432 const gss_OID mechType,
2433 uid_t *uidOut,
2434 gid_t *gidOut,
2435 gid_t *gids[],
2436 int *gidsLen,
2437 uid_t uid)
2439 CLIENT *clnt;
2440 gsscred_name_to_unix_cred_arg args;
2441 gsscred_name_to_unix_cred_res res;
2442 OM_uint32 major, minor;
2443 gss_OID nameOid;
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);
2450 if (uidOut == NULL)
2451 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2453 /* NULL out the output parameters */
2454 *uidOut = UID_NOBODY;
2455 if (gids)
2456 *gids = NULL;
2458 if (gidsLen)
2459 *gidsLen = 0;
2461 /* get the client handle to gssd */
2462 if ((clnt = getgssd_handle()) == NULL) {
2463 GSSLOG(1,
2464 "kgsscred_name_to_unix_cred: can't connect to server %s\n",
2465 server);
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");
2474 return (major);
2477 /* set the rpc parameters */
2478 args.uid = uid;
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) {
2500 *uidOut = res.uid;
2502 if (gidOut)
2503 *gidOut = res.gid;
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);
2516 return (res.major);
2517 } /* kgsscred_name_to_unix_cred */
2519 OM_uint32
2520 kgss_get_group_info(
2521 const uid_t puid,
2522 gid_t *gidOut,
2523 gid_t *gids[],
2524 int *gidsLen,
2525 uid_t uid)
2527 CLIENT *clnt;
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) {
2538 GSSLOG(1,
2539 "kgss_get_group_info: can't connect to server on %s\n",
2540 server);
2541 return (GSS_S_FAILURE);
2544 /* set the input parameters */
2545 args.uid = uid;
2546 args.puid = puid;
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) {
2558 *gidOut = res.gid;
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);
2568 return (res.major);
2569 } /* kgss_get_group_info */
2571 static char *
2572 kgss_get_kmod(gss_OID mech_oid)
2574 CLIENT *clnt;
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",
2582 server);
2583 return (NULL);
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");
2595 return (NULL);
2597 /* no results to free */
2598 killgssd_handle(clnt);
2600 if (res.module_follow == TRUE) {
2601 return (res.gss_get_kmod_res_u.modname);
2602 } else
2603 return (NULL);
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.
2615 static void
2616 __kgss_reset_mech(gss_mechanism *mechp, gss_OID mech_oid)
2618 gss_mechanism mech;
2619 char *kmod;
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);
2626 if (mech) {
2627 *mechp = mech;
2628 return;
2632 * Get the module name from the kernel.
2634 kmod = kgss_get_kmod(mech_oid);
2636 if (kmod) {
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);
2655 if (mech) {
2656 *mechp = mech;
2660 * If for some reason the module load didn't take,
2661 * we return anyway and hope that the next context
2662 * creation succeeds.
2664 return;
2669 * No kernel module, so enter this mech oid into the list
2670 * using the default sign/seal/etc. operations that upcall to
2671 * gssd.
2673 mutex_enter(&__kgss_mech_lock);
2674 mech = __kgss_get_mechanism(mech_oid);
2675 if (mech) {
2676 mutex_exit(&__kgss_mech_lock);
2677 *mechp = mech;
2678 return;
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.
2689 *mech = default_gc;
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);
2703 *mechp = mech;
2707 * Called with __kgss_mech_lock held.
2709 void
2710 __kgss_add_mechanism(gss_mechanism mech)
2712 gss_mechanism tmp;
2714 tmp = kgss_mech_tail;
2715 kgss_mech_tail = mech;
2717 if (tmp != NULL)
2718 tmp->next = 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
2727 * not supported.
2729 gss_mechanism
2730 __kgss_get_mechanism(gss_OID type)
2732 gss_mechanism mech;
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))
2746 return (mech);
2748 mech = mech->next;
2750 return (NULL);