3882 Remove xmod & friends
[illumos-gate.git] / usr / src / uts / common / gssapi / gssd_clnt_stubs.c
blobc934752798e059b762dca69391a69848eed89f69
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(minor_status,
89 desired_name,
90 time_req,
91 desired_mechs,
92 cred_usage,
93 output_cred_handle,
94 actual_mechs,
95 time_rec,
96 uid,
97 gssd_cred_verifier)
98 OM_uint32 *minor_status;
99 const gss_name_t desired_name;
100 OM_uint32 time_req;
101 const gss_OID_set desired_mechs;
102 int cred_usage;
103 gssd_cred_id_t *output_cred_handle;
104 gss_OID_set *actual_mechs;
105 OM_uint32 *time_rec;
106 uid_t uid;
107 OM_uint32 *gssd_cred_verifier;
109 CLIENT *clnt;
111 OM_uint32 minor_status_temp;
112 gss_buffer_desc external_name;
113 gss_OID name_type;
114 enum clnt_stat client_stat;
115 int i;
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",
124 server);
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);
168 (void) memcpy(
169 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
170 desired_mechs->elements[i].elements,
171 desired_mechs->elements[i].length);
173 } else
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
197 * GSS_S_FAILURE
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)
207 *time_rec = 0;
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);
244 } else {
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);
260 return (res.status);
264 OM_uint32
265 kgss_acquire_cred(minor_status,
266 desired_name,
267 time_req,
268 desired_mechs,
269 cred_usage,
270 output_cred_handle,
271 actual_mechs,
272 time_rec,
273 uid)
274 OM_uint32 *minor_status;
275 const gss_name_t desired_name;
276 OM_uint32 time_req;
277 const gss_OID_set desired_mechs;
278 int cred_usage;
279 gss_cred_id_t *output_cred_handle;
280 gss_OID_set *actual_mechs;
281 OM_uint32 *time_rec;
282 uid_t uid;
285 OM_uint32 err;
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;
297 return (err);
300 OM_uint32
301 kgss_add_cred_wrapped(minor_status,
302 input_cred_handle,
303 gssd_cred_verifier,
304 desired_name,
305 desired_mech_type,
306 cred_usage,
307 initiator_time_req,
308 acceptor_time_req,
309 actual_mechs,
310 initiator_time_rec,
311 acceptor_time_rec,
312 uid)
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;
318 int cred_usage;
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;
324 uid_t uid;
326 CLIENT *clnt;
328 OM_uint32 minor_status_temp;
329 gss_buffer_desc external_name;
330 gss_OID name_type;
331 int i;
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
341 * case
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",
356 server);
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
408 * GSS_S_FAILURE
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);
444 } else {
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);
460 return (res.status);
464 OM_uint32
465 kgss_add_cred(minor_status,
466 input_cred_handle,
467 desired_name,
468 desired_mech_type,
469 cred_usage,
470 initiator_time_req,
471 acceptor_time_req,
472 actual_mechs,
473 initiator_time_rec,
474 acceptor_time_rec,
475 uid)
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;
480 int cred_usage;
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;
486 uid_t uid;
489 OM_uint32 err;
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);
496 } else {
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);
505 return (err);
509 OM_uint32
510 kgss_release_cred_wrapped(minor_status,
511 cred_handle,
512 uid,
513 gssd_cred_verifier)
514 OM_uint32 *minor_status;
515 gssd_cred_id_t *cred_handle;
516 uid_t uid;
517 OM_uint32 gssd_cred_verifier;
519 CLIENT *clnt;
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",
529 server);
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;
542 } else
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)
558 *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)
568 *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);
579 return (res.status);
583 OM_uint32
584 kgss_release_cred(minor_status,
585 cred_handle,
586 uid)
587 OM_uint32 *minor_status;
588 gss_cred_id_t *cred_handle;
589 uid_t uid;
593 OM_uint32 err;
594 struct kgss_cred *kcred;
596 if (*cred_handle == GSS_C_NO_CREDENTIAL)
597 return (GSS_S_COMPLETE);
598 else
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;
605 return (err);
608 static OM_uint32
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,
617 int req_flags,
618 OM_uint32 time_req,
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,
623 int *ret_flags,
624 OM_uint32 *time_rec,
625 uid_t uid)
627 CLIENT *clnt;
629 OM_uint32 minor_status_temp;
630 gss_buffer_desc external_name;
631 gss_OID name_type;
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) {
639 GSSLOG(1,
640 "kgss_init_sec_context: can't connect to server on %s\n",
641 server);
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;
712 } else {
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)
746 *ret_flags = 0;
747 if (time_rec != NULL)
748 *time_rec = 0;
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.
780 *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) {
786 *actual_mech_type =
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);
813 return (res.status);
817 static struct gss_config default_gc = {
818 { 0, NULL},
819 NULL,
820 NULL,
822 kgss_unseal_wrapped,
823 NULL, /* kgss_delete_sec_context_wrapped */
824 kgss_seal_wrapped,
825 NULL, /* kgss_import_sec_context */
826 kgss_sign_wrapped,
827 kgss_verify_wrapped
830 void
831 kgss_free_oid(gss_OID oid)
833 FREE(oid->elements, oid->length);
834 FREE(oid, sizeof (gss_OID_desc));
837 OM_uint32
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,
844 int req_flags,
845 OM_uint32 time_req,
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,
850 int *ret_flags,
851 OM_uint32 *time_rec,
852 uid_t uid)
854 OM_uint32 err;
855 struct kgss_ctx *kctx;
856 gss_OID amt;
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) {
866 kctx = KGSS_ALLOC();
868 * The default gss-mechanism struct as pointers to
869 * the sign/seal/verify/unseal routines that make
870 * upcalls to gssd.
872 kctx->mech = &default_gc;
873 kctx->gssd_ctx = GSSD_NO_CONTEXT;
874 *context_handle = (gss_ctx_id_t)kctx;
875 } else
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);
881 } else {
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)) {
899 KGSS_FREE(kctx);
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) {
913 kgss_free_oid(amt);
916 return (err);
919 static OM_uint32
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,
929 gss_OID *mech_type,
930 gss_buffer_t output_token,
931 int *ret_flags,
932 OM_uint32 *time_rec,
933 gss_cred_id_t *delegated_cred_handle,
934 uid_t uid)
936 CLIENT *clnt;
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) {
945 GSSLOG(1,
946 "kgss_accept_sec_context: can't connect to server on %s\n",
947 server);
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;
991 } else {
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)
1012 *mech_type = NULL;
1013 if (output_token != NULL)
1014 output_token->length = 0;
1015 if (ret_flags != NULL)
1016 *ret_flags = 0;
1017 if (time_rec != NULL)
1018 *time_rec = 0;
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) {
1060 src_name->length =
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) {
1072 *mech_type =
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
1091 != 0)) {
1092 kcred = KGSS_CRED_ALLOC();
1093 kcred->gssd_cred =
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);
1116 OM_uint32
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,
1124 gss_OID *mech_type,
1125 gss_buffer_t output_token,
1126 int *ret_flags,
1127 OM_uint32 *time_rec,
1128 gss_cred_id_t *delegated_cred_handle,
1129 uid_t uid)
1131 OM_uint32 err;
1132 struct kgss_ctx *kctx;
1133 gss_OID mt;
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
1140 * on here.
1142 if (mech_type == NULL)
1143 mech_type = &mt;
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;
1150 } else
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);
1156 } else {
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)) {
1168 KGSS_FREE(kctx);
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) {
1178 kgss_free_oid(mt);
1182 return (err);
1185 OM_uint32
1186 kgss_process_context_token(minor_status,
1187 context_handle,
1188 token_buffer,
1189 uid)
1190 OM_uint32 *minor_status;
1191 const gss_ctx_id_t context_handle;
1192 gss_buffer_t token_buffer;
1193 uid_t uid;
1195 CLIENT *clnt;
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) {
1207 GSSLOG(1,
1208 "kgss_process_context_token: can't connect to server on %s\n",
1209 server);
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);
1253 /*ARGSUSED*/
1254 static OM_uint32
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)
1263 CLIENT *clnt;
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) {
1272 GSSLOG(1,
1273 "kgss_delete_sec_context: can't connect to server on %s\n",
1274 server);
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;
1316 else
1317 *context_handle =
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);
1338 OM_uint32
1339 kgss_delete_sec_context(
1340 OM_uint32 *minor_status,
1341 gss_ctx_id_t *context_handle,
1342 gss_buffer_t output_token)
1344 OM_uint32 err;
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);
1350 } else
1351 kctx = (struct kgss_ctx *)*context_handle;
1353 if (kctx->ctx_imported == FALSE) {
1354 if (kctx->gssd_ctx == GSSD_NO_CONTEXT) {
1355 KGSS_FREE(kctx);
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),
1361 minor_status,
1362 &kctx->gssd_ctx,
1363 output_token,
1364 kctx->gssd_ctx_verifier);
1365 } else {
1366 if (kctx->gssd_i_ctx == (gss_ctx_id_t)GSS_C_NO_CONTEXT) {
1367 KGSS_FREE(kctx);
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);
1374 KGSS_FREE(kctx);
1375 *context_handle = GSS_C_NO_CONTEXT;
1376 return (err);
1381 OM_uint32
1382 kgss_export_sec_context_wrapped(minor_status,
1383 context_handle,
1384 output_token,
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;
1391 CLIENT *clnt;
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
1418 * GSS_S_FAILURE
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);
1428 GSSLOG0(1,
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;
1440 else
1441 *context_handle =
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);
1464 OM_uint32
1465 kgss_export_sec_context(minor_status,
1466 context_handle,
1467 output_token)
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);
1476 else
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
1487 *minor_status = 0;
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,
1492 &kctx->gssd_ctx,
1493 output_token,
1494 kctx->gssd_ctx_verifier));
1496 } else {
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 "
1505 "unavailable \n");
1506 return (GSS_S_NAME_NOT_MN);
1511 OM_uint32
1512 kgss_import_sec_context(minor_status,
1513 interprocess_token,
1514 context_handle)
1516 OM_uint32 * minor_status;
1517 const gss_buffer_t interprocess_token;
1518 gss_ctx_id_t context_handle;
1521 OM_uint32 status;
1522 struct kgss_ctx *kctx;
1524 size_t length;
1525 char *p;
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);
1545 *minor_status = 0;
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;
1553 length = *p++;
1554 length = (length << 8) + *p++;
1555 length = (length << 8) + *p++;
1556 length = (length << 8) + *p++;
1558 p += length;
1560 token.length = interprocess_token->length - 4 - length;
1561 token.value = p;
1564 * select the approprate underlying mechanism routine and
1565 * call it.
1568 status = KGSS_IMPORT_SEC_CONTEXT(minor_status, &token, kctx,
1569 &internal_ctx_id);
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);
1575 } else
1576 return (status);
1579 /*ARGSUSED*/
1580 OM_uint32
1581 kgss_context_time(minor_status,
1582 context_handle,
1583 time_rec,
1584 uid)
1585 OM_uint32 *minor_status;
1586 const gss_ctx_id_t context_handle;
1587 OM_uint32 *time_rec;
1588 uid_t uid;
1590 return (GSS_S_FAILURE);
1593 /*ARGSUSED*/
1594 static OM_uint32
1595 kgss_sign_wrapped(void *private,
1596 OM_uint32 *minor_status,
1597 const gss_ctx_id_t ctx_handle,
1598 int qop_req,
1599 const gss_buffer_t message_buffer,
1600 gss_buffer_t msg_token,
1601 OM_uint32 gssd_context_verifier)
1603 CLIENT *clnt;
1604 gssd_ctx_id_t context_handle;
1606 gss_sign_arg arg;
1607 gss_sign_res res;
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,
1659 msg_token->length);
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);
1673 OM_uint32
1674 kgss_sign(
1675 OM_uint32 *minor_status,
1676 const gss_ctx_id_t context_handle,
1677 int qop_req,
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));
1687 /*ARGSUSED*/
1688 static OM_uint32
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,
1694 int *qop_state,
1695 OM_uint32 gssd_context_verifier)
1697 CLIENT *clnt;
1699 gssd_ctx_id_t context_handle;
1700 gss_verify_arg arg;
1701 gss_verify_res res;
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",
1709 server);
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)
1741 *qop_state = 0;
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);
1763 OM_uint32
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,
1768 int *qop_state)
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));
1776 /*ARGSUSED*/
1777 static OM_uint32
1778 kgss_seal_wrapped(void *private,
1779 OM_uint32 *minor_status,
1780 const gss_ctx_id_t ctx_handle,
1781 int conf_req_flag,
1782 int qop_req,
1783 const gss_buffer_t input_message_buffer,
1784 int *conf_state,
1785 gss_buffer_t output_message_buffer,
1786 OM_uint32 gssd_context_verifier)
1788 CLIENT *clnt;
1789 gssd_ctx_id_t context_handle;
1791 gss_seal_arg arg;
1792 gss_seal_res res;
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)
1835 *conf_state = 0;
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);
1873 /*ARGSUSED*/
1874 OM_uint32
1875 kgss_seal(OM_uint32 *minor_status,
1876 const gss_ctx_id_t context_handle,
1877 int conf_req_flag,
1878 int qop_req,
1879 const gss_buffer_t input_message_buffer,
1880 int *conf_state,
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));
1892 /*ARGSUSED*/
1893 static OM_uint32
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,
1899 int *conf_state,
1900 int *qop_state,
1901 OM_uint32 gssd_context_verifier)
1903 CLIENT *clnt;
1905 gss_unseal_arg arg;
1906 gss_unseal_res res;
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",
1915 server);
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)
1949 *conf_state = 0;
1950 if (qop_state != NULL)
1951 *qop_state = 0;
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);
1990 OM_uint32
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,
1995 int *conf_state,
1996 int *qop_state)
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));
2006 OM_uint32
2007 kgss_display_status(minor_status,
2008 status_value,
2009 status_type,
2010 mech_type,
2011 message_context,
2012 status_string,
2013 uid)
2014 OM_uint32 *minor_status;
2015 OM_uint32 status_value;
2016 int status_type;
2017 const gss_OID mech_type;
2018 int *message_context;
2019 gss_buffer_t status_string;
2020 uid_t uid;
2022 CLIENT *clnt;
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",
2031 server);
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);
2098 /*ARGSUSED*/
2099 OM_uint32
2100 kgss_indicate_mechs(minor_status,
2101 mech_set,
2102 uid)
2103 OM_uint32 *minor_status;
2104 gss_OID_set *mech_set;
2105 uid_t uid;
2107 CLIENT *clnt;
2108 void *arg;
2109 gss_indicate_mechs_res res;
2110 int i;
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",
2116 server);
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)
2131 *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);
2170 OM_uint32
2171 kgss_inquire_cred_wrapped(minor_status,
2172 cred_handle,
2173 gssd_cred_verifier,
2174 name,
2175 lifetime,
2176 cred_usage,
2177 mechanisms,
2178 uid)
2179 OM_uint32 *minor_status;
2180 const gssd_cred_id_t cred_handle;
2181 OM_uint32 gssd_cred_verifier;
2182 gss_name_t *name;
2183 OM_uint32 *lifetime;
2184 int *cred_usage;
2185 gss_OID_set *mechanisms;
2186 uid_t uid;
2188 CLIENT *clnt;
2190 OM_uint32 minor_status_temp;
2191 gss_buffer_desc external_name;
2192 gss_OID_desc name_type;
2193 int i;
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
2202 * case
2204 if (minor_status != NULL)
2205 *minor_status = DEFAULT_MINOR_STAT;
2206 if (name != NULL)
2207 *name = NULL;
2208 if (lifetime != NULL)
2209 *lifetime = 0;
2210 if (cred_usage != NULL)
2211 *cred_usage = 0;
2212 if (mechanisms != NULL)
2213 *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",
2219 server);
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 */
2257 if (name != NULL) {
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,
2275 (caddr_t)&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);
2306 } else {
2307 if (res.status == GSS_S_COMPLETE &&
2308 mechanisms != NULL)
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);
2322 OM_uint32
2323 kgss_inquire_cred(minor_status,
2324 cred_handle,
2325 name,
2326 lifetime,
2327 cred_usage,
2328 mechanisms,
2329 uid)
2330 OM_uint32 *minor_status;
2331 const gss_cred_id_t cred_handle;
2332 gss_name_t *name;
2333 OM_uint32 *lifetime;
2334 int *cred_usage;
2335 gss_OID_set * mechanisms;
2336 uid_t uid;
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));
2350 OM_uint32
2351 kgss_inquire_cred_by_mech_wrapped(minor_status,
2352 cred_handle,
2353 gssd_cred_verifier,
2354 mech_type,
2355 uid)
2356 OM_uint32 *minor_status;
2357 gssd_cred_id_t cred_handle;
2358 OM_uint32 gssd_cred_verifier;
2359 gss_OID mech_type;
2360 uid_t uid;
2362 CLIENT *clnt;
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",
2371 server);
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);
2420 OM_uint32
2421 kgss_inquire_cred_by_mech(minor_status,
2422 cred_handle,
2423 mech_type,
2424 uid)
2425 OM_uint32 *minor_status;
2426 gss_cred_id_t cred_handle;
2427 gss_OID mech_type;
2428 uid_t uid;
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,
2439 mech_type, uid));
2442 OM_uint32
2443 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
2444 const gss_buffer_t expName;
2445 uid_t *uidOut;
2446 gid_t *gidOut;
2447 gid_t *gids[];
2448 int *gidsLen;
2449 uid_t uid;
2451 CLIENT *clnt;
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);
2459 if (uidOut == NULL)
2460 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2462 /* NULL out output parameters */
2463 *uidOut = UID_NOBODY;
2464 if (gidsLen)
2465 *gidsLen = 0;
2467 if (gids)
2468 *gids = NULL;
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 */
2479 args.uid = uid;
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);
2489 GSSLOG0(1,
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)
2497 *uidOut = res.uid;
2498 if (gidOut)
2499 *gidOut = res.gid;
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);
2513 return (res.major);
2514 } /* kgsscred_expname_to_unix_cred */
2516 OM_uint32
2517 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
2518 gidsLen, uid)
2519 const gss_name_t intName;
2520 const gss_OID mechType;
2521 uid_t *uidOut;
2522 gid_t *gidOut;
2523 gid_t *gids[];
2524 int *gidsLen;
2525 uid_t uid;
2527 CLIENT *clnt;
2528 gsscred_name_to_unix_cred_arg args;
2529 gsscred_name_to_unix_cred_res res;
2530 OM_uint32 major, minor;
2531 gss_OID nameOid;
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);
2538 if (uidOut == NULL)
2539 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2541 /* NULL out the output parameters */
2542 *uidOut = UID_NOBODY;
2543 if (gids)
2544 *gids = NULL;
2546 if (gidsLen)
2547 *gidsLen = 0;
2549 /* get the client handle to gssd */
2550 if ((clnt = getgssd_handle()) == NULL)
2552 GSSLOG(1,
2553 "kgsscred_name_to_unix_cred: can't connect to server %s\n",
2554 server);
2555 return (GSS_S_FAILURE);
2558 /* convert the name to flat representation */
2559 if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
2560 != GSS_S_COMPLETE)
2562 killgssd_handle(clnt);
2563 GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n");
2564 return (major);
2567 /* set the rpc parameters */
2568 args.uid = uid;
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) {
2590 *uidOut = res.uid;
2592 if (gidOut)
2593 *gidOut = res.gid;
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);
2606 return (res.major);
2607 } /* kgsscred_name_to_unix_cred */
2609 OM_uint32
2610 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
2611 const uid_t puid;
2612 gid_t *gidOut;
2613 gid_t *gids[];
2614 int *gidsLen;
2615 uid_t uid;
2617 CLIENT *clnt;
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) {
2628 GSSLOG(1,
2629 "kgss_get_group_info: can't connect to server on %s\n",
2630 server);
2631 return (GSS_S_FAILURE);
2634 /* set the input parameters */
2635 args.uid = uid;
2636 args.puid = puid;
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) {
2648 *gidOut = res.gid;
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);
2658 return (res.major);
2659 } /* kgss_get_group_info */
2661 static char *
2662 kgss_get_kmod(gss_OID mech_oid)
2664 CLIENT *clnt;
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",
2672 server);
2673 return (NULL);
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");
2685 return (NULL);
2687 /* no results to free */
2688 killgssd_handle(clnt);
2690 if (res.module_follow == TRUE) {
2691 return (res.gss_get_kmod_res_u.modname);
2692 } else
2693 return (NULL);
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.
2705 static void
2706 __kgss_reset_mech(gss_mechanism *mechp, gss_OID mech_oid)
2708 gss_mechanism mech;
2709 char *kmod;
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);
2716 if (mech) {
2717 *mechp = mech;
2718 return;
2722 * Get the module name from the kernel.
2724 kmod = kgss_get_kmod(mech_oid);
2726 if (kmod) {
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);
2745 if (mech) {
2746 *mechp = mech;
2750 * If for some reason the module load didn't take,
2751 * we return anyway and hope that the next context
2752 * creation succeeds.
2754 return;
2759 * No kernel module, so enter this mech oid into the list
2760 * using the default sign/seal/etc. operations that upcall to
2761 * gssd.
2763 mutex_enter(&__kgss_mech_lock);
2764 mech = __kgss_get_mechanism(mech_oid);
2765 if (mech) {
2766 mutex_exit(&__kgss_mech_lock);
2767 *mechp = mech;
2768 return;
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.
2779 *mech = default_gc;
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);
2793 *mechp = mech;
2797 * Called with __kgss_mech_lock held.
2799 void
2800 __kgss_add_mechanism(gss_mechanism mech)
2802 gss_mechanism tmp;
2804 tmp = kgss_mech_tail;
2805 kgss_mech_tail = mech;
2807 if (tmp != NULL)
2808 tmp->next = 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
2817 * not supported.
2819 gss_mechanism
2820 __kgss_get_mechanism(gss_OID type)
2822 gss_mechanism mech;
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))
2836 return (mech);
2838 mech = mech->next;
2840 return (NULL);