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