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