1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * GSSAPI library stub module for gssd.
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <mechglueP.h>
34 #include "gssd.h"
35 #include <rpc/rpc.h>
36
37 #ifdef _KERNEL
38 #define MALLOC(n) kmem_alloc((n), KM_SLEEP)
39 #define FREE(x, n) kmem_free((x), (n))
40 #define memcpy(dst, src, n) bcopy((src), (dst), (n))
41 #define clnt_pcreateerror(srv) printf("Cannot connect to server on %s\n", srv)
42
43 #ifdef DEBUG
44 #ifndef _SYS_CMN_ERR_H
45 #define _SYS_CMN_ERR_H
46 #define CE_NOTE 1
47 #endif
48 #include <sys/types.h>
49 #include <sys/devops.h>
50 #include <sys/open.h>
51 #include <sys/stat.h>
52 #include <sys/conf.h>
53 #include <sys/ddi.h>
54 #include <sys/sunddi.h>
55 #include <sys/uio.h>
56 #endif /* DEBUG */
57
58 #else /* !_KERNEL */
59 #define MALLOC(n) malloc(n)
60 #define FREE(x, n) free(x)
61 #endif /* _KERNEL */
62 #define DEFAULT_MINOR_STAT ((OM_uint32) ~0)
63
64 CLIENT *clnt, *getgssd_handle();
65 char *server = "localhost";
66
67 OM_uint32
68 kgss_acquire_cred_wrapped(minor_status,
69 desired_name,
70 time_req,
71 desired_mechs,
72 cred_usage,
73 output_cred_handle,
74 actual_mechs,
75 time_rec,
76 uid,
77 gssd_cred_verifier)
78 OM_uint32 *minor_status;
79 gss_name_t desired_name;
80 OM_uint32 time_req;
81 gss_OID_set desired_mechs;
82 int cred_usage;
83 gssd_cred_id_t *output_cred_handle;
84 gss_OID_set *actual_mechs;
85 OM_uint32 *time_rec;
86 uid_t uid;
87 OM_uint32 *gssd_cred_verifier;
88 {
89 OM_uint32 minor_status_temp;
90 gss_buffer_desc external_name;
91 gss_OID name_type;
92 int i;
93
94 gss_acquire_cred_arg arg;
95 gss_acquire_cred_res res;
96
97 /* get the client handle to GSSD */
98
99 if ((clnt = getgssd_handle()) == NULL) {
100 clnt_pcreateerror(server);
101 return (GSS_S_FAILURE);
102 }
103
104 /* convert the desired name from internal to external format */
105
106 if (gss_display_name(&minor_status_temp, desired_name, &external_name,
107 &name_type) != GSS_S_COMPLETE) {
108
109 *minor_status = (OM_uint32) minor_status_temp;
110 gss_release_buffer(&minor_status_temp, &external_name);
111 return ((OM_uint32) GSS_S_FAILURE);
112 }
113
114
115 /* copy the procedure arguments into the rpc arg parameter */
116
117 arg.uid = (OM_uint32)uid;
118
119 arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
120 arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
121
122 arg.name_type.GSS_OID_len =
123 name_type == GSS_C_NULL_OID ?
124 0 : (uint_t)name_type->length;
125
126 arg.name_type.GSS_OID_val =
127 name_type == GSS_C_NULL_OID ?
128 (char *)NULL : (char *)name_type->elements;
129
130 arg.time_req = time_req;
131
132 if (desired_mechs != GSS_C_NULL_OID_SET) {
133 arg.desired_mechs.GSS_OID_SET_len =
134 (uint_t)desired_mechs->count;
135 arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
136 MALLOC(sizeof (GSS_OID) * desired_mechs->count);
137
138 for (i = 0; i < desired_mechs->count; i++) {
139 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
140 (uint_t)desired_mechs->elements[i].length;
141 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
142 (char *)
143 MALLOC(desired_mechs->elements[i].length);
144 memcpy(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
145 desired_mechs->elements[i].elements,
146 desired_mechs->elements[i].length);
147 }
148 } else
149 arg.desired_mechs.GSS_OID_SET_len = 0;
150
151 arg.cred_usage = cred_usage;
152
153 /* call the remote procedure */
154
155 memset(&res, 0, sizeof (res));
156 if (gss_acquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
157
158 /*
159 * if the RPC call times out, null out all return arguments,
160 * set minor_status to its maximum value, and return GSS_S_FAILURE
161 */
162
163 if (minor_status != NULL)
164 *minor_status = DEFAULT_MINOR_STAT;
165 if (output_cred_handle != NULL)
166 *output_cred_handle = NULL;
167 if (actual_mechs != NULL)
168 *actual_mechs = NULL;
169 if (time_rec != NULL)
170 *time_rec = 0;
171
172 return (GSS_S_FAILURE);
173 }
174
175 /* free the allocated memory for the flattened name and desire_mechs */
176
177 gss_release_buffer(&minor_status_temp, &external_name);
178 for (i = 0; i < desired_mechs->count; i++)
179 FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
180 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
181 FREE(arg.desired_mechs.GSS_OID_SET_val,
182 arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
183
184 /* copy the rpc results into the return arguments */
185
186 if (minor_status != NULL)
187 *minor_status = res.minor_status;
188
189 if (output_cred_handle != NULL) {
190 *output_cred_handle =
191 /*LINTED*/
192 *((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
193 *gssd_cred_verifier = res.gssd_cred_verifier;
194 }
195
196 if (res.status == GSS_S_COMPLETE &&
197 res.actual_mechs.GSS_OID_SET_len != 0 &&
198 actual_mechs != NULL) {
199 *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
200 (*actual_mechs)->count =
201 (int)res.actual_mechs.GSS_OID_SET_len;
202 (*actual_mechs)->elements = (gss_OID)
203 MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
204
205 for (i = 0; i < (*actual_mechs)->count; i++) {
206 (*actual_mechs)->elements[i].length = (OM_uint32)
207 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
208 (*actual_mechs)->elements[i].elements =
209 (void *) MALLOC((*actual_mechs)->elements[i].length);
210 memcpy((*actual_mechs)->elements[i].elements,
211 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
212 (*actual_mechs)->elements[i].length);
213 }
214 } else {
215 if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
216 (*actual_mechs)->count = 0;
217 }
218
219 if (time_rec != NULL)
220 *time_rec = res.time_rec;
221
222 /*
223 * free the memory allocated for the results and return with the status
224 * received in the rpc call
225 */
226
227 clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
228 return (res.status);
229 }
230
231 OM_uint32
232 kgss_acquire_cred(minor_status,
233 desired_name,
234 time_req,
235 desired_mechs,
236 cred_usage,
237 output_cred_handle,
238 actual_mechs,
239 time_rec,
240 uid)
241 OM_uint32 *minor_status;
242 gss_name_t desired_name;
243 OM_uint32 time_req;
244 gss_OID_set desired_mechs;
245 int cred_usage;
246 gss_cred_id_t *output_cred_handle;
247 gss_OID_set *actual_mechs;
248 OM_uint32 *time_rec;
249 uid_t uid;
250 {
251
252 OM_uint32 err;
253 struct kgss_cred *kcred;
254
255 kcred = KGSS_CRED_ALLOC();
256 *output_cred_handle = (gss_cred_id_t)kcred;
257 err = kgss_acquire_cred_wrapped(minor_status,
258 desired_name, time_req,
259 desired_mechs, cred_usage,
260 &kcred->gssd_cred, actual_mechs,
261 time_rec, uid,
262 &kcred->gssd_cred_verifier);
263 if (GSS_ERROR(err)) {
264 KGSS_CRED_FREE(kcred);
265 *output_cred_handle = GSS_C_NO_CREDENTIAL;
266 }
267 return (err);
268 }
269
270 OM_uint32
271 kgss_add_cred_wrapped(minor_status,
272 input_cred_handle,
273 gssd_cred_verifier,
274 desired_name,
275 desired_mech_type,
276 cred_usage,
277 initiator_time_req,
278 acceptor_time_req,
279 actual_mechs,
280 initiator_time_rec,
281 acceptor_time_rec,
282 uid)
283 OM_uint32 *minor_status;
284 gssd_cred_id_t input_cred_handle;
285 OM_uint32 gssd_cred_verifier;
286 gss_name_t desired_name;
287 gss_OID desired_mech_type;
288 int cred_usage;
289 int initiator_time_req;
290 int acceptor_time_req;
291 gss_OID_set *actual_mechs;
292 OM_uint32 *initiator_time_rec;
293 OM_uint32 *acceptor_time_rec;
294 uid_t uid;
295 {
296 CLIENT *clnt;
297
298 OM_uint32 minor_status_temp;
299 gss_buffer_desc external_name;
300 gss_OID name_type;
301 int i;
302
303 gss_add_cred_arg arg;
304 gss_add_cred_res res;
305
306 /* get the client handle to GSSD */
307
308 if ((clnt = getgssd_handle()) == NULL) {
309 clnt_pcreateerror(server);
310 return (GSS_S_FAILURE);
311 }
312
313
314 /* convert the desired name from internal to external format */
315
316 if (gss_display_name(&minor_status_temp, desired_name, &external_name,
317 &name_type) != GSS_S_COMPLETE) {
318
319 *minor_status = (OM_uint32) minor_status_temp;
320 (void) gss_release_buffer(&minor_status_temp, &external_name);
321 clnt_pcreateerror(server);
322 return ((OM_uint32) GSS_S_FAILURE);
323 }
324
325
326 /* copy the procedure arguments into the rpc arg parameter */
327
328 arg.uid = (OM_uint32) uid;
329 arg.input_cred_handle.GSS_CRED_ID_T_len =
330 input_cred_handle ==
331 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
332 0 : (uint_t)sizeof (gssd_cred_id_t);
333 arg.input_cred_handle.GSS_CRED_ID_T_val =
334 (char *)&input_cred_handle;
335 arg.gssd_cred_verifier = gssd_cred_verifier;
336 arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
337 arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
338 arg.name_type.GSS_OID_len =
339 name_type == GSS_C_NULL_OID ?
340 0 : (uint_t)name_type->length;
341 arg.name_type.GSS_OID_val =
342 name_type == GSS_C_NULL_OID ?
343 (char *)NULL : (char *)name_type->elements;
344
345 arg.desired_mech_type.GSS_OID_len =
346 (uint_t)(desired_mech_type != GSS_C_NULL_OID ?
347 desired_mech_type->length : 0);
348 arg.desired_mech_type.GSS_OID_val =
349 (char *)(desired_mech_type != GSS_C_NULL_OID ?
350 desired_mech_type->elements : 0);
351 arg.cred_usage = cred_usage;
352 arg.initiator_time_req = initiator_time_req;
353 arg.acceptor_time_req = acceptor_time_req;
354
355 /* call the remote procedure */
356
357 bzero((caddr_t)&res, sizeof (res));
358 if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
359
360 /*
361 * if the RPC call times out, null out all return arguments,
362 * set minor_status to its maximum value, and return
363 * GSS_S_FAILURE
364 */
365
366 if (minor_status != NULL)
367 *minor_status = DEFAULT_MINOR_STAT;
368 if (actual_mechs != NULL)
369 *actual_mechs = NULL;
370 if (initiator_time_rec != NULL)
371 *initiator_time_rec = 0;
372 if (acceptor_time_rec != NULL)
373 *acceptor_time_rec = 0;
374 return (GSS_S_FAILURE);
375 }
376
377 /* free the allocated memory for the flattened name */
378
379 (void) gss_release_buffer(&minor_status_temp, &external_name);
380
381 /* copy the rpc results into the return arguments */
382
383 if (minor_status != NULL)
384 *minor_status = res.minor_status;
385
386 if (res.status == GSS_S_COMPLETE &&
387 res.actual_mechs.GSS_OID_SET_len != 0 &&
388 actual_mechs != NULL) {
389 *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
390 (*actual_mechs)->count =
391 (int)res.actual_mechs.GSS_OID_SET_len;
392 (*actual_mechs)->elements = (gss_OID)
393 MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
394
395 for (i = 0; i < (*actual_mechs)->count; i++) {
396 (*actual_mechs)->elements[i].length = (OM_uint32)
397 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
398 (*actual_mechs)->elements[i].elements =
399 (void *) MALLOC((*actual_mechs)->elements[i].length);
400 memcpy((*actual_mechs)->elements[i].elements,
401 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
402 (*actual_mechs)->elements[i].length);
403 }
404 } else {
405 if (res.status == GSS_S_COMPLETE &&
406 actual_mechs != NULL)
407 (*actual_mechs)->count = 0;
408 }
409 if (initiator_time_rec != NULL)
410 *initiator_time_rec = res.initiator_time_rec;
411 if (acceptor_time_rec != NULL)
412 *acceptor_time_rec = res.acceptor_time_rec;
413
414 /*
415 * free the memory allocated for the results and return with the status
416 * received in the rpc call
417 */
418
419 clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
420 return (res.status);
421
422 }
423
424 OM_uint32
425 kgss_add_cred(minor_status,
426 input_cred_handle,
427 desired_name,
428 desired_mech_type,
429 cred_usage,
430 initiator_time_req,
431 acceptor_time_req,
432 actual_mechs,
433 initiator_time_rec,
434 acceptor_time_rec,
435 uid)
436 OM_uint32 *minor_status;
437 gss_cred_id_t input_cred_handle;
438 gss_name_t desired_name;
439 gss_OID desired_mech_type;
440 int cred_usage;
441 int initiator_time_req;
442 int acceptor_time_req;
443 gss_OID_set *actual_mechs;
444 OM_uint32 *initiator_time_rec;
445 OM_uint32 *acceptor_time_rec;
446 uid_t uid;
447 {
448
449 OM_uint32 err;
450 OM_uint32 gssd_cred_verifier;
451 gssd_cred_id_t gssd_input_cred_handle;
452
453
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_cred_id_t)GSS_C_NO_CREDENTIAL;
459
460 err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
461 gssd_cred_verifier, desired_name, desired_mech_type,
462 cred_usage, initiator_time_req, acceptor_time_req,
463 actual_mechs, initiator_time_rec,
464 acceptor_time_rec, uid);
465 return (err);
466 }
467
468 OM_uint32
469 kgss_release_cred_wrapped(minor_status,
470 cred_handle,
471 uid,
472 gssd_cred_verifier)
473 OM_uint32 *minor_status;
474 gssd_cred_id_t *cred_handle;
475 uid_t uid;
476 OM_uint32 gssd_cred_verifier;
477 {
478
479 gss_release_cred_arg arg;
480 gss_release_cred_res res;
481
482
483 /* get the client handle to GSSD */
484 if ((clnt = getgssd_handle()) == NULL) {
485 clnt_pcreateerror(server);
486 return (GSS_S_FAILURE);
487 }
488
489 /* copy the procedure arguments into the rpc arg parameter */
490
491 arg.uid = (OM_uint32) uid;
492 arg.gssd_cred_verifier = gssd_cred_verifier;
493
494 if (cred_handle != NULL) {
495 arg.cred_handle.GSS_CRED_ID_T_len =
496 (uint_t)sizeof (gssd_cred_id_t);
497 arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
498 } else
499 arg.cred_handle.GSS_CRED_ID_T_len = 0;
500
501 /* call the remote procedure */
502
503 memset(&res, 0, sizeof (res));
504 if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
505
506 /*
507 * if the RPC call times out, null out all return arguments,
508 * set minor_status to its max value, and return GSS_S_FAILURE
509 */
510
511 if (minor_status != NULL)
512 *minor_status = DEFAULT_MINOR_STAT;
513 if (cred_handle != NULL)
514 *cred_handle = NULL;
515
516 return (GSS_S_FAILURE);
517 }
518
519 /* if the release succeeded, null out the cred_handle */
520 if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
521 *cred_handle = NULL;
522
523 /* copy the rpc results into the return arguments */
524 if (minor_status != NULL)
525 *minor_status = res.minor_status;
526
527 /* return with status returned in rpc call */
528 return (res.status);
529 }
530
531 OM_uint32
532 kgss_release_cred(minor_status,
533 cred_handle,
534 uid)
535 OM_uint32 *minor_status;
536 gss_cred_id_t *cred_handle;
537 uid_t uid;
538
539 {
540
541 OM_uint32 err;
542 struct kgss_cred *kcred;
543
544 if (*cred_handle == GSS_C_NO_CREDENTIAL)
545 return (GSS_S_COMPLETE);
546 else
547 kcred = KCRED_TO_KGSS_CRED(*cred_handle);
548
549 err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
550 uid, kcred->gssd_cred_verifier);
551 KGSS_CRED_FREE(kcred);
552 *cred_handle = GSS_C_NO_CREDENTIAL;
553 return (err);
554 }
555
556 OM_uint32
557 kgss_init_sec_context_wrapped(minor_status,
558 claimant_cred_handle,
559 gssd_cred_verifier,
560 context_handle,
561 gssd_context_verifier,
562 target_name,
563 mech_type,
564 req_flags,
565 time_req,
566 input_chan_bindings,
567 input_token,
568 actual_mech_type,
569 output_token,
570 ret_flags,
571 time_rec,
572 uid)
573 OM_uint32 *minor_status;
574 gssd_cred_id_t claimant_cred_handle;
575 OM_uint32 gssd_cred_verifier;
576 OM_uint32 *context_handle;
577 OM_uint32 *gssd_context_verifier;
578 gss_name_t target_name;
579 gss_OID mech_type;
580 int req_flags;
581 OM_uint32 time_req;
582 gss_channel_bindings_t input_chan_bindings;
583 gss_buffer_t input_token;
584 gss_OID *actual_mech_type;
585 gss_buffer_t output_token;
586 int *ret_flags;
587 OM_uint32 *time_rec;
588 uid_t uid;
589 {
590 OM_uint32 minor_status_temp;
591 gss_buffer_desc external_name;
592 gss_OID name_type;
593 gss_init_sec_context_arg arg;
594 gss_init_sec_context_res res;
595
596 /* get the client handle to GSSD */
597
598 if ((clnt = getgssd_handle()) == NULL) {
599 clnt_pcreateerror(server);
600 return (GSS_S_FAILURE);
601 }
602
603 /* convert the target name from internal to external format */
604
605 if (gss_display_name(&minor_status_temp, target_name,
606 &external_name, &name_type) != GSS_S_COMPLETE) {
607
608 *minor_status = (OM_uint32) minor_status_temp;
609 return ((OM_uint32) GSS_S_FAILURE);
610 }
611
612
613 /* copy the procedure arguments into the rpc arg parameter */
614
615 arg.uid = (OM_uint32) uid;
616
617 arg.context_handle.GSS_CTX_ID_T_len =
618 *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
619 (uint_t)sizeof (OM_uint32);
620 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
621 arg.gssd_context_verifier = *gssd_context_verifier;
622
623 arg.claimant_cred_handle.GSS_CRED_ID_T_len =
624 claimant_cred_handle == (gssd_cred_id_t)GSS_C_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;
629
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;
632
633 arg.name_type.GSS_OID_len =
634 name_type == GSS_C_NULL_OID ?
635 0 : (uint_t)name_type->length;
636
637 arg.name_type.GSS_OID_val =
638 name_type == GSS_C_NULL_OID ?
639 (char *)NULL : (char *)name_type->elements;
640
641 arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
642 mech_type->length : 0);
643 arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
644 mech_type->elements : 0);
645
646 arg.req_flags = req_flags;
647
648 arg.time_req = time_req;
649
650 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
651 arg.input_chan_bindings.present = YES;
652 arg.input_chan_bindings.initiator_addrtype =
653 input_chan_bindings->initiator_addrtype;
654 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
655 (uint_t)input_chan_bindings->initiator_address.length;
656 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
657 (void *) input_chan_bindings->initiator_address.value;
658 arg.input_chan_bindings.acceptor_addrtype =
659 input_chan_bindings->acceptor_addrtype;
660 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
661 (uint_t)input_chan_bindings->acceptor_address.length;
662 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
663 (void *) input_chan_bindings->acceptor_address.value;
664 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
665 (uint_t)input_chan_bindings->application_data.length;
666 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
667 (void *) input_chan_bindings->application_data.value;
668 } else {
669 arg.input_chan_bindings.present = NO;
670 arg.input_chan_bindings.initiator_addrtype = 0;
671 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
672 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
673 arg.input_chan_bindings.acceptor_addrtype = 0;
674 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
675 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
676 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
677 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
678 }
679
680 arg.input_token.GSS_BUFFER_T_len = (uint_t)
681 (input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
682 arg.input_token.GSS_BUFFER_T_val = (char *)
683 (input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
684
685 /* initialize the output parameters to empty values */
686 if (minor_status != NULL)
687 *minor_status = DEFAULT_MINOR_STAT;
688 if (actual_mech_type != NULL)
689 *actual_mech_type = NULL;
690 if (output_token != NULL)
691 output_token->length = 0;
692 if (ret_flags != NULL)
693 *ret_flags = 0;
694 if (time_rec != NULL)
695 *time_rec = 0;
696
697 /* call the remote procedure */
698 memset(&res, 0, sizeof (res));
699 if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
700
701 /* free the allocated memory for the flattened name */
702 gss_release_buffer(&minor_status_temp, &external_name);
703
704 return (GSS_S_FAILURE);
705 }
706
707 /*
708 * We could return from a GSS error here and need to return both the
709 * minor_status and output_token, back to the caller if applicable.
710 */
711 if (minor_status != NULL)
712 *minor_status = res.minor_status;
713
714 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
715 output_token->length =
716 (size_t)res.output_token.GSS_BUFFER_T_len;
717 output_token->value =
718 (void *)res.output_token.GSS_BUFFER_T_val;
719 res.output_token.GSS_BUFFER_T_val = NULL;
720 res.output_token.GSS_BUFFER_T_len = 0;
721 }
722
723 /* free the allocated memory for the flattened name */
724 gss_release_buffer(&minor_status_temp, &external_name);
725
726 /* if the call was successful, copy out the results */
727 if (res.status == (OM_uint32) GSS_S_COMPLETE ||
728 res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
729 /*
730 * copy the rpc results into the return argument
731 * on CONTINUE_NEEDED only ctx handle is ready.
732 */
733 /*LINTED*/
734 *context_handle = *((OM_uint32 *)
735 res.context_handle.GSS_CTX_ID_T_val);
736 *gssd_context_verifier = res.gssd_context_verifier;
737
738
739 /* the rest of the parameters is only ready on COMPLETE */
740 if (res.status == GSS_S_COMPLETE) {
741 if (actual_mech_type != NULL) {
742 *actual_mech_type = (gss_OID)
743 MALLOC(sizeof (gss_OID_desc));
744 (*actual_mech_type)->length = (OM_UINT32)
745 res.actual_mech_type.GSS_OID_len;
746 (*actual_mech_type)->elements = (void *)
747 MALLOC((*actual_mech_type)->length);
748 memcpy((*actual_mech_type)->elements, (void *)
749 res.actual_mech_type.GSS_OID_val,
750 (*actual_mech_type)->length);
751 }
752
753
754 if (ret_flags != NULL)
755 *ret_flags = res.ret_flags;
756
757 if (time_rec != NULL)
758 *time_rec = res.time_rec;
759 }
760 }
761
762
763 /*
764 * free the memory allocated for the results and return with the
765 * status received in the rpc call.
766 */
767
768 clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
769 return (res.status);
770 }
771 OM_uint32
772 kgss_init_sec_context(
773 OM_uint32 *minor_status,
774 gss_cred_id_t claimant_cred_handle,
775 gss_ctx_id_t *context_handle,
776 gss_name_t target_name,
777 gss_OID mech_type,
778 int req_flags,
779 OM_uint32 time_req,
780 gss_channel_bindings_t input_chan_bindings,
781 gss_buffer_t input_token,
782 gss_OID *actual_mech_type,
783 gss_buffer_t output_token,
784 int *ret_flags,
785 OM_uint32 *time_rec,
786 uid_t uid)
787 {
788 OM_uint32 err;
789 struct kgss_ctx *kctx;
790 OM_uint32 gssd_cred_verifier;
791 gssd_cred_id_t gssd_cl_cred_handle;
792
793 /*
794 * If this is an initial call, we'll need to create the
795 * wrapper struct that contains kernel state information, and
796 * a reference to the handle from gssd.
797 */
798 if (*context_handle == GSS_C_NO_CONTEXT) {
799 kctx = KGSS_ALLOC();
800 *context_handle = (gss_ctx_id_t)kctx;
801 kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
802 } else
803 kctx = (struct kgss_ctx *)*context_handle;
804
805 if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
806 gssd_cred_verifier =
807 KCRED_TO_CREDV(claimant_cred_handle);
808 gssd_cl_cred_handle =
809 KCRED_TO_CRED(claimant_cred_handle);
810 } else
811 gssd_cl_cred_handle =
812 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
813
814 err = kgss_init_sec_context_wrapped(minor_status,
815 gssd_cl_cred_handle,
816 gssd_cred_verifier, &kctx->gssd_ctx,
817 &kctx->gssd_ctx_verifier,
818 target_name, mech_type, req_flags, time_req,
819 input_chan_bindings, input_token, actual_mech_type,
820 output_token, ret_flags, time_rec, uid);
821
822 if (GSS_ERROR(err)) {
823 KGSS_FREE(kctx);
824 *context_handle = GSS_C_NO_CONTEXT;
825 }
826 return (err);
827 }
828 OM_uint32
829 kgss_accept_sec_context_wrapped(minor_status,
830 context_handle,
831 gssd_context_verifier,
832 verifier_cred_handle,
833 gssd_cred_verifier,
834 input_token,
835 input_chan_bindings,
836 src_name,
837 mech_type,
838 output_token,
839 ret_flags,
840 time_rec,
841 delegated_cred_handle,
842 uid)
843 OM_uint32 *minor_status;
844 gssd_ctx_id_t *context_handle;
845 OM_uint32 *gssd_context_verifier;
846 gssd_cred_id_t verifier_cred_handle;
847 OM_uint32 gssd_cred_verifier;
848 gss_buffer_t input_token;
849 gss_channel_bindings_t input_chan_bindings;
850 gss_buffer_t src_name;
851 gss_OID *mech_type;
852 gss_buffer_t output_token;
853 int *ret_flags;
854 OM_uint32 *time_rec;
855 gss_cred_id_t *delegated_cred_handle;
856 uid_t uid;
857 {
858 gss_accept_sec_context_arg arg;
859 gss_accept_sec_context_res res;
860 struct kgss_cred *kcred;
861
862 /* get the client handle to GSSD */
863 if ((clnt = getgssd_handle()) == NULL) {
864 clnt_pcreateerror(server);
865 return (GSS_S_FAILURE);
866 }
867
868 /* copy the procedure arguments into the rpc arg parameter */
869 arg.uid = (OM_uint32) uid;
870
871 arg.context_handle.GSS_CTX_ID_T_len =
872 *context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ?
873 0 : (uint_t)sizeof (gssd_ctx_id_t);
874 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
875 arg.gssd_context_verifier =
876 *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ?
877 0 : *gssd_context_verifier;
878
879 arg.verifier_cred_handle.GSS_CRED_ID_T_len =
880 verifier_cred_handle ==
881 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
882 0 : (uint_t)sizeof (gssd_cred_id_t);
883 arg.verifier_cred_handle.GSS_CRED_ID_T_val =
884 (char *)&verifier_cred_handle;
885 arg.gssd_cred_verifier = gssd_cred_verifier;
886
887 arg.input_token_buffer.GSS_BUFFER_T_len =
888 (uint_t)(input_token != GSS_C_NO_BUFFER ?
889 input_token->length : 0);
890 arg.input_token_buffer.GSS_BUFFER_T_val =
891 (char *)(input_token != GSS_C_NO_BUFFER ?
892 input_token->value : 0);
893
894 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
895 arg.input_chan_bindings.present = YES;
896 arg.input_chan_bindings.initiator_addrtype =
897 input_chan_bindings->initiator_addrtype;
898 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
899 (uint_t)input_chan_bindings->initiator_address.length;
900 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
901 (void *) input_chan_bindings->initiator_address.value;
902 arg.input_chan_bindings.acceptor_addrtype =
903 input_chan_bindings->acceptor_addrtype;
904 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
905 (uint_t)input_chan_bindings->acceptor_address.length;
906 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
907 (void *) input_chan_bindings->acceptor_address.value;
908 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
909 (uint_t)input_chan_bindings->application_data.length;
910 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
911 (void *) input_chan_bindings->application_data.value;
912 } else {
913 arg.input_chan_bindings.present = NO;
914 arg.input_chan_bindings.initiator_addrtype = 0;
915 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
916 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
917 arg.input_chan_bindings.acceptor_addrtype = 0;
918 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
919 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
920 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
921 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
922 }
923
924 /* set the output parameters to empty values.... */
925 if (minor_status != NULL)
926 *minor_status = DEFAULT_MINOR_STAT;
927 if (src_name != NULL) {
928 src_name->length = 0;
929 src_name->value = NULL;
930 }
931 if (mech_type != NULL)
932 *mech_type = NULL;
933 if (output_token != NULL)
934 output_token->length = 0;
935 if (ret_flags != NULL)
936 *ret_flags = 0;
937 if (time_rec != NULL)
938 *time_rec = 0;
939 if (delegated_cred_handle != NULL)
940 *delegated_cred_handle = NULL;
941
942 /* call the remote procedure */
943 memset(&res, 0, sizeof (res));
944 if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
945 return (GSS_S_FAILURE);
946 }
947
948 /*
949 * We could return from a GSS error here and need to return both the
950 * minor_status and output_token, back to the caller if applicable.
951 */
952 if (minor_status != NULL)
953 *minor_status = res.minor_status;
954
955 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
956 output_token->length =
957 res.output_token.GSS_BUFFER_T_len;
958 output_token->value =
959 (void *) res.output_token.GSS_BUFFER_T_val;
960 res.output_token.GSS_BUFFER_T_val = 0;
961 res.output_token.GSS_BUFFER_T_len = 0;
962 }
963
964 if (res.status == (OM_uint32) GSS_S_COMPLETE ||
965 res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
966 /*
967 * when gss returns CONTINUE_NEEDED we can only
968 * use the context parameter.
969 */
970 /*LINTED*/
971 *context_handle = *((gssd_ctx_id_t *)
972 res.context_handle.GSS_CTX_ID_T_val);
973 *gssd_context_verifier = res.gssd_context_verifier;
974
975 /* the other parameters are ready on for COMPLETE */
976 if (res.status == GSS_S_COMPLETE)
977 {
978 /*
979 * The src_name is in external format.
980 */
981 if (src_name != NULL) {
982 src_name->length = res.src_name.GSS_BUFFER_T_len;
983 src_name->value = res.src_name.GSS_BUFFER_T_val;
984 res.src_name.GSS_BUFFER_T_val = NULL;
985 res.src_name.GSS_BUFFER_T_len = 0;
986 }
987 /*
988 * move mech type returned to mech_type
989 * for gss_import_name_for_mech()
990 */
991 if (mech_type != NULL) {
992 *mech_type =
993 (gss_OID) MALLOC(sizeof (gss_OID_desc));
994 (*mech_type)->length =
995 (OM_UINT32) res.mech_type.GSS_OID_len;
996 (*mech_type)->elements =
997 (void *) MALLOC((*mech_type)->length);
998 memcpy((*mech_type)->elements,
999 res.mech_type.GSS_OID_val,
1000 (*mech_type)->length);
1001 }
1002
1003 if (ret_flags != NULL)
1004 *ret_flags = res.ret_flags;
1005
1006 if (time_rec != NULL)
1007 *time_rec = res.time_rec;
1008
1009 if ((delegated_cred_handle != NULL) &&
1010 (res.delegated_cred_handle.GSS_CRED_ID_T_len
1011 != 0)) {
1012 kcred = KGSS_CRED_ALLOC();
1013 /*LINTED*/
1014 kcred->gssd_cred = *((gssd_cred_id_t *)
1015 res.delegated_cred_handle.GSS_CRED_ID_T_val);
1016 kcred->gssd_cred_verifier =
1017 res.gssd_context_verifier;
1018 *delegated_cred_handle = (gss_cred_id_t)kcred;
1019 }
1020 } /* res.status == GSS_S_COMPLETE */
1021 } /* res.status == GSS_S_COMPLETE or GSS_CONTINUE_NEEDED */
1022
1023
1024 /*
1025 * free the memory allocated for the results and return with the status
1026 * received in the rpc call
1027 */
1028
1029 clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
1030 return (res.status);
1031 }
1032
1033 OM_uint32
1034 kgss_accept_sec_context(
1035 OM_uint32 *minor_status,
1036 gss_ctx_id_t *context_handle,
1037 gss_cred_id_t verifier_cred_handle,
1038 gss_buffer_t input_token,
1039 gss_channel_bindings_t input_chan_bindings,
1040 gss_buffer_t src_name,
1041 gss_OID *mech_type,
1042 gss_buffer_t output_token,
1043 int *ret_flags,
1044 OM_uint32 *time_rec,
1045 gss_cred_id_t *delegated_cred_handle,
1046 uid_t uid)
1047 {
1048 OM_uint32 err;
1049 struct kgss_ctx *kctx;
1050 OM_uint32 gssd_cred_verifier;
1051 gssd_cred_id_t gssd_ver_cred_handle;
1052
1053
1054 if (*context_handle == GSS_C_NO_CONTEXT) {
1055 kctx = KGSS_ALLOC();
1056 *context_handle = (gss_ctx_id_t)kctx;
1057 kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT;
1058 } else
1059 kctx = (struct kgss_ctx *)*context_handle;
1060
1061 if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
1062 gssd_cred_verifier =
1063 KCRED_TO_CREDV(verifier_cred_handle);
1064 gssd_ver_cred_handle =
1065 KCRED_TO_CRED(verifier_cred_handle);
1066 } else
1067 gssd_ver_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
1068
1069 err = kgss_accept_sec_context_wrapped(minor_status,
1070 &kctx->gssd_ctx,
1071 &kctx->gssd_ctx_verifier, gssd_ver_cred_handle,
1072 gssd_cred_verifier, input_token, input_chan_bindings,
1073 src_name, mech_type, output_token, ret_flags,
1074 time_rec, delegated_cred_handle, uid);
1075
1076 if (GSS_ERROR(err)) {
1077 KGSS_FREE(kctx);
1078 *context_handle = GSS_C_NO_CONTEXT;
1079
1080 }
1081
1082 return (err);
1083 }
1084
1085 OM_uint32
1086 kgss_process_context_token(minor_status,
1087 context_handle,
1088 token_buffer,
1089 uid)
1090 OM_uint32 *minor_status;
1091 gss_ctx_id_t context_handle;
1092 gss_buffer_t token_buffer;
1093 uid_t uid;
1094 {
1095 OM_uint32 gssd_context_verifier;
1096
1097 gss_process_context_token_arg arg;
1098 gss_process_context_token_res res;
1099
1100 gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
1101
1102 /* get the client handle to GSSD */
1103
1104 if ((clnt = getgssd_handle()) == NULL) {
1105 clnt_pcreateerror(server);
1106 return (GSS_S_FAILURE);
1107 }
1108
1109 /* copy the procedure arguments into the rpc arg parameter */
1110 arg.uid = (OM_uint32) uid;
1111
1112 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
1113 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1114 arg.gssd_context_verifier = gssd_context_verifier;
1115 arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer;
1116 arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
1117
1118 /* call the remote procedure */
1119
1120 memset(&res, 0, sizeof (res));
1121 if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
1122
1123 /*
1124 * if the RPC call times out, null out all return arguments,
1125 * set minor_status to its maximum value, and return GSS_S_FAILURE
1126 */
1127
1128 if (minor_status != NULL)
1129 *minor_status = DEFAULT_MINOR_STAT;
1130
1131 return (GSS_S_FAILURE);
1132 }
1133
1134 /* copy the rpc results into the return arguments */
1135
1136 if (minor_status != NULL)
1137 *minor_status = res.minor_status;
1138
1139 /* return with status returned in rpc call */
1140
1141 return (res.status);
1142 }
1143
1144 OM_uint32
1145 kgss_delete_sec_context_wrapped(minor_status,
1146 context_handle,
1147 gssd_context_verifier,
1148 output_token)
1149 OM_uint32 *minor_status;
1150 gssd_ctx_id_t *context_handle;
1151 OM_uint32 gssd_context_verifier;
1152 gss_buffer_t output_token;
1153 {
1154 gss_delete_sec_context_arg arg;
1155 gss_delete_sec_context_res res;
1156
1157
1158 /* get the client handle to GSSD */
1159 if ((clnt = getgssd_handle()) == NULL) {
1160 clnt_pcreateerror(server);
1161 return (GSS_S_FAILURE);
1162 }
1163
1164 /* copy the procedure arguments into the rpc arg parameter */
1165
1166 arg.context_handle.GSS_CTX_ID_T_len =
1167 *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
1168 (uint_t)sizeof (OM_uint32);
1169 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
1170
1171 arg.gssd_context_verifier = gssd_context_verifier;
1172
1173 /* call the remote procedure */
1174
1175 memset(&res, 0, sizeof (res));
1176 if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
1177
1178 /*
1179 * if the RPC call times out, null out all return arguments,
1180 * set minor_status to its max value, and return GSS_S_FAILURE
1181 */
1182
1183 if (minor_status != NULL)
1184 *minor_status = DEFAULT_MINOR_STAT;
1185 if (context_handle != NULL)
1186 *context_handle = NULL;
1187 if (output_token != NULL)
1188 output_token->length = 0;
1189
1190 return (GSS_S_FAILURE);
1191 }
1192
1193 /* copy the rpc results into the return arguments */
1194
1195 if (minor_status != NULL)
1196 *minor_status = res.minor_status;
1197
1198 if (res.context_handle.GSS_CTX_ID_T_len == 0)
1199 *context_handle = NULL;
1200 else
1201 /*LINTED*/
1202 *context_handle = *((gssd_ctx_id_t *)
1203 res.context_handle.GSS_CTX_ID_T_val);
1204
1205 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
1206 output_token->length = res.output_token.GSS_BUFFER_T_len;
1207 output_token->value = res.output_token.GSS_BUFFER_T_val;
1208 res.output_token.GSS_BUFFER_T_len = 0;
1209 res.output_token.GSS_BUFFER_T_val = NULL;
1210 }
1211
1212 /*
1213 * free the memory allocated for the results and return with the status
1214 * received in the rpc call
1215 */
1216
1217 clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
1218 return (res.status);
1219 }
1220
1221 /*ARGSUSED*/
1222 OM_uint32
1223 kgss_delete_sec_context(
1224 OM_uint32 *minor_status,
1225 gss_ctx_id_t *context_handle,
1226 gss_buffer_t output_token)
1227 {
1228 OM_uint32 err;
1229 struct kgss_ctx *kctx;
1230
1231 if (*context_handle == GSS_C_NO_CONTEXT) {
1232 return (GSS_S_NO_CONTEXT);
1233 } else
1234 kctx = KCTX_TO_KGSS_CTX(*context_handle);
1235
1236 err = kgss_delete_sec_context_wrapped(minor_status,
1237 &kctx->gssd_ctx, kctx->gssd_ctx_verifier,
1238 output_token);
1239
1240 if (kctx->gssd_ctx != (gssd_ctx_id_t)GSS_C_NO_CONTEXT)
1241 err = GSS_S_FAILURE;
1242 else
1243 err = GSS_S_COMPLETE;
1244
1245 KGSS_FREE(kctx);
1246 *context_handle = GSS_C_NO_CONTEXT;
1247 return (err);
1248 }
1249
1250 /*ARGSUSED*/
1251 OM_uint32
1252 kgss_context_time(minor_status,
1253 context_handle,
1254 time_rec,
1255 uid)
1256 OM_uint32 *minor_status;
1257 gss_ctx_id_t context_handle;
1258 OM_uint32 *time_rec;
1259 uid_t uid;
1260 {
1261 return (GSS_S_FAILURE);
1262 }
1263
1264 OM_uint32
1265 kgss_sign_wrapped(minor_status,
1266 context_handle,
1267 qop_req,
1268 message_buffer,
1269 msg_token,
1270 gssd_context_verifier)
1271 OM_uint32 *minor_status;
1272 gssd_ctx_id_t context_handle;
1273 OM_uint32 gssd_context_verifier;
1274 int qop_req;
1275 gss_buffer_t message_buffer;
1276 gss_buffer_t msg_token;
1277 {
1278
1279 gss_sign_arg arg;
1280 gss_sign_res res;
1281
1282 /* get the client handle to GSSD */
1283
1284 if ((clnt = getgssd_handle()) == NULL) {
1285 clnt_pcreateerror(server);
1286 return (GSS_S_FAILURE);
1287 }
1288
1289 /* copy the procedure arguments into the rpc arg parameter */
1290
1291
1292 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1293 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1294 arg.gssd_context_verifier = gssd_context_verifier;
1295
1296 arg.qop_req = qop_req;
1297 arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
1298 arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
1299
1300 /* call the remote procedure */
1301
1302 memset(&res, 0, sizeof (res));
1303 if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
1304
1305 /*
1306 * if the RPC call times out, null out all return arguments,
1307 * set minor_status to its maximum value, and return GSS_S_FAILURE
1308 */
1309
1310 if (minor_status != NULL)
1311 *minor_status = DEFAULT_MINOR_STAT;
1312 if (msg_token != NULL)
1313 msg_token->length = 0;
1314
1315 return (GSS_S_FAILURE);
1316 }
1317
1318 /* copy the rpc results into the return arguments */
1319
1320 if (minor_status != NULL)
1321 *minor_status = res.minor_status;
1322
1323 if (msg_token != NULL) {
1324 msg_token->length = res.msg_token.GSS_BUFFER_T_len;
1325 msg_token->value = (void *) MALLOC(msg_token->length);
1326 memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
1327 msg_token->length);
1328 }
1329
1330 /*
1331 * free the memory allocated for the results and return with the status
1332 * received in the rpc call
1333 */
1334
1335 clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
1336 return (res.status);
1337 }
1338
1339 OM_uint32
1340 kgss_sign(
1341 OM_uint32 *minor_status,
1342 gss_ctx_id_t context_handle,
1343 int qop_req,
1344 gss_buffer_t message_buffer,
1345 gss_buffer_t msg_token)
1346 {
1347 if (context_handle == GSS_C_NO_CONTEXT)
1348 return (GSS_S_FAILURE);
1349
1350 return (KGSS_SIGN(minor_status,
1351 context_handle, qop_req, message_buffer,
1352 msg_token));
1353 }
1354
1355 OM_uint32
1356 kgss_verify_wrapped(
1357 minor_status,
1358 context_handle,
1359 message_buffer,
1360 token_buffer,
1361 qop_state,
1362 gssd_context_verifier)
1363 OM_uint32 *minor_status;
1364 gssd_ctx_id_t context_handle;
1365 OM_uint32 gssd_context_verifier;
1366 gss_buffer_t message_buffer;
1367 gss_buffer_t token_buffer;
1368 int *qop_state;
1369 {
1370 gss_verify_arg arg;
1371 gss_verify_res res;
1372
1373 /* get the client handle to GSSD */
1374
1375 if ((clnt = getgssd_handle()) == NULL) {
1376 clnt_pcreateerror(server);
1377 return (GSS_S_FAILURE);
1378 }
1379
1380 /* copy the procedure arguments into the rpc arg parameter */
1381
1382 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1383 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1384
1385 arg.gssd_context_verifier = gssd_context_verifier;
1386
1387 arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
1388 arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
1389
1390 arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
1391 arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
1392
1393 /* call the remote procedure */
1394
1395 memset(&res, 0, sizeof (res));
1396 if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
1397
1398 /*
1399 * if the RPC call times out, null out all return arguments,
1400 * set minor_status to its maximum value, and return GSS_S_FAILURE
1401 */
1402
1403 if (minor_status != NULL)
1404 *minor_status = DEFAULT_MINOR_STAT;
1405 if (qop_state != NULL)
1406 *qop_state = 0;
1407
1408 return (GSS_S_FAILURE);
1409 }
1410
1411 /* copy the rpc results into the return arguments */
1412
1413 if (minor_status != NULL)
1414 *minor_status = res.minor_status;
1415
1416 if (qop_state != NULL)
1417 *qop_state = res.qop_state;
1418
1419 /* return with status returned in rpc call */
1420
1421 return (res.status);
1422 }
1423
1424 OM_uint32
1425 kgss_verify(OM_uint32 *minor_status,
1426 gss_ctx_id_t context_handle,
1427 gss_buffer_t message_buffer,
1428 gss_buffer_t token_buffer,
1429 int *qop_state)
1430 {
1431 if (context_handle == GSS_C_NO_CONTEXT)
1432 return (GSS_S_FAILURE);
1433
1434 return (KGSS_VERIFY(minor_status, context_handle,
1435 message_buffer,
1436 token_buffer, qop_state));
1437 }
1438
1439
1440 /* EXPORT DELETE START */
1441
1442 OM_uint32
1443 kgss_seal_wrapped(
1444 minor_status,
1445 context_handle,
1446 conf_req_flag,
1447 qop_req,
1448 input_message_buffer,
1449 conf_state,
1450 output_message_buffer,
1451 gssd_context_verifier)
1452
1453 OM_uint32 *minor_status;
1454 gssd_ctx_id_t context_handle;
1455 OM_uint32 gssd_context_verifier;
1456 int conf_req_flag;
1457 int qop_req;
1458 gss_buffer_t input_message_buffer;
1459 int *conf_state;
1460 gss_buffer_t output_message_buffer;
1461 {
1462 gss_seal_arg arg;
1463 gss_seal_res res;
1464
1465 /* get the client handle to GSSD */
1466
1467 if ((clnt = getgssd_handle()) == NULL) {
1468 clnt_pcreateerror(server);
1469 return (GSS_S_FAILURE);
1470 }
1471
1472 /* copy the procedure arguments into the rpc arg parameter */
1473
1474
1475 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1476 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1477 arg.gssd_context_verifier = gssd_context_verifier;
1478
1479 arg.conf_req_flag = conf_req_flag;
1480
1481 arg.qop_req = qop_req;
1482
1483 arg.input_message_buffer.GSS_BUFFER_T_len =
1484 (uint_t)input_message_buffer->length;
1485
1486 arg.input_message_buffer.GSS_BUFFER_T_val =
1487 (char *)input_message_buffer->value;
1488
1489 /* call the remote procedure */
1490
1491 memset(&res, 0, sizeof (res));
1492 if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1493
1494 /*
1495 * if the RPC call times out, null out all return arguments,
1496 * set minor_status to its maximum value, and return GSS_S_FAILURE
1497 */
1498
1499 if (minor_status != NULL)
1500 *minor_status = DEFAULT_MINOR_STAT;
1501 if (conf_state != NULL)
1502 *conf_state = 0;
1503 if (output_message_buffer != NULL)
1504 output_message_buffer->length = 0;
1505
1506 return (GSS_S_FAILURE);
1507 }
1508
1509 /* copy the rpc results into the return arguments */
1510
1511 if (minor_status != NULL)
1512 *minor_status = res.minor_status;
1513
1514 if (conf_state != NULL)
1515 *conf_state = res.conf_state;
1516
1517 if (output_message_buffer != NULL) {
1518 output_message_buffer->length =
1519 res.output_message_buffer.GSS_BUFFER_T_len;
1520
1521 output_message_buffer->value =
1522 (void *) MALLOC(output_message_buffer->length);
1523 memcpy(output_message_buffer->value,
1524 res.output_message_buffer.GSS_BUFFER_T_val,
1525 output_message_buffer->length);
1526 }
1527
1528 /*
1529 * free the memory allocated for the results and return with the status
1530 * received in the rpc call
1531 */
1532
1533 clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
1534 return (res.status);
1535 }
1536
1537 OM_uint32
1538 kgss_seal(OM_uint32 *minor_status,
1539 gss_ctx_id_t context_handle,
1540 int conf_req_flag,
1541 int qop_req,
1542 gss_buffer_t input_message_buffer,
1543 int *conf_state,
1544 gss_buffer_t output_message_buffer)
1545
1546 {
1547 if (context_handle == GSS_C_NO_CONTEXT)
1548 return (GSS_S_FAILURE);
1549
1550 return (KGSS_SEAL(minor_status, context_handle,
1551 conf_req_flag, qop_req,
1552 input_message_buffer,
1553 conf_state, output_message_buffer));
1554 }
1555
1556 OM_uint32
1557 kgss_unseal_wrapped(minor_status,
1558 context_handle,
1559 input_message_buffer,
1560 output_message_buffer,
1561 conf_state,
1562 qop_state,
1563 gssd_context_verifier)
1564 OM_uint32 *minor_status;
1565 gssd_ctx_id_t context_handle;
1566 OM_uint32 gssd_context_verifier;
1567 gss_buffer_t input_message_buffer;
1568 gss_buffer_t output_message_buffer;
1569 int *conf_state;
1570 int *qop_state;
1571 {
1572 gss_unseal_arg arg;
1573 gss_unseal_res res;
1574
1575 /* get the client handle to GSSD */
1576
1577 if ((clnt = getgssd_handle()) == NULL) {
1578 clnt_pcreateerror(server);
1579 return (GSS_S_FAILURE);
1580 }
1581
1582 /* copy the procedure arguments into the rpc arg parameter */
1583
1584
1585 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1586 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1587 arg.gssd_context_verifier = gssd_context_verifier;
1588
1589 arg.input_message_buffer.GSS_BUFFER_T_len =
1590 (uint_t)input_message_buffer->length;
1591
1592 arg.input_message_buffer.GSS_BUFFER_T_val =
1593 (char *)input_message_buffer->value;
1594
1595 /* call the remote procedure */
1596
1597 memset(&res, 0, sizeof (res));
1598 if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1599
1600 /*
1601 * if the RPC call times out, null out all return arguments,
1602 * set minor_status to its maximum value, and return GSS_S_FAILURE
1603 */
1604
1605 if (minor_status != NULL)
1606 *minor_status = DEFAULT_MINOR_STAT;
1607 if (output_message_buffer != NULL)
1608 output_message_buffer->length = 0;
1609 if (conf_state != NULL)
1610 *conf_state = 0;
1611 if (qop_state != NULL)
1612 *qop_state = 0;
1613
1614 return (GSS_S_FAILURE);
1615 }
1616
1617 /* copy the rpc results into the return arguments */
1618
1619 if (minor_status != NULL)
1620 *minor_status = res.minor_status;
1621
1622 if (output_message_buffer != NULL) {
1623 output_message_buffer->length =
1624 res.output_message_buffer.GSS_BUFFER_T_len;
1625
1626 output_message_buffer->value =
1627 (void *) MALLOC(output_message_buffer->length);
1628 memcpy(output_message_buffer->value,
1629 res.output_message_buffer.GSS_BUFFER_T_val,
1630 output_message_buffer->length);
1631 }
1632
1633 if (conf_state != NULL)
1634 *conf_state = res.conf_state;
1635
1636 if (qop_state != NULL)
1637 *qop_state = res.qop_state;
1638
1639 /*
1640 * free the memory allocated for the results and return with the status
1641 * received in the rpc call
1642 */
1643
1644 clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
1645 return (res.status);
1646 }
1647
1648 OM_uint32
1649 kgss_unseal(OM_uint32 *minor_status,
1650 gss_ctx_id_t context_handle,
1651 gss_buffer_t input_message_buffer,
1652 gss_buffer_t output_message_buffer,
1653 int *conf_state,
1654 int *qop_state)
1655 {
1656 if (context_handle == GSS_C_NO_CONTEXT)
1657 return (GSS_S_FAILURE);
1658
1659 return (KGSS_UNSEAL(minor_status, context_handle,
1660 input_message_buffer,
1661 output_message_buffer,
1662 conf_state, qop_state));
1663 }
1664
1665 /* EXPORT DELETE END */
1666
1667 OM_uint32
1668 kgss_display_status(minor_status,
1669 status_value,
1670 status_type,
1671 mech_type,
1672 message_context,
1673 status_string,
1674 uid)
1675 OM_uint32 *minor_status;
1676 OM_uint32 status_value;
1677 int status_type;
1678 gss_OID mech_type;
1679 int *message_context;
1680 gss_buffer_t status_string;
1681 uid_t uid;
1682 {
1683 gss_display_status_arg arg;
1684 gss_display_status_res res;
1685
1686 /* get the client handle to GSSD */
1687
1688 if ((clnt = getgssd_handle()) == NULL) {
1689 clnt_pcreateerror(server);
1690 return (GSS_S_FAILURE);
1691 }
1692
1693 /* copy the procedure arguments into the rpc arg parameter */
1694
1695 arg.uid = (OM_uint32) uid;
1696
1697 arg.status_value = status_value;
1698 arg.status_type = status_type;
1699
1700 arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
1701 mech_type->length : 0);
1702 arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
1703 mech_type->elements : 0);
1704
1705 arg.message_context = *message_context;
1706
1707 /* call the remote procedure */
1708
1709 if (message_context != NULL)
1710 *message_context = 0;
1711 if (status_string != NULL) {
1712 status_string->length = 0;
1713 status_string->value = NULL;
1714 }
1715
1716 memset(&res, 0, sizeof (res));
1717 if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
1718
1719 /*
1720 * if the RPC call times out, null out all return arguments,
1721 * set minor_status to its maximum value, and return GSS_S_FAILURE
1722 */
1723
1724 if (minor_status != NULL)
1725 *minor_status = DEFAULT_MINOR_STAT;
1726
1727 return (GSS_S_FAILURE);
1728 }
1729
1730 if (minor_status != NULL)
1731 *minor_status = res.minor_status;
1732
1733 /* now process the results and pass them back to the caller */
1734
1735 if (res.status == GSS_S_COMPLETE) {
1736 if (message_context != NULL)
1737 *message_context = res.message_context;
1738 if (status_string != NULL) {
1739 status_string->length =
1740 (size_t)res.status_string.GSS_BUFFER_T_len;
1741 status_string->value =
1742 (void *)MALLOC(status_string->length);
1743 memcpy(status_string->value,
1744 res.status_string.GSS_BUFFER_T_val,
1745 status_string->length);
1746 }
1747 }
1748
1749 clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
1750 return (res.status);
1751 }
1752
1753 /*ARGSUSED*/
1754 OM_uint32
1755 kgss_indicate_mechs(minor_status,
1756 mech_set,
1757 uid)
1758 OM_uint32 *minor_status;
1759 gss_OID_set *mech_set;
1760 uid_t uid;
1761 {
1762 void *arg;
1763 gss_indicate_mechs_res res;
1764 int i;
1765
1766 /* get the client handle to GSSD */
1767
1768 if ((clnt = getgssd_handle()) == NULL) {
1769 clnt_pcreateerror(server);
1770 return (GSS_S_FAILURE);
1771 }
1772
1773 memset(&res, 0, sizeof (res));
1774 if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
1775
1776 /*
1777 * if the RPC call times out, null out all return arguments,
1778 * set minor_status to its maximum value, and return GSS_S_FAILURE
1779 */
1780
1781 if (minor_status != NULL)
1782 *minor_status = DEFAULT_MINOR_STAT;
1783 if (mech_set != NULL)
1784 *mech_set = NULL;
1785
1786 return (GSS_S_FAILURE);
1787 }
1788
1789 /* copy the rpc results into the return arguments */
1790
1791 if (minor_status != NULL)
1792 *minor_status = res.minor_status;
1793
1794 if (mech_set != NULL) {
1795 *mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1796 (*mech_set)->count = res.mech_set.GSS_OID_SET_len;
1797 (*mech_set)->elements = (void *)
1798 MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
1799 for (i = 0; i < (*mech_set)->count; i++) {
1800 (*mech_set)->elements[i].length =
1801 res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
1802 (*mech_set)->elements[i].elements = (void *)
1803 MALLOC ((*mech_set)->elements[i].length);
1804 memcpy ((*mech_set)->elements[i].elements,
1805 res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
1806 (*mech_set)->elements[i].length);
1807 }
1808 }
1809
1810 /*
1811 * free the memory allocated for the results and return with the status
1812 * received in the rpc call
1813 */
1814
1815 clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
1816 return (res.status);
1817 }
1818
1819
1820 OM_uint32
1821 kgss_inquire_cred_wrapped(minor_status,
1822 cred_handle,
1823 gssd_cred_verifier,
1824 name,
1825 lifetime,
1826 cred_usage,
1827 mechanisms,
1828 uid)
1829 OM_uint32 *minor_status;
1830 gssd_cred_id_t cred_handle;
1831 OM_uint32 gssd_cred_verifier;
1832 gss_name_t *name;
1833 OM_uint32 *lifetime;
1834 int *cred_usage;
1835 gss_OID_set *mechanisms;
1836 uid_t uid;
1837 {
1838 OM_uint32 minor_status_temp;
1839 gss_buffer_desc external_name;
1840 gss_OID name_type;
1841 int i;
1842
1843 gss_inquire_cred_arg arg;
1844 gss_inquire_cred_res res;
1845
1846 /* get the client handle to GSSD */
1847
1848 if ((clnt = getgssd_handle()) == NULL) {
1849 clnt_pcreateerror(server);
1850 return (GSS_S_FAILURE);
1851 }
1852
1853
1854 /* copy the procedure arguments into the rpc arg parameter */
1855
1856 arg.uid = (OM_uint32) uid;
1857
1858 arg.cred_handle.GSS_CRED_ID_T_len =
1859 cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
1860 0 : (uint_t)sizeof (gssd_cred_id_t);
1861 arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
1862 arg.gssd_cred_verifier = gssd_cred_verifier;
1863
1864 /* call the remote procedure */
1865
1866 memset(&res, 0, sizeof (res));
1867 if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
1868
1869 /*
1870 * if the RPC call times out, null out all return arguments,
1871 * set minor_status to its maximum value, and return GSS_S_FAILURE
1872 */
1873
1874 if (minor_status != NULL)
1875 *minor_status = DEFAULT_MINOR_STAT;
1876 if (name != NULL)
1877 *name = NULL;
1878 if (lifetime != NULL)
1879 *lifetime = 0;
1880 if (cred_usage != NULL)
1881 *cred_usage = 0;
1882 if (mechanisms != NULL)
1883 *mechanisms = NULL;
1884
1885 return (GSS_S_FAILURE);
1886 }
1887
1888 /* copy the rpc results into the return arguments */
1889
1890 if (minor_status != NULL)
1891 *minor_status = res.minor_status;
1892
1893 /* convert name from external to internal format */
1894
1895 if (name != NULL) {
1896 external_name.length = res.name.GSS_BUFFER_T_len;
1897 external_name.value = res.name.GSS_BUFFER_T_val;
1898
1899 /*
1900 * we have to allocate a name_type descriptor and
1901 * elements storage, since gss_import_name() only
1902 * stores a pointer to the name_type info in the
1903 * union_name struct
1904 */
1905
1906 name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc));
1907
1908 name_type->length = res.name_type.GSS_OID_len;
1909 name_type->elements = (void *) MALLOC(name_type->length);
1910 memcpy(name_type->elements, res.name_type.GSS_OID_val,
1911 name_type->length);
1912
1913 if (gss_import_name(&minor_status_temp, &external_name,
1914 name_type, name) != GSS_S_COMPLETE) {
1915
1916 *minor_status = (OM_uint32) minor_status_temp;
1917 gss_release_buffer(&minor_status_temp, &external_name);
1918
1919 clnt_freeres(clnt, xdr_gss_inquire_cred_res,
1920 (caddr_t)&res);
1921 return ((OM_uint32) GSS_S_FAILURE);
1922 }
1923 }
1924
1925 if (lifetime != NULL)
1926 *lifetime = res.lifetime;
1927
1928 if (cred_usage != NULL)
1929 *cred_usage = res.cred_usage;
1930
1931 if (mechanisms != NULL) {
1932 *mechanisms =
1933 (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1934 if (res.mechanisms.GSS_OID_SET_len != 0) {
1935 (*mechanisms)->count =
1936 (int)res.mechanisms.GSS_OID_SET_len;
1937 (*mechanisms)->elements = (gss_OID)
1938 MALLOC(sizeof (gss_OID) * (*mechanisms)->count);
1939
1940 for (i = 0; i < (*mechanisms)->count; i++) {
1941 (*mechanisms)->elements[i].length = (OM_uint32)
1942 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
1943 (*mechanisms)->elements[i].elements = (void *)
1944 MALLOC((*mechanisms)->elements[i].length);
1945 memcpy((*mechanisms)->elements[i].elements,
1946 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
1947 (*mechanisms)->elements[i].length);
1948 }
1949 } else
1950 (*mechanisms)->count = 0;
1951 }
1952
1953 /*
1954 * free the memory allocated for the results and return with the status
1955 * received in the rpc call
1956 */
1957
1958 clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
1959 return (res.status);
1960 }
1961
1962
1963 OM_uint32
1964 kgss_inquire_cred(minor_status,
1965 cred_handle,
1966 name,
1967 lifetime,
1968 cred_usage,
1969 mechanisms,
1970 uid)
1971 OM_uint32 *minor_status;
1972 gss_cred_id_t cred_handle;
1973 gss_name_t *name;
1974 OM_uint32 *lifetime;
1975 int *cred_usage;
1976 gss_OID_set * mechanisms;
1977 uid_t uid;
1978 {
1979
1980 OM_uint32 gssd_cred_verifier;
1981 gssd_cred_id_t gssd_cred_handle;
1982
1983 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
1984 gssd_cred_handle = KCRED_TO_CRED(cred_handle);
1985
1986 return (kgss_inquire_cred_wrapped(minor_status,
1987 gssd_cred_handle, gssd_cred_verifier,
1988 name, lifetime, cred_usage, mechanisms, uid));
1989 }
1990
1991
1992 OM_uint32
1993 kgss_inquire_cred_by_mech_wrapped(minor_status,
1994 cred_handle,
1995 gssd_cred_verifier,
1996 mech_type,
1997 uid)
1998 OM_uint32 *minor_status;
1999 gssd_cred_id_t cred_handle;
2000 OM_uint32 gssd_cred_verifier;
2001 gss_OID mech_type;
2002 uid_t uid;
2003 {
2004 OM_uint32 minor_status_temp;
2005
2006 gss_inquire_cred_by_mech_arg arg;
2007 gss_inquire_cred_by_mech_res res;
2008
2009 /* get the client handle to GSSD */
2010
2011 if ((clnt = getgssd_handle()) == NULL) {
2012 clnt_pcreateerror(server);
2013 return (GSS_S_FAILURE);
2014 }
2015
2016
2017 /* copy the procedure arguments into the rpc arg parameter */
2018
2019 arg.uid = (OM_uint32) uid;
2020
2021 arg.cred_handle.GSS_CRED_ID_T_len =
2022 cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
2023 0 : (uint_t)sizeof (gssd_cred_id_t);
2024 arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
2025 arg.gssd_cred_verifier = gssd_cred_verifier;
2026
2027 arg.mech_type.GSS_OID_len =
2028 (uint_t)(mech_type != GSS_C_NULL_OID ?
2029 mech_type->length : 0);
2030 arg.mech_type.GSS_OID_val =
2031 (char *)(mech_type != GSS_C_NULL_OID ?
2032 mech_type->elements : 0);
2033 /* call the remote procedure */
2034
2035 memset(&res, 0, sizeof (res));
2036 if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
2037
2038 /*
2039 * if the RPC call times out, null out all return arguments,
2040 * set minor_status to its maximum value, and return GSS_S_FAILURE
2041 */
2042
2043 if (minor_status != NULL)
2044 *minor_status = DEFAULT_MINOR_STAT;
2045 return (GSS_S_FAILURE);
2046 }
2047
2048 /* copy the rpc results into the return arguments */
2049
2050 if (minor_status != NULL)
2051 *minor_status = res.minor_status;
2052
2053 /* convert name from external to internal format */
2054
2055 /*
2056 * free the memory allocated for the results and return with the status
2057 * received in the rpc call
2058 */
2059
2060 clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
2061 return (res.status);
2062 }
2063
2064
2065 OM_uint32
2066 kgss_inquire_cred_by_mech(minor_status,
2067 cred_handle,
2068 mech_type,
2069 uid)
2070 OM_uint32 *minor_status;
2071 gss_cred_id_t cred_handle;
2072 gss_OID mech_type;
2073 uid_t uid;
2074 {
2075
2076 OM_uint32 gssd_cred_verifier;
2077 gssd_cred_id_t gssd_cred_handle;
2078
2079 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
2080 gssd_cred_handle = KCRED_TO_CRED(cred_handle);
2081
2082 return (kgss_inquire_cred_by_mech_wrapped(minor_status,
2083 gssd_cred_handle, gssd_cred_verifier,
2084 mech_type, uid));
2085 }
2086
2087 OM_uint32
2088 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
2089 const gss_buffer_t expName;
2090 uid_t *uidOut;
2091 gid_t *gidOut;
2092 gid_t *gids[];
2093 int *gidsLen;
2094 uid_t uid;
2095 {
2096 gsscred_expname_to_unix_cred_arg args;
2097 gsscred_expname_to_unix_cred_res res;
2098
2099 /* check input/output parameters */
2100 if (expName == NULL || expName->value == NULL)
2101 return (GSS_S_CALL_INACCESSIBLE_READ);
2102
2103 if (uidOut == NULL)
2104 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2105
2106 /* NULL out output parameters */
2107 *uidOut = 0;
2108 if (gidsLen)
2109 *gidsLen = 0;
2110
2111 if (gids)
2112 *gids = NULL;
2113
2114 /* get the client handle to gssd */
2115 if ((clnt = getgssd_handle()) == NULL)
2116 {
2117 clnt_pcreateerror(server);
2118 return (GSS_S_FAILURE);
2119 }
2120
2121 /* copy the procedure arguments */
2122 args.uid = uid;
2123 args.expname.GSS_BUFFER_T_val = expName->value;
2124 args.expname.GSS_BUFFER_T_len = expName->length;
2125
2126 /* null out the return buffer and call the remote proc */
2127 memset(&res, 0, sizeof (res));
2128
2129 if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2130 {
2131 return (GSS_S_FAILURE);
2132 }
2133
2134 /* copy the results into the result parameters */
2135 if (res.major == GSS_S_COMPLETE)
2136 {
2137 *uidOut = res.uid;
2138 if (gidOut)
2139 *gidOut = res.gid;
2140 if (gids && gidsLen)
2141 {
2142 *gids = res.gids.GSSCRED_GIDS_val;
2143 *gidsLen = res.gids.GSSCRED_GIDS_len;
2144 res.gids.GSSCRED_GIDS_val = NULL;
2145 res.gids.GSSCRED_GIDS_len = 0;
2146 }
2147 }
2148
2149 /* free RPC results */
2150 clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
2151
2152 return (res.major);
2153 } /* kgsscred_expname_to_unix_cred */
2154
2155 OM_uint32
2156 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
2157 gidsLen, uid)
2158 const gss_name_t intName;
2159 const gss_OID mechType;
2160 uid_t *uidOut;
2161 gid_t *gidOut;
2162 gid_t *gids[];
2163 int *gidsLen;
2164 uid_t uid;
2165 {
2166 gsscred_name_to_unix_cred_arg args;
2167 gsscred_name_to_unix_cred_res res;
2168 OM_uint32 major, minor;
2169 gss_OID nameOid;
2170 gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
2171
2172
2173 /* check the input/output parameters */
2174 if (intName == NULL || mechType == NULL)
2175 return (GSS_S_CALL_INACCESSIBLE_READ);
2176
2177 if (uidOut == NULL)
2178 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2179
2180 /* NULL out the output parameters */
2181 *uidOut = 0;
2182 if (gids)
2183 *gids = NULL;
2184
2185 if (gidsLen)
2186 *gidsLen = 0;
2187
2188 /* get the client handle to gssd */
2189 if ((clnt = getgssd_handle()) == NULL)
2190 {
2191 clnt_pcreateerror(server);
2192 return (GSS_S_FAILURE);
2193 }
2194
2195 /* convert the name to flat representation */
2196 if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
2197 != GSS_S_COMPLETE)
2198 {
2199 return (major);
2200 }
2201
2202 /* set the rpc parameters */
2203 args.uid = uid;
2204 args.pname.GSS_BUFFER_T_len = flatName.length;
2205 args.pname.GSS_BUFFER_T_val = flatName.value;
2206 args.name_type.GSS_OID_len = nameOid->length;
2207 args.name_type.GSS_OID_val = nameOid->elements;
2208 args.mech_type.GSS_OID_len = mechType->length;
2209 args.mech_type.GSS_OID_val = mechType->elements;
2210
2211 /* call the remote procedure */
2212 memset(&res, 0, sizeof (res));
2213 if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2214 {
2215 gss_release_buffer(&minor, &flatName);
2216 return (GSS_S_FAILURE);
2217 }
2218
2219 gss_release_buffer(&minor, &flatName);
2220 /* copy the output parameters on output */
2221 if (res.major == GSS_S_COMPLETE)
2222 {
2223 *uidOut = res.uid;
2224 if (gidOut)
2225 *gidOut = res.gid;
2226 if (gids && gidsLen)
2227 {
2228 *gids = res.gids.GSSCRED_GIDS_val;
2229 *gidsLen = res.gids.GSSCRED_GIDS_len;
2230 res.gids.GSSCRED_GIDS_val = NULL;
2231 res.gids.GSSCRED_GIDS_len = 0;
2232 }
2233 }
2234
2235 /* delete RPC allocated memory */
2236 clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
2237
2238 return (res.major);
2239 } /* kgsscred_name_to_unix_cred */
2240
2241 OM_uint32
2242 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
2243 const uid_t puid;
2244 gid_t *gidOut;
2245 gid_t *gids[];
2246 int *gidsLen;
2247 uid_t uid;
2248 {
2249 gss_get_group_info_arg args;
2250 gss_get_group_info_res res;
2251
2252
2253 /* check the output parameters */
2254 if (gidOut == NULL || gids == NULL || gidsLen == NULL)
2255 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2256
2257 /* get the client GSSD handle */
2258 if ((clnt = getgssd_handle()) == NULL)
2259 {
2260 clnt_pcreateerror(server);
2261 return (GSS_S_FAILURE);
2262 }
2263
2264 /* set the input parameters */
2265 args.uid = uid;
2266 args.puid = puid;
2267
2268
2269 /* call the remote procedure */
2270 memset(&res, 0, sizeof (res));
2271 if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS)
2272 {
2273 return (GSS_S_FAILURE);
2274 }
2275
2276 /* copy the results */
2277 if (res.major == GSS_S_COMPLETE)
2278 {
2279 *gidOut = res.gid;
2280 *gids = res.gids.GSSCRED_GIDS_val;
2281 *gidsLen = res.gids.GSSCRED_GIDS_len;
2282 res.gids.GSSCRED_GIDS_val = NULL;
2283 res.gids.GSSCRED_GIDS_len = 0;
2284 }
2285
2286 /* nothing to free */
2287
2288 return (res.major);
2289 } /* kgss_get_group_info */
2290
2291 OM_uint32
2292 kgss_export_sec_context_wrapped(minor_status,
2293 context_handle,
2294 output_token,
2295 gssd_context_verifier)
2296 OM_uint32 *minor_status;
2297 gssd_ctx_id_t *context_handle;
2298 gss_buffer_t output_token;
2299 OM_uint32 gssd_context_verifier;
2300 {
2301 CLIENT *clnt;
2302 gss_export_sec_context_arg arg;
2303 gss_export_sec_context_res res;
2304
2305
2306 /* get the client handle to GSSD */
2307
2308 if ((clnt = getgssd_handle()) == NULL) {
2309 clnt_pcreateerror(server);
2310 return (GSS_S_FAILURE);
2311 }
2312
2313 /* copy the procedure arguments into the rpc arg parameter */
2314
2315 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
2316 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
2317 arg.gssd_context_verifier = gssd_context_verifier;
2318
2319 /* call the remote procedure */
2320
2321 memset(&res, 0, sizeof (res));
2322 if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2323
2324 /*
2325 * if the RPC call times out, null out all return arguments, set minor_status
2326 * to its maximum value, and return GSS_S_FAILURE
2327 */
2328
2329 if (minor_status != NULL)
2330 *minor_status = DEFAULT_MINOR_STAT;
2331 if (context_handle != NULL)
2332 *context_handle = NULL;
2333 if (output_token != NULL)
2334 output_token->length = 0;
2335
2336 return (GSS_S_FAILURE);
2337 }
2338
2339 /* copy the rpc results into the return arguments */
2340
2341 if (minor_status != NULL)
2342 *minor_status = res.minor_status;
2343
2344 if (res.context_handle.GSS_CTX_ID_T_len == 0)
2345 *context_handle = NULL;
2346 else
2347 *context_handle =
2348 *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2349
2350 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
2351 output_token->length = res.output_token.GSS_BUFFER_T_len;
2352 output_token->value =
2353 (void *) MALLOC(output_token->length);
2354 memcpy(output_token->value,
2355 res.output_token.GSS_BUFFER_T_val,
2356 output_token->length);
2357 }
2358
2359 /*
2360 * free the memory allocated for the results and return with the status
2361 * received in the rpc call
2362 */
2363
2364 clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
2365 return (res.status);
2366
2367 }
2368
2369 OM_uint32
2370 kgss_export_sec_context(minor_status,
2371 context_handle,
2372 output_token)
2373 OM_uint32 *minor_status;
2374 gss_ctx_id_t *context_handle;
2375 gss_buffer_t output_token;
2376 {
2377 OM_uint32 err;
2378 struct kgss_ctx *kctx;
2379
2380 if (*context_handle == GSS_C_NO_CONTEXT) {
2381 return (GSS_S_NO_CONTEXT);
2382 } else
2383 kctx = KCTX_TO_KGSS_CTX(*context_handle);
2384
2385 err = kgss_export_sec_context_wrapped(minor_status,
2386 &kctx->gssd_ctx, output_token,
2387 kctx->gssd_ctx_verifier);
2388
2389 if (GSS_ERROR(err))
2390 return (err);
2391 else {
2392 KGSS_FREE(kctx);
2393 *context_handle = GSS_C_NO_CONTEXT;
2394 return (err);
2395 }
2396
2397 }
2398
2399 OM_uint32
2400 kgss_import_sec_context_wrapped(minor_status,
2401 input_token,
2402 context_handle,
2403 gssd_context_verifier)
2404 OM_uint32 *minor_status;
2405 gss_buffer_t input_token;
2406 gss_ctx_id_t *context_handle;
2407 OM_uint32 gssd_context_verifier;
2408 {
2409 CLIENT *clnt;
2410 gss_import_sec_context_arg arg;
2411 gss_import_sec_context_res res;
2412
2413
2414 /* get the client handle to GSSD */
2415
2416 if ((clnt = getgssd_handle()) == NULL) {
2417 clnt_pcreateerror(server);
2418 return (GSS_S_FAILURE);
2419 }
2420
2421 /* copy the procedure arguments into the rpc arg parameter */
2422 arg.input_token.GSS_BUFFER_T_len = (uint_t)
2423 (input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
2424 arg.input_token.GSS_BUFFER_T_val = (char *)
2425 (input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
2426 arg.gssd_context_verifier = gssd_context_verifier;
2427
2428
2429 /* call the remote procedure */
2430
2431 memset(&res, 0, sizeof (res));
2432 if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2433
2434 /*
2435 * if the RPC call times out, null out all return arguments, set minor_status
2436 * to its maximum value, and return GSS_S_FAILURE
2437 */
2438
2439 if (minor_status != NULL)
2440 *minor_status = DEFAULT_MINOR_STAT;
2441 if (context_handle != NULL)
2442 *context_handle = NULL;
2443
2444 return (GSS_S_FAILURE);
2445 }
2446
2447 /* copy the rpc results into the return arguments */
2448
2449 if (minor_status != NULL)
2450 *minor_status = res.minor_status;
2451
2452 if (res.context_handle.GSS_CTX_ID_T_len == 0)
2453 *context_handle = NULL;
2454 else
2455 *context_handle =
2456 *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2457
2458
2459 /*
2460 * free the memory allocated for the results and return with the status
2461 * received in the rpc call
2462 */
2463
2464 clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res);
2465 return (res.status);
2466 }
2467
2468 OM_uint32
2469 kgss_import_sec_context(minor_status,
2470 input_token,
2471 context_handle)
2472 OM_uint32 *minor_status;
2473 gss_buffer_t input_token;
2474 gss_ctx_id_t *context_handle;
2475 {
2476 struct kgss_ctx *kctx;
2477
2478 if (*context_handle == GSS_C_NO_CONTEXT) {
2479 kctx = KGSS_ALLOC();
2480 *context_handle = (gss_ctx_id_t)kctx;
2481 kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
2482 } else
2483 kctx = (struct kgss_ctx *)*context_handle;
2484 return (kgss_import_sec_context_wrapped(minor_status,
2485 input_token, &kctx->gssd_ctx,
2486 KCTX_TO_CTXV(context_handle)));
2487 }
2488
2489 #ifdef _KERNEL
2490 #include <sys/modctl.h>
2491
2492 static void *gss_clnt = NULL;
2493
2494 #ifdef DEBUG
2495 typedef struct {
2496 char *name; /* just put something here */
2497 } gssd_devstate_t;
2498
2499
2500 static void *gssd_state;
2501
2502 static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2503 {
2504 /* cmn_err(CE_NOTE, "In gssd_attach"); */
2505 switch (cmd) {
2506 case DDI_ATTACH:
2507 if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0)
2508 == DDI_FAILURE) {
2509 ddi_remove_minor_node(dip, NULL);
2510 return (DDI_FAILURE);
2511 }
2512 return (DDI_SUCCESS);
2513
2514 default:
2515 return (DDI_FAILURE);
2516 }
2517 }
2518
2519 static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
2520 void *arg, void **result)
2521 {
2522 dev_t dev;
2523 int error;
2524
2525 /* cmn_err(CE_NOTE, "In gssd_getinfo"); */
2526
2527 switch (infocmd) {
2528 case DDI_INFO_DEVT2INSTANCE:
2529 dev = (dev_t)arg;
2530 *result = (void *) getminor(dev);
2531 error = DDI_SUCCESS;
2532 break;
2533
2534 case DDI_INFO_DEVT2DEVINFO:
2535 /* cmn_err(CE_NOTE, "getinfo wants devinfo"); */
2536 default:
2537 error = DDI_FAILURE;
2538 break;
2539 }
2540 return (error);
2541 }
2542
2543 static int gssd_identify(dev_info_t *dip)
2544 {
2545 /* cmn_err(CE_NOTE, "in gssd_identify"); */
2546 if (strcmp(ddi_get_name(dip), "gssd") == 0)
2547 return (DDI_IDENTIFIED);
2548 else
2549 return (DDI_NOT_IDENTIFIED);
2550 }
2551
2552 static int gssd_probe(dev_info_t *dip)
2553 {
2554 /* cmn_err(CE_NOTE, "In gssd_probe"); */
2555
2556 return (DDI_PROBE_SUCCESS);
2557 }
2558
2559 static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
2560 {
2561 /* cmn_err (CE_NOTE, "In gssd_open"); */
2562 if (otyp != OTYP_CHR)
2563 return (EINVAL);
2564
2565 gss_clnt = getgssd_handle();
2566 return (0);
2567 }
2568
2569 static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp)
2570 {
2571 /* cmn_err(CE_NOTE, "In gssd_close"); */
2572 killgssd_handle(gss_clnt);
2573 return (0);
2574 }
2575
2576 static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp)
2577 {
2578 char buffer[1024];
2579 int len;
2580
2581 /* cmn_err(CE_NOTE, "In gssd_write"); */
2582 bzero(buffer, 1024);
2583
2584 uiomove(buffer, 1024, UIO_WRITE, uiop);
2585 len = strlen(buffer);
2586
2587 if (buffer[len-1] == '\n')
2588 buffer[--len] = '\0';
2589
2590 cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer);
2591 do_gssdtest(buffer);
2592 return (0);
2593 }
2594
2595 static struct cb_ops gssd_cb_ops = {
2596 gssd_open, /* cb_open */
2597 gssd_close, /* cb_close */
2598 nodev, /* cb_strategy */
2599 nodev, /* cb_print */
2600 nodev, /* cb_dump */
2601 nulldev, /* cb_read */
2602 gssd_write, /* cb_write */
2603 nodev, /* cb_ioctl */
2604 nodev, /* cb_devmap */
2605 nodev, /* cb_mmap */
2606 nodev, /* cb_segmap */
2607 nochpoll, /* cb_chpoll */
2608 ddi_prop_op, /* cb_prop_op */
2609 NULL, /* cb_stream */
2610 (int)(D_NEW|D_MP) /* cb_flag */
2611 };
2612
2613 static struct dev_ops gssd_ops = {
2614 DEVO_REV, /* devo_rev */
2615 0, /* devo_refcnt */
2616 gssd_getinfo, /* devo_getinfo */
2617 gssd_identify, /* devo_identify */
2618 nulldev, /* devo_probe */
2619 gssd_attach, /* devo_attach */
2620 nulldev, /* devo_detach */
2621 nodev, /* devo_reset */
2622 &gssd_cb_ops, /* devo_cb_ops */
2623 (struct bus_ops *)NULL /* devo_bus_ops */
2624 };
2625
2626 extern struct mod_ops mod_driverops;
2627
2628 static struct modldrv modlmisc = {
2629 &mod_driverops,
2630 "GSSD DRV Client Module",
2631 &gssd_ops
2632
2633 #else /* !DEBUG */
2634
2635 static struct modlmisc modlmisc = {
2636 &mod_miscops,
2637 "GSSD Client Module"
2638 #endif /* DEBUG */
2639 };
2640
2641 static struct modlinkage modlinkage = {
2642 MODREV_1,
2643 (void *)&modlmisc,
2644 NULL
2645 };
2646
2647 char _depends_on[] = "strmod/rpcmod misc/tlimod";
2648
2649 _init(void)
2650 {
2651 int status;
2652
2653 if ((status = ddi_soft_state_init(&gssd_state,
2654 sizeof (gssd_devstate_t), 1)) != 0)
2655 return (status);
2656
2657 if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0)
2658 ddi_soft_state_fini(&gssd_state);
2659
2660 cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status);
2661 return (status);
2662 }
2663
2664 _fini()
2665 {
2666 int status;
2667
2668 killgssd_handle(gss_clnt);
2669 cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module.");
2670
2671 if ((status = mod_remove(&modlinkage)) != 0)
2672 return (status);
2673
2674 ddi_soft_state_fini(&gssd_state);
2675 return (status);
2676 }
2677
2678 _info(modinfop)
2679 struct modinfo *modinfop;
2680 {
2681 return (mod_info(&modlinkage, modinfop));
2682 }
2683
2684 #endif