4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2017 Joyent Inc
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
27 * RPC server procedures for the gssapi usermode daemon gssd.
31 #include <stdio_ext.h>
37 #include <sys/param.h>
38 #include <mechglueP.h>
40 #include <gssapi/gssapi.h>
44 #include <sys/resource.h>
45 #include <sys/debug.h>
48 #define FDCACHE_PERCENTAGE .75 /* Percentage of total FD limit */
49 #define FDCACHE_DEFAULT 16 /* Default LRU cache size */
50 #define GSSD_FD_LIMIT 255 /* Increase number of fds allowed */
52 extern int gssd_debug
; /* declared in gssd.c */
53 static OM_uint32 gssd_time_verf
; /* verifies same gssd */
54 static OM_uint32 context_verf
; /* context sequence numbers */
56 struct gssd_ctx_slot
{
57 struct gssd_ctx_slot
*lru_next
;
58 struct gssd_ctx_slot
*lru_prev
;
60 OM_uint32 create_time
;
66 struct gssd_ctx_slot
*gssd_ctx_slot_tbl
;
67 struct gssd_ctx_slot
*gssd_lru_head
;
69 static int max_contexts
;
71 static int checkfrom(struct svc_req
*, uid_t
*);
72 extern void set_gssd_uid(uid_t
);
73 extern int __rpc_get_local_uid(SVCXPRT
*, uid_t
*);
76 * Syslog (and output to stderr if debug set) the GSSAPI major
80 syslog_gss_error(OM_uint32 maj_stat
, OM_uint32 min_stat
, char *errstr
)
82 OM_uint32 gmaj_stat
, gmin_stat
;
84 OM_uint32 msg_ctx
= 0;
89 "gssd: syslog_gss_err: called from %s: maj=%d min=%d\n",
90 errstr
? errstr
: "<null>", maj_stat
, min_stat
);
92 /* Print the major status error from the mech. */
93 /* msg_ctx - skip the check for it as is probably unnecesary */
94 gmaj_stat
= gss_display_status(&gmin_stat
, maj_stat
,
96 GSS_C_NULL_OID
, &msg_ctx
, &msg
);
97 if ((gmaj_stat
== GSS_S_COMPLETE
)||
98 (gmaj_stat
== GSS_S_CONTINUE_NEEDED
)) {
99 syslog(LOG_DAEMON
|LOG_NOTICE
,
100 "GSSAPI error major: %s", (char *)msg
.value
);
102 (void) fprintf(stderr
,
103 "gssd: GSSAPI error major: %s\n",
106 (void) gss_release_buffer(&gmin_stat
, &msg
);
109 /* Print the minor status error from the mech. */
111 /* msg_ctx - skip the check for it as is probably unnecesary */
112 gmaj_stat
= gss_display_status(&gmin_stat
, min_stat
,
116 if ((gmaj_stat
== GSS_S_COMPLETE
)||
117 (gmaj_stat
== GSS_S_CONTINUE_NEEDED
)) {
118 syslog(LOG_DAEMON
|LOG_NOTICE
,
119 "GSSAPI error minor: %s",
122 (void) fprintf(stderr
,
123 "gssd: GSSAPI error minor: %s\n",
125 (void) gss_release_buffer(&gmin_stat
, &msg
);
130 gssd_setup(char *arg
)
134 hrtime_t high_res_time
;
136 gssd_time_verf
= (OM_uint32
)time(NULL
);
137 max_contexts
= FDCACHE_DEFAULT
;
140 * Use low order bits of high resolution time to get a reasonably
141 * random number to start the context sequencing. This alternative
142 * to using a time value avoid clock resets via NTP or ntpdate.
144 high_res_time
= gethrtime();
145 context_verf
= (OM_uint32
)high_res_time
;
148 * Increase resource limit of FDs in case we get alot accept/init_
149 * sec_context calls before we're able to export them. This can
150 * happen in very heavily load environments where gssd doesn't get
151 * much time to work on its backlog.
153 if ((getrlimit(RLIMIT_NOFILE
, &rl
)) == 0) {
154 rl
.rlim_cur
= (rl
.rlim_max
>= GSSD_FD_LIMIT
) ?
155 GSSD_FD_LIMIT
: rl
.rlim_max
;
156 if ((setrlimit(RLIMIT_NOFILE
, &rl
)) == 0)
157 max_contexts
= rl
.rlim_cur
* FDCACHE_PERCENTAGE
;
158 (void) enable_extended_FILE_stdio(-1, -1);
161 gssd_ctx_slot_tbl
= (struct gssd_ctx_slot
*)
162 malloc(sizeof (struct gssd_ctx_slot
) * max_contexts
);
164 if (gssd_ctx_slot_tbl
== NULL
) {
165 (void) fprintf(stderr
,
166 gettext("[%s] could not allocate %d byte context table"
168 (sizeof (struct gssd_ctx_slot
) * max_contexts
));
172 for (i
= 1; i
< max_contexts
; i
++) {
173 gssd_ctx_slot_tbl
[i
-1].lru_next
= &gssd_ctx_slot_tbl
[i
];
174 gssd_ctx_slot_tbl
[i
].lru_prev
= &gssd_ctx_slot_tbl
[i
-1];
175 gssd_ctx_slot_tbl
[i
].inuse
= FALSE
;
176 gssd_ctx_slot_tbl
[i
].verf
= 0;
177 gssd_ctx_slot_tbl
[i
].create_time
= 0;
178 gssd_ctx_slot_tbl
[i
].rpcctx
= (gss_ctx_id_t
)(i
+ 1);
181 gssd_ctx_slot_tbl
[max_contexts
- 1].lru_next
= &gssd_ctx_slot_tbl
[0];
182 gssd_ctx_slot_tbl
[0].lru_prev
= &gssd_ctx_slot_tbl
[max_contexts
- 1];
183 gssd_ctx_slot_tbl
[0].inuse
= FALSE
;
184 gssd_ctx_slot_tbl
[0].verf
= 0;
185 gssd_ctx_slot_tbl
[0].create_time
= 0;
186 gssd_ctx_slot_tbl
[0].rpcctx
= (gss_ctx_id_t
)1;
188 gssd_lru_head
= &gssd_ctx_slot_tbl
[0];
191 static OM_uint32 syslog_interval
= 60;
193 static struct gssd_ctx_slot
*
194 gssd_alloc_slot(gss_ctx_id_t ctx
)
196 struct gssd_ctx_slot
*lru
;
197 OM_uint32 current_time
;
198 static OM_uint32 last_syslog
= 0;
199 static bool_t first_take
= TRUE
;
201 OM_uint32 minor_status
;
204 gssd_lru_head
= lru
->lru_next
;
206 current_time
= (OM_uint32
) time(NULL
);
208 if (last_syslog
== 0)
209 last_syslog
= current_time
; /* Save 1st alloc time */
212 if (lru
->ctx
!= GSS_C_NO_CONTEXT
)
213 (void) gss_delete_sec_context(&minor_status
,
217 if (((current_time
- last_syslog
) > syslog_interval
) ||
219 syslog(LOG_WARNING
, gettext("re-used an existing "
220 "context slot of age %u seconds (%d slots re-"
221 "used during last %u seconds)"),
222 current_time
- lru
->create_time
, tooks
,
223 current_time
- last_syslog
);
225 last_syslog
= current_time
;
232 * Assign the next context verifier to the context (avoiding zero).
235 if (context_verf
== 0)
237 lru
->verf
= context_verf
;
239 lru
->create_time
= current_time
;
246 * We always add 1 because we don't want slot 0 to be confused
247 * with GSS_C_NO_CONTEXT.
250 static struct gssd_ctx_slot
*
251 gssd_handle_to_slot(GSS_CTX_ID_T
*h
)
255 if (h
->GSS_CTX_ID_T_len
== 0) {
258 if (h
->GSS_CTX_ID_T_len
!= sizeof (i
))
261 i
= (*(intptr_t *)(h
->GSS_CTX_ID_T_val
)) - 1;
263 if (i
< 0 || i
>= max_contexts
)
266 return (&gssd_ctx_slot_tbl
[i
]);
270 gssd_rel_slot(struct gssd_ctx_slot
*lru
)
272 struct gssd_ctx_slot
*prev
, *next
;
280 * Remove entry from its current location in list
282 prev
= lru
->lru_prev
;
283 next
= lru
->lru_next
;
284 prev
->lru_next
= next
;
285 next
->lru_prev
= prev
;
288 * Since it is no longer in use, it is the least recently
291 prev
= gssd_lru_head
->lru_prev
;
292 next
= gssd_lru_head
;
294 prev
->lru_next
= lru
;
295 lru
->lru_prev
= prev
;
297 next
->lru_prev
= lru
;
298 lru
->lru_next
= next
;
304 gssd_convert_context_handle(GSS_CTX_ID_T
*h
,
305 gss_ctx_id_t
*context_handle
,
307 bool_t
*context_verf_ok
,
308 struct gssd_ctx_slot
**slotp
)
310 struct gssd_ctx_slot
*slot
;
312 *context_verf_ok
= FALSE
;
313 *context_handle
= (gss_ctx_id_t
)1;
317 if (h
->GSS_CTX_ID_T_len
== 0) {
318 *context_handle
= GSS_C_NO_CONTEXT
;
319 *context_verf_ok
= TRUE
;
323 slot
= gssd_handle_to_slot(h
);
328 if (verf
!= slot
->verf
)
331 *context_verf_ok
= TRUE
;
332 *context_handle
= slot
->ctx
;
338 gss_acquire_cred_1_svc(argp
, res
, rqstp
)
339 gss_acquire_cred_arg
*argp
;
340 gss_acquire_cred_res
*res
;
341 struct svc_req
*rqstp
;
343 OM_uint32 minor_status
;
344 gss_name_t desired_name
;
345 gss_OID_desc name_type_desc
;
346 gss_OID name_type
= &name_type_desc
;
348 gss_OID_set_desc desired_mechs_desc
;
349 gss_OID_set desired_mechs
;
351 gss_cred_id_t output_cred_handle
;
352 gss_OID_set actual_mechs
;
353 gss_buffer_desc external_name
;
358 fprintf(stderr
, gettext("gss_acquire_cred\n"));
360 memset(res
, 0, sizeof (*res
));
363 * if the request isn't from root, null out the result pointer
364 * entries, so the next time through xdr_free won't try to
365 * free unmalloc'd memory and then return NULL
368 if (checkfrom(rqstp
, &uid
) == 0) {
369 res
->output_cred_handle
.GSS_CRED_ID_T_val
= NULL
;
370 res
->actual_mechs
.GSS_OID_SET_val
= NULL
;
374 /* set the uid sent as the RPC argument */
379 /* convert the desired name from external to internal format */
381 external_name
.length
= argp
->desired_name
.GSS_BUFFER_T_len
;
382 external_name
.value
= (void *)malloc(external_name
.length
);
383 if (!external_name
.value
)
384 return (GSS_S_FAILURE
);
385 memcpy(external_name
.value
, argp
->desired_name
.GSS_BUFFER_T_val
,
386 external_name
.length
);
388 if (argp
->name_type
.GSS_OID_len
== 0) {
389 name_type
= GSS_C_NULL_OID
;
391 name_type
->length
= argp
->name_type
.GSS_OID_len
;
392 name_type
->elements
= (void *)malloc(name_type
->length
);
393 if (!name_type
->elements
) {
394 free(external_name
.value
);
395 return (GSS_S_FAILURE
);
397 memcpy(name_type
->elements
, argp
->name_type
.GSS_OID_val
,
401 if (gss_import_name(&minor_status
, &external_name
, name_type
,
402 &desired_name
) != GSS_S_COMPLETE
) {
404 res
->status
= (OM_uint32
) GSS_S_FAILURE
;
405 res
->minor_status
= minor_status
;
407 free(external_name
.value
);
408 if (name_type
!= GSS_C_NULL_OID
)
409 free(name_type
->elements
);
415 * copy the XDR structured arguments into their corresponding local GSSAPI
419 cred_usage
= argp
->cred_usage
;
420 time_req
= argp
->time_req
;
422 if (argp
->desired_mechs
.GSS_OID_SET_len
!= 0) {
423 desired_mechs
= &desired_mechs_desc
;
424 desired_mechs
->count
=
425 (int)argp
->desired_mechs
.GSS_OID_SET_len
;
426 desired_mechs
->elements
= (gss_OID
)
427 malloc(sizeof (gss_OID_desc
) * desired_mechs
->count
);
428 if (!desired_mechs
->elements
) {
429 free(external_name
.value
);
430 free(name_type
->elements
);
431 return (GSS_S_FAILURE
);
433 for (i
= 0; i
< desired_mechs
->count
; i
++) {
434 desired_mechs
->elements
[i
].length
=
435 (OM_uint32
)argp
->desired_mechs
.
436 GSS_OID_SET_val
[i
].GSS_OID_len
;
437 desired_mechs
->elements
[i
].elements
=
438 (void *)malloc(desired_mechs
->elements
[i
].
440 if (!desired_mechs
->elements
[i
].elements
) {
441 free(external_name
.value
);
442 free(name_type
->elements
);
443 for (j
= 0; j
< (i
-1); j
++) {
445 (desired_mechs
->elements
[j
].elements
);
447 free(desired_mechs
->elements
);
448 return (GSS_S_FAILURE
);
450 memcpy(desired_mechs
->elements
[i
].elements
,
451 argp
->desired_mechs
.GSS_OID_SET_val
[i
].
453 desired_mechs
->elements
[i
].length
);
456 desired_mechs
= GSS_C_NULL_OID_SET
;
458 /* call the gssapi routine */
460 res
->status
= (OM_uint32
)gss_acquire_cred(&res
->minor_status
,
470 * convert the output args from the parameter given in the call to the
471 * variable in the XDR result
474 res
->output_cred_handle
.GSS_CRED_ID_T_len
= sizeof (gss_cred_id_t
);
475 res
->output_cred_handle
.GSS_CRED_ID_T_val
=
476 (void *)malloc(sizeof (gss_cred_id_t
));
477 if (!res
->output_cred_handle
.GSS_CRED_ID_T_val
) {
478 free(external_name
.value
);
479 free(name_type
->elements
);
480 for (i
= 0; i
< desired_mechs
->count
; i
++) {
481 free(desired_mechs
->elements
[i
].elements
);
483 free(desired_mechs
->elements
);
484 return (GSS_S_FAILURE
);
486 memcpy(res
->output_cred_handle
.GSS_CRED_ID_T_val
, &output_cred_handle
,
487 sizeof (gss_cred_id_t
));
489 if (actual_mechs
!= GSS_C_NULL_OID_SET
) {
490 res
->actual_mechs
.GSS_OID_SET_len
=
491 (uint_t
)actual_mechs
->count
;
492 res
->actual_mechs
.GSS_OID_SET_val
= (GSS_OID
*)
493 malloc(sizeof (GSS_OID
) * actual_mechs
->count
);
494 if (!res
->actual_mechs
.GSS_OID_SET_val
) {
495 free(external_name
.value
);
496 free(name_type
->elements
);
497 for (i
= 0; i
< desired_mechs
->count
; i
++) {
498 free(desired_mechs
->elements
[i
].elements
);
500 free(desired_mechs
->elements
);
501 free(res
->output_cred_handle
.GSS_CRED_ID_T_val
);
502 return (GSS_S_FAILURE
);
504 for (i
= 0; i
< actual_mechs
->count
; i
++) {
505 res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
=
506 (uint_t
)actual_mechs
->elements
[i
].length
;
507 res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
=
508 (char *)malloc(actual_mechs
->elements
[i
].
510 if (!res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
) {
511 free(external_name
.value
);
512 free(name_type
->elements
);
513 free(desired_mechs
->elements
);
514 for (j
= 0; j
< desired_mechs
->count
; j
++) {
516 (desired_mechs
->elements
[i
].elements
);
518 free(res
->actual_mechs
.GSS_OID_SET_val
);
519 for (j
= 0; j
< (i
- 1); j
++) {
522 GSS_OID_SET_val
[j
].GSS_OID_val
);
524 return (GSS_S_FAILURE
);
526 memcpy(res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
527 actual_mechs
->elements
[i
].elements
,
528 actual_mechs
->elements
[i
].length
);
531 res
->actual_mechs
.GSS_OID_SET_len
= 0;
534 * set the time verifier for credential handle. To ensure that the
535 * timestamp is not the same as previous gssd process, verify that
536 * time is not the same as set earlier at start of process. If it
537 * is, sleep one second and reset. (due to one second granularity)
540 if (res
->status
== GSS_S_COMPLETE
) {
541 res
->gssd_cred_verifier
= (OM_uint32
)time(NULL
);
542 if (res
->gssd_cred_verifier
== gssd_time_verf
) {
544 gssd_time_verf
= (OM_uint32
)time(NULL
);
546 res
->gssd_cred_verifier
= gssd_time_verf
;
548 syslog_gss_error(res
->status
, res
->minor_status
,
552 * now release the space allocated by the underlying gssapi mechanism
553 * library for actual_mechs as well as by this routine for
554 * external_name, name_type and desired_name
557 free(external_name
.value
);
558 if (name_type
!= GSS_C_NULL_OID
)
559 free(name_type
->elements
);
560 gss_release_name(&minor_status
, &desired_name
);
562 if (actual_mechs
!= GSS_C_NULL_OID_SET
) {
563 for (i
= 0; i
< actual_mechs
->count
; i
++)
564 free(actual_mechs
->elements
[i
].elements
);
565 free(actual_mechs
->elements
);
569 if (desired_mechs
!= GSS_C_NULL_OID_SET
) {
570 for (i
= 0; i
< desired_mechs
->count
; i
++)
571 free(desired_mechs
->elements
[i
].elements
);
572 free(desired_mechs
->elements
);
576 /* return to caller */
582 gss_add_cred_1_svc(argp
, res
, rqstp
)
583 gss_add_cred_arg
*argp
;
584 gss_add_cred_res
*res
;
585 struct svc_req
*rqstp
;
588 OM_uint32 minor_status
;
589 gss_name_t desired_name
;
590 gss_OID_desc name_type_desc
;
591 gss_OID name_type
= &name_type_desc
;
592 gss_OID_desc desired_mech_type_desc
;
593 gss_OID desired_mech_type
= &desired_mech_type_desc
;
595 gss_cred_id_t input_cred_handle
;
596 gss_OID_set actual_mechs
;
597 gss_buffer_desc external_name
;
602 fprintf(stderr
, gettext("gss_add_cred\n"));
604 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
605 res
->status
= (OM_uint32
)GSS_S_DEFECTIVE_CREDENTIAL
;
606 res
->minor_status
= 0;
607 res
->actual_mechs
.GSS_OID_SET_len
= 0;
608 res
->actual_mechs
.GSS_OID_SET_val
= NULL
;
609 res
->initiator_time_rec
= 0;
610 res
->acceptor_time_rec
= 0;
611 fprintf(stderr
, gettext("gss_add_cred defective cred\n"));
614 memset(res
, 0, sizeof (*res
));
617 * if the request isn't from root, null out the result pointer
618 * entries, so the next time through xdr_free won't try to
619 * free unmalloc'd memory and then return NULL
622 if (checkfrom(rqstp
, &uid
) == 0) {
626 /* set the uid sent as the RPC argument */
631 /* convert the desired name from external to internal format */
633 external_name
.length
= argp
->desired_name
.GSS_BUFFER_T_len
;
634 external_name
.value
= (void *)argp
->desired_name
.GSS_BUFFER_T_val
;
635 name_type
->length
= argp
->name_type
.GSS_OID_len
;
636 name_type
->elements
= (void *)argp
->name_type
.GSS_OID_val
;
638 if (gss_import_name(&minor_status
, &external_name
, name_type
,
639 &desired_name
) != GSS_S_COMPLETE
) {
643 gettext("gss_add_cred:import name"),
644 gettext(" failed status %d \n"),
646 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
647 res
->minor_status
= minor_status
;
652 * copy the XDR structured arguments into their corresponding local GSSAPI
656 cred_usage
= argp
->cred_usage
;
657 if (argp
->desired_mech_type
.GSS_OID_len
== 0)
658 desired_mech_type
= GSS_C_NULL_OID
;
660 desired_mech_type
->length
=
661 (OM_uint32
)argp
->desired_mech_type
.GSS_OID_len
;
662 desired_mech_type
->elements
=
663 (void *)malloc(desired_mech_type
->length
);
664 if (!desired_mech_type
->elements
) {
665 return (GSS_S_FAILURE
);
667 memcpy(desired_mech_type
->elements
,
668 argp
->desired_mech_type
.GSS_OID_val
,
669 desired_mech_type
->length
);
672 (argp
->input_cred_handle
.GSS_CRED_ID_T_len
== 0 ?
673 GSS_C_NO_CREDENTIAL
:
675 *((gss_cred_id_t
*)argp
->input_cred_handle
.
678 if (input_cred_handle
!= GSS_C_NO_CREDENTIAL
)
679 /* verify the input_cred_handle */
680 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
681 res
->status
= (OM_uint32
)GSS_S_DEFECTIVE_CREDENTIAL
;
682 res
->minor_status
= 0;
686 /* call the gssapi routine */
688 res
->status
= (OM_uint32
)gss_add_cred(&res
->minor_status
,
693 argp
->initiator_time_req
,
694 argp
->acceptor_time_req
,
697 &res
->initiator_time_rec
,
698 &res
->acceptor_time_rec
);
700 if ((res
->status
!= GSS_S_COMPLETE
) &&
701 (res
->status
!= GSS_S_DUPLICATE_ELEMENT
))
702 syslog_gss_error(res
->status
, res
->minor_status
, "add_cred");
705 * convert the output args from the parameter given in the call to the
706 * variable in the XDR result
708 if (actual_mechs
!= GSS_C_NULL_OID_SET
) {
709 res
->actual_mechs
.GSS_OID_SET_len
=
710 (uint_t
)actual_mechs
->count
;
711 res
->actual_mechs
.GSS_OID_SET_val
= (GSS_OID
*)
712 malloc(sizeof (GSS_OID
) * actual_mechs
->count
);
713 if (!res
->actual_mechs
.GSS_OID_SET_val
) {
714 free(desired_mech_type
->elements
);
715 free(desired_mech_type
);
716 return (GSS_S_FAILURE
);
718 for (i
= 0; i
< actual_mechs
->count
; i
++) {
719 res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_len
=
720 (uint_t
)actual_mechs
->elements
[i
].length
;
721 res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
=
722 (char *)malloc(actual_mechs
->elements
[i
].
724 if (!res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
) {
725 free(desired_mech_type
->elements
);
726 free(desired_mech_type
);
727 free(res
->actual_mechs
.GSS_OID_SET_val
);
728 for (j
= 0; j
< (i
- 1); j
++) {
731 GSS_OID_SET_val
[j
].GSS_OID_val
);
733 return (GSS_S_FAILURE
);
735 memcpy(res
->actual_mechs
.GSS_OID_SET_val
[i
].GSS_OID_val
,
736 actual_mechs
->elements
[i
].elements
,
737 actual_mechs
->elements
[i
].length
);
740 res
->actual_mechs
.GSS_OID_SET_len
= 0;
743 * now release the space allocated for
744 * desired_name and desired_mech_type
747 gss_release_name(&minor_status
, &desired_name
);
748 free(desired_mech_type
->elements
);
749 gss_release_oid_set(&minor_status
, &actual_mechs
);
751 * if (actual_mechs != GSS_C_NULL_OID_SET) {
752 * for (i = 0; i < actual_mechs->count; i++)
753 * free(actual_mechs->elements[i].elements);
754 * free(actual_mechs->elements);
755 * free(actual_mechs);
760 /* return to caller */
766 gss_release_cred_1_svc(argp
, res
, rqstp
)
767 gss_release_cred_arg
*argp
;
768 gss_release_cred_res
*res
;
769 struct svc_req
*rqstp
;
773 gss_cred_id_t cred_handle
;
775 memset(res
, 0, sizeof (*res
));
778 fprintf(stderr
, gettext("gss_release_cred\n"));
780 if (checkfrom(rqstp
, &uid
) == 0)
783 /* set the uid sent as the RPC argument */
789 * if the cred_handle verifier is not correct,
790 * set status to GSS_S_DEFECTIVE_CREDENTIAL and return
793 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
794 res
->status
= (OM_uint32
)GSS_S_DEFECTIVE_CREDENTIAL
;
799 * if the cred_handle length is 0
800 * set cred_handle argument to GSS_S_NO_CREDENTIAL
803 if (argp
->cred_handle
.GSS_CRED_ID_T_len
== 0)
804 cred_handle
= GSS_C_NO_CREDENTIAL
;
807 (gss_cred_id_t
)argp
->cred_handle
.GSS_CRED_ID_T_val
;
809 /* call the gssapi routine */
811 res
->status
= (OM_uint32
)gss_release_cred(&res
->minor_status
,
814 /* return to caller */
820 gss_init_sec_context_1_svc(argp
, res
, rqstp
)
821 gss_init_sec_context_arg
*argp
;
822 gss_init_sec_context_res
*res
;
823 struct svc_req
*rqstp
;
826 OM_uint32 minor_status
;
827 gss_ctx_id_t context_handle
;
828 bool_t context_verf_ok
;
829 gss_cred_id_t claimant_cred_handle
;
830 gss_buffer_desc external_name
;
831 gss_OID_desc name_type_desc
;
832 gss_OID name_type
= &name_type_desc
;
833 gss_name_t internal_name
;
835 gss_OID_desc mech_type_desc
;
836 gss_OID mech_type
= &mech_type_desc
;
837 struct gss_channel_bindings_struct
839 gss_channel_bindings_t input_chan_bindings_ptr
;
840 gss_buffer_desc input_token
;
841 gss_buffer_desc output_token
;
842 gss_buffer_t input_token_ptr
;
843 gss_OID actual_mech_type
;
844 struct gssd_ctx_slot
*slot
= NULL
;
848 memset(res
, 0, sizeof (*res
));
851 fprintf(stderr
, gettext("gss_init_sec_context\n"));
854 * if the request isn't from root, null out the result pointer
855 * entries, so the next time through xdr_free won't try to
856 * free unmalloc'd memory and then return NULL
859 if (checkfrom(rqstp
, &uid
) == 0) {
860 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
861 res
->actual_mech_type
.GSS_OID_val
= NULL
;
862 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
866 /* set the uid sent as the RPC argument */
872 * copy the supplied context handle into the local context handle, so it
873 * can be supplied to the gss_init_sec_context call
876 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
877 argp
->gssd_context_verifier
, &context_verf_ok
, &slot
);
879 claimant_cred_handle
=
880 (argp
->claimant_cred_handle
.GSS_CRED_ID_T_len
== 0 ?
881 GSS_C_NO_CREDENTIAL
:
883 *((gss_cred_id_t
*)argp
->claimant_cred_handle
.
886 if (claimant_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
887 /* verify the verifier_cred_handle */
888 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
889 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
890 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
891 res
->actual_mech_type
.GSS_OID_val
= NULL
;
892 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
893 res
->output_token
.GSS_BUFFER_T_len
= 0;
894 res
->actual_mech_type
.GSS_OID_len
= 0;
895 res
->status
= (OM_uint32
)GSS_S_DEFECTIVE_CREDENTIAL
;
896 res
->minor_status
= 0;
901 if (context_handle
!= GSS_C_NO_CONTEXT
) {
902 /* verify the verifier_context_handle */
904 if (!context_verf_ok
) {
905 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
906 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
907 res
->actual_mech_type
.GSS_OID_val
= NULL
;
908 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
909 res
->output_token
.GSS_BUFFER_T_len
= 0;
910 res
->actual_mech_type
.GSS_OID_len
= 0;
911 res
->status
= (OM_uint32
)GSS_S_NO_CONTEXT
;
912 res
->minor_status
= 0;
917 /* convert the target name from external to internal format */
919 external_name
.length
= argp
->target_name
.GSS_BUFFER_T_len
;
920 external_name
.value
= (void *)argp
->target_name
.GSS_BUFFER_T_val
;
922 if (argp
->name_type
.GSS_OID_len
== 0) {
923 name_type
= GSS_C_NULL_OID
;
925 name_type
->length
= argp
->name_type
.GSS_OID_len
;
926 name_type
->elements
= (void *)malloc(name_type
->length
);
927 if (!name_type
->elements
)
928 return (GSS_S_FAILURE
);
929 memcpy(name_type
->elements
, argp
->name_type
.GSS_OID_val
,
933 if (argp
->mech_type
.GSS_OID_len
== 0)
934 mech_type
= GSS_C_NULL_OID
;
936 mech_type
->length
= (OM_uint32
)argp
->mech_type
.GSS_OID_len
;
937 mech_type
->elements
= (void *)argp
->mech_type
.GSS_OID_val
;
940 if (gss_import_name(&minor_status
, &external_name
, name_type
,
941 &internal_name
) != GSS_S_COMPLETE
) {
943 if (name_type
!= GSS_C_NULL_OID
)
944 free(name_type
->elements
);
945 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
946 res
->minor_status
= minor_status
;
951 * copy the XDR structured arguments into their corresponding local GSSAPI
955 if (argp
->input_chan_bindings
.present
== YES
) {
956 input_chan_bindings_ptr
= &input_chan_bindings
;
957 input_chan_bindings
.initiator_addrtype
=
958 (OM_uint32
)argp
->input_chan_bindings
.
960 input_chan_bindings
.initiator_address
.length
=
961 (uint_t
)argp
->input_chan_bindings
.initiator_address
.
963 input_chan_bindings
.initiator_address
.value
=
964 (void *)argp
->input_chan_bindings
.initiator_address
.
966 input_chan_bindings
.acceptor_addrtype
=
967 (OM_uint32
)argp
->input_chan_bindings
.acceptor_addrtype
;
968 input_chan_bindings
.acceptor_address
.length
=
969 (uint_t
)argp
->input_chan_bindings
.acceptor_address
.
971 input_chan_bindings
.acceptor_address
.value
=
972 (void *)argp
->input_chan_bindings
.acceptor_address
.
974 input_chan_bindings
.application_data
.length
=
975 (uint_t
)argp
->input_chan_bindings
.application_data
.
977 input_chan_bindings
.application_data
.value
=
978 (void *)argp
->input_chan_bindings
.application_data
.
981 input_chan_bindings_ptr
= GSS_C_NO_CHANNEL_BINDINGS
;
982 input_chan_bindings
.initiator_addrtype
= 0;
983 input_chan_bindings
.initiator_address
.length
= 0;
984 input_chan_bindings
.initiator_address
.value
= 0;
985 input_chan_bindings
.acceptor_addrtype
= 0;
986 input_chan_bindings
.acceptor_address
.length
= 0;
987 input_chan_bindings
.acceptor_address
.value
= 0;
988 input_chan_bindings
.application_data
.length
= 0;
989 input_chan_bindings
.application_data
.value
= 0;
992 if (argp
->input_token
.GSS_BUFFER_T_len
== 0) {
993 input_token_ptr
= GSS_C_NO_BUFFER
;
995 input_token_ptr
= &input_token
;
996 input_token
.length
= (size_t)
997 argp
->input_token
.GSS_BUFFER_T_len
;
998 input_token
.value
= (void *)argp
->input_token
.GSS_BUFFER_T_val
;
1001 /* call the gssapi routine */
1003 res
->status
= (OM_uint32
)gss_init_sec_context(&res
->minor_status
,
1004 (gss_cred_id_t
)argp
->claimant_cred_handle
.
1011 input_chan_bindings_ptr
,
1019 * convert the output args from the parameter given in the call to the
1020 * variable in the XDR result
1023 if (res
->status
== (OM_uint32
)GSS_S_COMPLETE
||
1024 res
->status
== (OM_uint32
)GSS_S_CONTINUE_NEEDED
) {
1026 if (slot
== NULL
|| slot
->ctx
!= context_handle
) {
1028 * Note that gssd_alloc_slot() will delete ctx's as long
1029 * as we don't call gssd_rel_slot().
1031 slot
= gssd_alloc_slot(context_handle
);
1034 res
->gssd_context_verifier
= slot
->verf
;
1036 res
->context_handle
.GSS_CTX_ID_T_len
= sizeof (gss_ctx_id_t
);
1037 res
->context_handle
.GSS_CTX_ID_T_val
=
1038 (void *)malloc(sizeof (gss_ctx_id_t
));
1039 if (!res
->context_handle
.GSS_CTX_ID_T_val
) {
1040 free(name_type
->elements
);
1041 return (GSS_S_FAILURE
);
1044 memcpy(res
->context_handle
.GSS_CTX_ID_T_val
, &slot
->rpcctx
,
1045 sizeof (gss_ctx_id_t
));
1047 res
->output_token
.GSS_BUFFER_T_len
=
1048 (uint_t
)output_token
.length
;
1049 res
->output_token
.GSS_BUFFER_T_val
=
1050 (char *)output_token
.value
;
1053 * the actual mech type parameter
1054 * is ready only upon GSS_S_COMPLETE
1056 if (res
->status
== GSS_S_COMPLETE
) {
1057 res
->actual_mech_type
.GSS_OID_len
=
1058 (uint_t
)actual_mech_type
->length
;
1059 res
->actual_mech_type
.GSS_OID_val
=
1060 (void *)malloc(actual_mech_type
->length
);
1061 if (!res
->actual_mech_type
.GSS_OID_val
) {
1062 free(name_type
->elements
);
1063 free(res
->context_handle
.GSS_CTX_ID_T_val
);
1064 return (GSS_S_FAILURE
);
1066 memcpy(res
->actual_mech_type
.GSS_OID_val
,
1067 (char *)actual_mech_type
->elements
,
1068 actual_mech_type
->length
);
1070 res
->actual_mech_type
.GSS_OID_len
= 0;
1072 syslog_gss_error(res
->status
, res
->minor_status
,
1073 "init_sec_context");
1074 if (context_handle
!= GSS_C_NO_CONTEXT
) {
1075 (void) gss_delete_sec_context(&minor_status
,
1076 &context_handle
, NULL
);
1078 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1079 res
->actual_mech_type
.GSS_OID_len
= 0;
1080 res
->output_token
.GSS_BUFFER_T_len
= 0;
1084 * now release the space allocated by the underlying gssapi mechanism
1085 * library for internal_name and for the name_type.
1088 gss_release_name(&minor_status
, &internal_name
);
1089 if (name_type
!= GSS_C_NULL_OID
)
1090 free(name_type
->elements
);
1093 /* return to caller */
1098 gss_accept_sec_context_1_svc(argp
, res
, rqstp
)
1099 gss_accept_sec_context_arg
*argp
;
1100 gss_accept_sec_context_res
*res
;
1101 struct svc_req
*rqstp
;
1104 OM_uint32 minor_status
;
1105 gss_ctx_id_t context_handle
= NULL
;
1106 gss_cred_id_t verifier_cred_handle
;
1107 gss_buffer_desc external_name
;
1108 gss_name_t internal_name
= NULL
;
1110 gss_buffer_desc input_token_buffer
;
1111 gss_buffer_t input_token_buffer_ptr
;
1112 struct gss_channel_bindings_struct
1113 input_chan_bindings
;
1114 gss_channel_bindings_t input_chan_bindings_ptr
;
1116 gss_buffer_desc output_token
;
1117 gss_cred_id_t delegated_cred_handle
;
1118 bool_t context_verf_ok
;
1119 struct gssd_ctx_slot
*slot
= NULL
;
1121 memset(res
, 0, sizeof (*res
));
1124 fprintf(stderr
, gettext("gss_accept_sec_context\n"));
1127 * if the request isn't from root, null out the result pointer
1128 * entries, so the next time through xdr_free won't try to
1129 * free unmalloc'd memory and then return NULL
1132 if (checkfrom(rqstp
, &uid
) == 0) {
1133 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1134 res
->src_name
.GSS_BUFFER_T_val
= NULL
;
1135 res
->mech_type
.GSS_OID_val
= NULL
;
1136 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1137 res
->delegated_cred_handle
.GSS_CRED_ID_T_val
= NULL
;
1141 /* set the uid sent as the RPC argument */
1147 * copy the supplied context handle into the local context handle, so
1148 * it can be supplied to the gss_accept_sec_context call
1151 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1152 argp
->gssd_context_verifier
, &context_verf_ok
, &slot
);
1154 if (context_handle
!= GSS_C_NO_CONTEXT
)
1155 /* verify the context_handle */
1156 if (!context_verf_ok
) {
1157 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1158 res
->src_name
.GSS_BUFFER_T_val
= NULL
;
1159 res
->mech_type
.GSS_OID_val
= NULL
;
1160 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1161 res
->delegated_cred_handle
.GSS_CRED_ID_T_val
= NULL
;
1162 res
->src_name
.GSS_BUFFER_T_len
= 0;
1163 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1164 res
->delegated_cred_handle
.GSS_CRED_ID_T_len
= 0;
1165 res
->output_token
.GSS_BUFFER_T_len
= 0;
1166 res
->mech_type
.GSS_OID_len
= 0;
1167 res
->status
= (OM_uint32
)GSS_S_NO_CONTEXT
;
1168 res
->minor_status
= 0;
1173 * copy the XDR structured arguments into their corresponding local
1174 * GSSAPI variable equivalents.
1178 verifier_cred_handle
=
1179 (argp
->verifier_cred_handle
.GSS_CRED_ID_T_len
== 0 ?
1180 GSS_C_NO_CREDENTIAL
:
1182 *((gss_cred_id_t
*)argp
->verifier_cred_handle
.
1183 GSS_CRED_ID_T_val
));
1185 if (verifier_cred_handle
!= GSS_C_NO_CREDENTIAL
)
1186 /* verify the verifier_cred_handle */
1187 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
1188 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1189 res
->src_name
.GSS_BUFFER_T_val
= NULL
;
1190 res
->mech_type
.GSS_OID_val
= NULL
;
1191 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1192 res
->delegated_cred_handle
.GSS_CRED_ID_T_val
= NULL
;
1193 res
->src_name
.GSS_BUFFER_T_len
= 0;
1194 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1195 res
->delegated_cred_handle
.GSS_CRED_ID_T_len
= 0;
1196 res
->output_token
.GSS_BUFFER_T_len
= 0;
1197 res
->mech_type
.GSS_OID_len
= 0;
1198 res
->status
= (OM_uint32
)GSS_S_DEFECTIVE_CREDENTIAL
;
1199 res
->minor_status
= 0;
1203 input_token_buffer_ptr
= &input_token_buffer
;
1204 input_token_buffer
.length
= (size_t)argp
->input_token_buffer
.
1206 input_token_buffer
.value
= (void *)argp
->input_token_buffer
.
1209 if (argp
->input_chan_bindings
.present
== YES
) {
1210 input_chan_bindings_ptr
= &input_chan_bindings
;
1211 input_chan_bindings
.initiator_addrtype
=
1212 (OM_uint32
)argp
->input_chan_bindings
.
1214 input_chan_bindings
.initiator_address
.length
=
1215 (uint_t
)argp
->input_chan_bindings
.initiator_address
.
1217 input_chan_bindings
.initiator_address
.value
=
1218 (void *)argp
->input_chan_bindings
.initiator_address
.
1220 input_chan_bindings
.acceptor_addrtype
=
1221 (OM_uint32
)argp
->input_chan_bindings
.
1223 input_chan_bindings
.acceptor_address
.length
=
1224 (uint_t
)argp
->input_chan_bindings
.acceptor_address
.
1226 input_chan_bindings
.acceptor_address
.value
=
1227 (void *)argp
->input_chan_bindings
.acceptor_address
.
1229 input_chan_bindings
.application_data
.length
=
1230 (uint_t
)argp
->input_chan_bindings
.application_data
.
1232 input_chan_bindings
.application_data
.value
=
1233 (void *)argp
->input_chan_bindings
.application_data
.
1236 input_chan_bindings_ptr
= GSS_C_NO_CHANNEL_BINDINGS
;
1237 input_chan_bindings
.initiator_addrtype
= 0;
1238 input_chan_bindings
.initiator_address
.length
= 0;
1239 input_chan_bindings
.initiator_address
.value
= 0;
1240 input_chan_bindings
.acceptor_addrtype
= 0;
1241 input_chan_bindings
.acceptor_address
.length
= 0;
1242 input_chan_bindings
.acceptor_address
.value
= 0;
1243 input_chan_bindings
.application_data
.length
= 0;
1244 input_chan_bindings
.application_data
.value
= 0;
1248 /* call the gssapi routine */
1250 res
->status
= (OM_uint32
)gss_accept_sec_context(&res
->minor_status
,
1252 verifier_cred_handle
,
1253 input_token_buffer_ptr
,
1254 input_chan_bindings_ptr
,
1260 &delegated_cred_handle
);
1262 /* convert the src name from internal to external format */
1264 if (res
->status
== (OM_uint32
)GSS_S_COMPLETE
||
1265 res
->status
== (OM_uint32
)GSS_S_CONTINUE_NEEDED
) {
1268 * upon GSS_S_CONTINUE_NEEDED only the following
1269 * parameters are ready: minor, ctxt, and output token
1271 res
->context_handle
.GSS_CTX_ID_T_len
= sizeof (gss_ctx_id_t
);
1272 res
->context_handle
.GSS_CTX_ID_T_val
=
1273 (void *)malloc(sizeof (gss_ctx_id_t
));
1274 if (!res
->context_handle
.GSS_CTX_ID_T_val
) {
1275 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
1276 res
->minor_status
= 0;
1280 if (slot
== NULL
|| slot
->ctx
!= context_handle
) {
1282 * Note that gssd_alloc_slot() will delete ctx's as long
1283 * as we don't call gssd_rel_slot().
1285 slot
= gssd_alloc_slot(context_handle
);
1288 memcpy(res
->context_handle
.GSS_CTX_ID_T_val
, &slot
->rpcctx
,
1289 sizeof (gss_ctx_id_t
));
1290 res
->gssd_context_verifier
= slot
->verf
;
1292 res
->output_token
.GSS_BUFFER_T_len
=
1293 (uint_t
)output_token
.length
;
1294 res
->output_token
.GSS_BUFFER_T_val
=
1295 (char *)output_token
.value
;
1297 if (res
->status
== GSS_S_COMPLETE
) {
1298 if (gss_export_name(&minor_status
, internal_name
,
1300 != GSS_S_COMPLETE
) {
1302 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
1303 res
->minor_status
= minor_status
;
1304 gss_release_name(&minor_status
, &internal_name
);
1305 gss_delete_sec_context(&minor_status
,
1306 &context_handle
, NULL
);
1307 free(res
->context_handle
.GSS_CTX_ID_T_val
);
1308 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1309 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1310 gss_release_buffer(&minor_status
,
1312 res
->output_token
.GSS_BUFFER_T_len
= 0;
1313 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1316 res
->src_name
.GSS_BUFFER_T_len
=
1317 (uint_t
)external_name
.length
;
1318 res
->src_name
.GSS_BUFFER_T_val
=
1319 (void *)external_name
.value
;
1321 res
->delegated_cred_handle
.GSS_CRED_ID_T_len
=
1322 sizeof (gss_cred_id_t
);
1323 res
->delegated_cred_handle
.GSS_CRED_ID_T_val
=
1324 (void *)malloc(sizeof (gss_cred_id_t
));
1325 if (!res
->delegated_cred_handle
.GSS_CRED_ID_T_val
) {
1326 free(res
->context_handle
.GSS_CTX_ID_T_val
);
1327 gss_release_name(&minor_status
, &internal_name
);
1328 gss_delete_sec_context(&minor_status
,
1329 &context_handle
, NULL
);
1330 gss_release_buffer(&minor_status
,
1332 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
1333 res
->minor_status
= 0;
1336 memcpy(res
->delegated_cred_handle
.GSS_CRED_ID_T_val
,
1337 &delegated_cred_handle
,
1338 sizeof (gss_cred_id_t
));
1340 res
->mech_type
.GSS_OID_len
= (uint_t
)mech_type
->length
;
1341 res
->mech_type
.GSS_OID_val
=
1342 (void *)malloc(mech_type
->length
);
1343 if (!res
->mech_type
.GSS_OID_val
) {
1344 free(res
->context_handle
.GSS_CTX_ID_T_val
);
1345 free(res
->delegated_cred_handle
.GSS_CRED_ID_T_val
);
1346 gss_release_name(&minor_status
, &internal_name
);
1347 gss_delete_sec_context(&minor_status
,
1348 &context_handle
, NULL
);
1349 gss_release_buffer(&minor_status
, &external_name
);
1350 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
1351 res
->minor_status
= 0;
1354 memcpy(res
->mech_type
.GSS_OID_val
, mech_type
->elements
,
1357 /* release the space allocated for internal_name */
1358 gss_release_name(&minor_status
, &internal_name
);
1360 } else { /* GSS_S_CONTINUE_NEEDED */
1361 res
->src_name
.GSS_BUFFER_T_len
= 0;
1362 res
->delegated_cred_handle
.GSS_CRED_ID_T_len
= 0;
1363 res
->mech_type
.GSS_OID_len
= 0;
1366 syslog_gss_error(res
->status
, res
->minor_status
,
1367 "accept_sec_context");
1369 if (context_handle
!= GSS_C_NO_CONTEXT
) {
1370 (void) gss_delete_sec_context(&minor_status
,
1371 &context_handle
, NULL
);
1373 res
->src_name
.GSS_BUFFER_T_len
= 0;
1374 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1375 res
->delegated_cred_handle
.GSS_CRED_ID_T_len
= 0;
1376 res
->output_token
.GSS_BUFFER_T_len
=
1377 (uint_t
)output_token
.length
;
1378 res
->output_token
.GSS_BUFFER_T_val
=
1379 (char *)output_token
.value
;
1381 res
->mech_type
.GSS_OID_len
= 0;
1384 /* return to caller */
1390 gss_process_context_token_1_svc(argp
, res
, rqstp
)
1391 gss_process_context_token_arg
*argp
;
1392 gss_process_context_token_res
*res
;
1393 struct svc_req
*rqstp
;
1397 gss_buffer_desc token_buffer
;
1398 gss_ctx_id_t context_handle
;
1399 bool_t context_verf_ok
;
1401 memset(res
, 0, sizeof (*res
));
1404 fprintf(stderr
, gettext("gss_process_context_token\n"));
1406 if (checkfrom(rqstp
, &uid
) == 0)
1409 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1410 argp
->gssd_context_verifier
, &context_verf_ok
, NULL
);
1412 /* verify the context_handle */
1414 if (!context_verf_ok
) {
1415 res
->status
= (OM_uint32
) GSS_S_NO_CONTEXT
;
1416 res
->minor_status
= 0;
1420 /* set the uid sent as the RPC argument */
1426 * copy the XDR structured arguments into their corresponding local
1427 * GSSAPI variable equivalents.
1430 token_buffer
.length
= (size_t)argp
->token_buffer
.GSS_BUFFER_T_len
;
1431 token_buffer
.value
= (void *)argp
->token_buffer
.GSS_BUFFER_T_val
;
1434 /* call the gssapi routine */
1436 res
->status
= (OM_uint32
)gss_process_context_token(&res
->minor_status
,
1440 if (GSS_ERROR(res
->status
))
1441 syslog_gss_error(res
->status
, res
->minor_status
,
1442 "process_context_token");
1444 /* return to caller */
1450 gss_delete_sec_context_1_svc(argp
, res
, rqstp
)
1451 gss_delete_sec_context_arg
*argp
;
1452 gss_delete_sec_context_res
*res
;
1453 struct svc_req
*rqstp
;
1456 gss_ctx_id_t context_handle
;
1457 gss_buffer_desc output_token
;
1458 bool_t context_verf_ok
;
1459 struct gssd_ctx_slot
*slot
= NULL
;
1461 memset(res
, 0, sizeof (*res
));
1464 fprintf(stderr
, gettext("gss_delete_sec_context\n"));
1468 * copy the supplied context handle into the local context handle, so it
1469 * can be supplied to the gss_delete_sec_context call
1471 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1472 argp
->gssd_context_verifier
, &context_verf_ok
, &slot
);
1474 /* verify the context_handle */
1475 if (!context_verf_ok
) {
1476 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1477 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1478 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1479 res
->output_token
.GSS_BUFFER_T_len
= 0;
1480 res
->status
= (OM_uint32
)GSS_S_NO_CONTEXT
;
1481 res
->minor_status
= 0;
1486 * if the request isn't from root, null out the result pointer
1487 * entries, so the next time through xdr_free won't try to
1488 * free unmalloc'd memory and then return NULL
1491 if (checkfrom(rqstp
, &uid
) == 0) {
1492 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1493 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1497 /* call the gssapi routine */
1499 res
->status
= (OM_uint32
)gss_delete_sec_context(&res
->minor_status
,
1504 * convert the output args from the parameter given in the call to the
1505 * variable in the XDR result. If the delete succeeded, return a zero
1509 if (res
->status
== GSS_S_COMPLETE
) {
1510 if (context_handle
!= GSS_C_NO_CONTEXT
)
1511 return (GSS_S_FAILURE
);
1512 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1513 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1514 res
->output_token
.GSS_BUFFER_T_len
=
1515 (uint_t
)output_token
.length
;
1516 res
->output_token
.GSS_BUFFER_T_val
=
1517 (char *)output_token
.value
;
1521 * gss_delete_sec_context deletes the context if it
1522 * succeeds so clear slot->ctx to avoid a dangling
1525 slot
->ctx
= GSS_C_NO_CONTEXT
;
1526 gssd_rel_slot(slot
);
1529 res
->context_handle
.GSS_CTX_ID_T_len
= sizeof (gss_ctx_id_t
);
1530 res
->context_handle
.GSS_CTX_ID_T_val
=
1531 (void *)malloc(sizeof (gss_ctx_id_t
));
1532 if (!res
->context_handle
.GSS_CTX_ID_T_val
) {
1533 return (GSS_S_FAILURE
);
1536 if (slot
== NULL
|| slot
->ctx
!= context_handle
) {
1538 * Note that gssd_alloc_slot() will delete ctx's as long
1539 * as we don't call gssd_rel_slot().
1541 slot
= gssd_alloc_slot(context_handle
);
1543 * Note that no verifier is returned in the .x
1544 * protocol. So if the context changes, we won't
1545 * be able to release it now. So it will have to
1550 memcpy(res
->context_handle
.GSS_CTX_ID_T_val
, &slot
->rpcctx
,
1551 sizeof (gss_ctx_id_t
));
1553 res
->output_token
.GSS_BUFFER_T_len
= 0;
1554 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1557 /* return to caller */
1565 gss_export_sec_context_1_svc(argp
, res
, rqstp
)
1566 gss_export_sec_context_arg
*argp
;
1567 gss_export_sec_context_res
*res
;
1568 struct svc_req
*rqstp
;
1572 gss_ctx_id_t context_handle
;
1573 gss_buffer_desc output_token
;
1574 bool_t context_verf_ok
;
1575 struct gssd_ctx_slot
*slot
= NULL
;
1577 memset(res
, 0, sizeof (*res
));
1580 fprintf(stderr
, "gss_export_sec_context\n");
1583 * if the request isn't from root, null out the result pointer
1584 * entries, so the next time through xdr_free won't try to
1585 * free unmalloc'd memory and then return NULL
1588 if (checkfrom(rqstp
, &uid
) == 0) {
1589 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1590 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1595 * copy the supplied context handle into the local context handle, so it
1596 * can be supplied to the gss_export_sec_context call
1599 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1600 argp
->gssd_context_verifier
, &context_verf_ok
, &slot
);
1602 /* verify the context_handle */
1604 if (!context_verf_ok
) {
1605 res
->status
= (OM_uint32
)GSS_S_NO_CONTEXT
;
1606 /* the rest of "res" was cleared by a previous memset() */
1610 /* call the gssapi routine */
1612 res
->status
= (OM_uint32
)gss_export_sec_context(&res
->minor_status
,
1617 * convert the output args from the parameter given in the call to the
1618 * variable in the XDR result. If the delete succeeded, return a zero context
1621 if (res
->status
== GSS_S_COMPLETE
) {
1622 if (context_handle
!= GSS_C_NO_CONTEXT
)
1623 return (GSS_S_FAILURE
);
1624 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1625 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1626 res
->output_token
.GSS_BUFFER_T_len
=
1627 (uint_t
)output_token
.length
;
1628 res
->output_token
.GSS_BUFFER_T_val
=
1629 (char *)output_token
.value
;
1633 * gss_export_sec_context deletes the context if it
1634 * succeeds so set slot->ctx to avoid a dangling
1637 slot
->ctx
= GSS_C_NO_CONTEXT
;
1638 gssd_rel_slot(slot
);
1641 res
->context_handle
.GSS_CTX_ID_T_len
= sizeof (gss_ctx_id_t
);
1642 res
->context_handle
.GSS_CTX_ID_T_val
=
1643 (void *)malloc(sizeof (gss_ctx_id_t
));
1645 if (slot
== NULL
|| slot
->ctx
!= context_handle
) {
1647 * Note that gssd_alloc_slot() will delete ctx's as long
1648 * as we don't call gssd_rel_slot().
1650 slot
= gssd_alloc_slot(context_handle
);
1652 * Note that no verifier is returned in the .x
1653 * protocol. So if the context changes, we won't
1654 * be able to release it now. So it will have to
1659 memcpy(res
->context_handle
.GSS_CTX_ID_T_val
, &slot
->rpcctx
,
1660 sizeof (gss_ctx_id_t
));
1661 res
->output_token
.GSS_BUFFER_T_len
= 0;
1662 res
->output_token
.GSS_BUFFER_T_val
= NULL
;
1666 /* return to caller */
1672 * This routine doesn't appear to ever be called.
1675 gss_import_sec_context_1_svc(argp
, res
, rqstp
)
1676 gss_import_sec_context_arg
*argp
;
1677 gss_import_sec_context_res
*res
;
1678 struct svc_req
*rqstp
;
1682 gss_ctx_id_t context_handle
;
1683 gss_buffer_desc input_token
;
1684 gss_buffer_t input_token_ptr
;
1686 memset(res
, 0, sizeof (*res
));
1689 fprintf(stderr
, "gss_export_sec_context\n");
1692 * if the request isn't from root, null out the result pointer
1693 * entries, so the next time through xdr_free won't try to
1694 * free unmalloc'd memory and then return NULL
1697 if (checkfrom(rqstp
, &uid
) == 0) {
1698 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1703 if (argp
->input_token
.GSS_BUFFER_T_len
== 0) {
1704 input_token_ptr
= GSS_C_NO_BUFFER
;
1706 input_token_ptr
= &input_token
;
1707 input_token
.length
= (size_t)
1708 argp
->input_token
.GSS_BUFFER_T_len
;
1709 input_token
.value
= (void *) argp
->input_token
.GSS_BUFFER_T_val
;
1713 /* call the gssapi routine */
1715 res
->status
= (OM_uint32
) gss_import_sec_context(&res
->minor_status
,
1720 * convert the output args from the parameter given in the call to the
1721 * variable in the XDR result. If the delete succeeded, return a zero context
1724 if (res
->status
== GSS_S_COMPLETE
) {
1725 res
->context_handle
.GSS_CTX_ID_T_len
= sizeof (gss_ctx_id_t
);
1726 res
->context_handle
.GSS_CTX_ID_T_val
=
1727 (void *) malloc(sizeof (gss_ctx_id_t
));
1728 memcpy(res
->context_handle
.GSS_CTX_ID_T_val
, &context_handle
,
1729 sizeof (gss_ctx_id_t
));
1731 res
->context_handle
.GSS_CTX_ID_T_len
= 0;
1732 res
->context_handle
.GSS_CTX_ID_T_val
= NULL
;
1736 /* return to caller */
1742 gss_context_time_1_svc(argp
, res
, rqstp
)
1743 gss_context_time_arg
*argp
;
1744 gss_context_time_res
*res
;
1745 struct svc_req
*rqstp
;
1749 memset(res
, 0, sizeof (*res
));
1752 fprintf(stderr
, gettext("gss_context_time\n"));
1755 * if the request isn't from root, null out the result pointer
1756 * entries, so the next time through xdr_free won't try to
1757 * free unmalloc'd memory and then return NULL
1760 if (checkfrom(rqstp
, &uid
) == 0)
1763 /* set the uid sent as the RPC argument */
1768 /* Semantics go here */
1774 gss_sign_1_svc(argp
, res
, rqstp
)
1777 struct svc_req
*rqstp
;
1782 gss_buffer_desc message_buffer
;
1783 gss_buffer_desc msg_token
;
1784 gss_ctx_id_t context_handle
;
1785 bool_t context_verf_ok
;
1787 memset(res
, 0, sizeof (*res
));
1790 fprintf(stderr
, gettext("gss_sign\n"));
1792 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1793 argp
->gssd_context_verifier
, &context_verf_ok
, NULL
);
1795 /* verify the context_handle */
1796 if (!context_verf_ok
) {
1797 res
->msg_token
.GSS_BUFFER_T_val
= NULL
;
1798 res
->msg_token
.GSS_BUFFER_T_len
= 0;
1799 res
->status
= (OM_uint32
) GSS_S_NO_CONTEXT
;
1800 res
->minor_status
= 0;
1806 * if the request isn't from root, null out the result pointer
1807 * entries, so the next time through xdr_free won't try to
1808 * free unmalloc'd memory and then return NULL
1811 if (checkfrom(rqstp
, &uid
) == 0) {
1812 res
->msg_token
.GSS_BUFFER_T_val
= NULL
;
1817 * copy the XDR structured arguments into their corresponding local
1818 * GSSAPI variable equivalents.
1821 message_buffer
.length
= (size_t)argp
->message_buffer
.GSS_BUFFER_T_len
;
1822 message_buffer
.value
= (void *)argp
->message_buffer
.GSS_BUFFER_T_val
;
1824 /* call the gssapi routine */
1826 res
->status
= (OM_uint32
)gss_sign(&res
->minor_status
,
1829 (gss_buffer_t
)&message_buffer
,
1830 (gss_buffer_t
)&msg_token
);
1832 * convert the output args from the parameter given in the call to
1833 * the variable in the XDR result
1836 if (res
->status
== GSS_S_COMPLETE
) {
1837 res
->msg_token
.GSS_BUFFER_T_len
= (uint_t
)msg_token
.length
;
1838 res
->msg_token
.GSS_BUFFER_T_val
= (char *)msg_token
.value
;
1840 syslog_gss_error(res
->status
, res
->minor_status
, "sign");
1842 /* return to caller */
1848 gss_verify_1_svc(argp
, res
, rqstp
)
1849 gss_verify_arg
*argp
;
1850 gss_verify_res
*res
;
1851 struct svc_req
*rqstp
;
1856 gss_buffer_desc message_buffer
;
1857 gss_buffer_desc token_buffer
;
1858 gss_ctx_id_t context_handle
;
1859 bool_t context_verf_ok
;
1861 memset(res
, 0, sizeof (*res
));
1864 fprintf(stderr
, gettext("gss_verify\n"));
1866 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1867 argp
->gssd_context_verifier
, &context_verf_ok
, NULL
);
1869 /* verify the context_handle */
1870 if (!context_verf_ok
) {
1871 res
->status
= (OM_uint32
) GSS_S_NO_CONTEXT
;
1872 res
->minor_status
= 0;
1877 * if the request isn't from root, null out the result pointer
1878 * entries, so the next time through xdr_free won't try to
1879 * free unmalloc'd memory and then return NULL
1882 if (checkfrom(rqstp
, &uid
) == 0)
1886 * copy the XDR structured arguments into their corresponding local
1887 * GSSAPI variable equivalents.
1890 message_buffer
.length
= (size_t)argp
->message_buffer
.GSS_BUFFER_T_len
;
1891 message_buffer
.value
= (void *)argp
->message_buffer
.GSS_BUFFER_T_val
;
1893 token_buffer
.length
= (size_t)argp
->token_buffer
.GSS_BUFFER_T_len
;
1894 token_buffer
.value
= (void *)argp
->token_buffer
.GSS_BUFFER_T_val
;
1896 /* call the gssapi routine */
1898 res
->status
= (OM_uint32
)gss_verify(&res
->minor_status
,
1904 if (GSS_ERROR(res
->status
))
1905 syslog_gss_error(res
->status
, res
->minor_status
, "verify");
1907 /* return to caller */
1912 gss_seal_1_svc(argp
, res
, rqstp
)
1915 struct svc_req
*rqstp
;
1919 gss_buffer_desc input_message_buffer
;
1920 gss_buffer_desc output_message_buffer
;
1921 gss_ctx_id_t context_handle
;
1922 bool_t context_verf_ok
;
1924 memset(res
, 0, sizeof (*res
));
1927 fprintf(stderr
, gettext("gss_seal\n"));
1929 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
1930 argp
->gssd_context_verifier
, &context_verf_ok
, NULL
);
1932 /* verify the context_handle */
1934 if (!context_verf_ok
) {
1935 res
->output_message_buffer
.GSS_BUFFER_T_val
= NULL
;
1936 res
->output_message_buffer
.GSS_BUFFER_T_len
= 0;
1937 res
->status
= (OM_uint32
) GSS_S_NO_CONTEXT
;
1938 res
->minor_status
= 0;
1943 * if the request isn't from root, null out the result pointer
1944 * entries, so the next time through xdr_free won't try to
1945 * free unmalloc'd memory and then return NULL
1948 if (checkfrom(rqstp
, &uid
) == 0) {
1949 res
->output_message_buffer
.GSS_BUFFER_T_val
= NULL
;
1956 * copy the XDR structured arguments into their corresponding local
1957 * GSSAPI variable equivalents.
1960 input_message_buffer
.length
= (size_t)argp
->input_message_buffer
.
1962 input_message_buffer
.value
= (void *)argp
->input_message_buffer
.
1966 /* call the gssapi routine */
1968 res
->status
= (OM_uint32
)gss_seal(&res
->minor_status
,
1970 argp
->conf_req_flag
,
1972 &input_message_buffer
,
1974 &output_message_buffer
);
1976 * convert the output args from the parameter given in the call to the
1977 * variable in the XDR result
1980 if (res
->status
== GSS_S_COMPLETE
) {
1981 res
->output_message_buffer
.GSS_BUFFER_T_len
=
1982 (uint_t
)output_message_buffer
.length
;
1983 res
->output_message_buffer
.GSS_BUFFER_T_val
=
1984 (char *)output_message_buffer
.value
;
1986 syslog_gss_error(res
->status
, res
->minor_status
, "seal");
1988 /* return to caller */
1994 gss_unseal_1_svc(argp
, res
, rqstp
)
1995 gss_unseal_arg
*argp
;
1996 gss_unseal_res
*res
;
1997 struct svc_req
*rqstp
;
2002 gss_buffer_desc input_message_buffer
;
2003 gss_buffer_desc output_message_buffer
;
2004 gss_ctx_id_t context_handle
;
2005 bool_t context_verf_ok
;
2007 memset(res
, 0, sizeof (*res
));
2010 fprintf(stderr
, gettext("gss_unseal\n"));
2012 /* verify the context_handle */
2013 gssd_convert_context_handle(&argp
->context_handle
, &context_handle
,
2014 argp
->gssd_context_verifier
, &context_verf_ok
, NULL
);
2016 /* verify the context_handle */
2017 if (!context_verf_ok
) {
2018 res
->output_message_buffer
.GSS_BUFFER_T_val
= NULL
;
2019 res
->output_message_buffer
.GSS_BUFFER_T_len
= 0;
2020 res
->status
= (OM_uint32
)GSS_S_NO_CONTEXT
;
2021 res
->minor_status
= 0;
2026 * if the request isn't from root, null out the result pointer
2027 * entries, so the next time through xdr_free won't try to
2028 * free unmalloc'd memory and then return NULL
2031 if (checkfrom(rqstp
, &uid
) == 0) {
2032 res
->output_message_buffer
.GSS_BUFFER_T_val
= NULL
;
2038 * copy the XDR structured arguments into their corresponding local
2039 * GSSAPI variable equivalents.
2042 input_message_buffer
.length
= (size_t)argp
->input_message_buffer
.
2044 input_message_buffer
.value
= (void *)argp
->input_message_buffer
.
2047 /* call the gssapi routine */
2049 res
->status
= (OM_uint32
)gss_unseal(&res
->minor_status
,
2051 &input_message_buffer
,
2052 &output_message_buffer
,
2057 * convert the output args from the parameter given in the call to the
2058 * variable in the XDR result
2061 if (res
->status
== GSS_S_COMPLETE
) {
2062 res
->output_message_buffer
.GSS_BUFFER_T_len
=
2063 (uint_t
)output_message_buffer
.length
;
2064 res
->output_message_buffer
.GSS_BUFFER_T_val
=
2065 (char *)output_message_buffer
.value
;
2067 syslog_gss_error(res
->status
, res
->minor_status
, "unseal");
2070 /* return to caller */
2076 gss_display_status_1_svc(argp
, res
, rqstp
)
2077 gss_display_status_arg
*argp
;
2078 gss_display_status_res
*res
;
2079 struct svc_req
*rqstp
;
2083 gss_OID_desc mech_type_desc
;
2084 gss_buffer_desc status_string
;
2086 memset(res
, 0, sizeof (*res
));
2089 fprintf(stderr
, gettext("gss_display_status\n"));
2092 * if the request isn't from root, null out the result pointer
2093 * entries, so the next time through xdr_free won't try to
2094 * free unmalloc'd memory and then return NULL
2097 if (checkfrom(rqstp
, &uid
) == 0) {
2098 res
->status_string
.GSS_BUFFER_T_val
= NULL
;
2102 /* set the uid sent as the RPC argument */
2108 * copy the XDR structured arguments into their corresponding local
2112 if (argp
->mech_type
.GSS_OID_len
== 0)
2113 mech_type
= GSS_C_NULL_OID
;
2115 mech_type
= &mech_type_desc
;
2116 mech_type_desc
.length
= (OM_uint32
) argp
->mech_type
.GSS_OID_len
;
2117 mech_type_desc
.elements
= (void *) argp
->mech_type
.GSS_OID_val
;
2121 /* call the gssapi routine */
2123 res
->status
= (OM_uint32
) gss_display_status(&res
->minor_status
,
2127 (OM_uint32
*)&res
->message_context
,
2131 * convert the output args from the parameter given in the call to the
2132 * variable in the XDR result
2135 if (res
->status
== GSS_S_COMPLETE
) {
2136 res
->status_string
.GSS_BUFFER_T_len
=
2137 (uint_t
)status_string
.length
;
2138 res
->status_string
.GSS_BUFFER_T_val
=
2139 (char *)status_string
.value
;
2148 gss_indicate_mechs_1_svc(argp
, res
, rqstp
)
2150 gss_indicate_mechs_res
*res
;
2151 struct svc_req
*rqstp
;
2153 gss_OID_set oid_set
;
2156 memset(res
, 0, sizeof (*res
));
2159 fprintf(stderr
, gettext("gss_indicate_mechs\n"));
2161 res
->mech_set
.GSS_OID_SET_val
= NULL
;
2164 * if the request isn't from root, null out the result pointer
2165 * entries, so the next time through xdr_free won't try to
2166 * free unmalloc'd memory and then return NULL
2169 if (checkfrom(rqstp
, &uid
) == 0) {
2173 res
->status
= gss_indicate_mechs(&res
->minor_status
, &oid_set
);
2175 if (res
->status
== GSS_S_COMPLETE
) {
2178 res
->mech_set
.GSS_OID_SET_len
= oid_set
->count
;
2179 res
->mech_set
.GSS_OID_SET_val
= (void *)
2180 malloc(oid_set
->count
* sizeof (GSS_OID
));
2181 if (!res
->mech_set
.GSS_OID_SET_val
) {
2182 return (GSS_S_FAILURE
);
2184 for (i
= 0; i
< oid_set
->count
; i
++) {
2185 res
->mech_set
.GSS_OID_SET_val
[i
].GSS_OID_len
=
2186 oid_set
->elements
[i
].length
;
2187 res
->mech_set
.GSS_OID_SET_val
[i
].GSS_OID_val
=
2188 (char *)malloc(oid_set
->elements
[i
].length
);
2189 if (!res
->mech_set
.GSS_OID_SET_val
[i
].GSS_OID_val
) {
2190 for (j
= 0; j
< (i
-1); j
++) {
2192 (res
->mech_set
.GSS_OID_SET_val
[i
].GSS_OID_val
);
2194 free(res
->mech_set
.GSS_OID_SET_val
);
2195 return (GSS_S_FAILURE
);
2197 memcpy(res
->mech_set
.GSS_OID_SET_val
[i
].GSS_OID_val
,
2198 oid_set
->elements
[i
].elements
,
2199 oid_set
->elements
[i
].length
);
2207 gss_inquire_cred_1_svc(argp
, res
, rqstp
)
2208 gss_inquire_cred_arg
*argp
;
2209 gss_inquire_cred_res
*res
;
2210 struct svc_req
*rqstp
;
2215 OM_uint32 minor_status
;
2216 gss_cred_id_t cred_handle
;
2217 gss_buffer_desc external_name
;
2219 gss_name_t internal_name
;
2220 gss_OID_set mechanisms
;
2223 memset(res
, 0, sizeof (*res
));
2226 fprintf(stderr
, gettext("gss_inquire_cred\n"));
2228 /* verify the verifier_cred_handle */
2230 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
2231 res
->name
.GSS_BUFFER_T_val
= NULL
;
2232 res
->name_type
.GSS_OID_val
= NULL
;
2233 res
->mechanisms
.GSS_OID_SET_val
= NULL
;
2234 res
->status
= (OM_uint32
) GSS_S_DEFECTIVE_CREDENTIAL
;
2235 res
->minor_status
= 0;
2240 * if the request isn't from root, null out the result pointer
2241 * entries, so the next time through xdr_free won't try to
2242 * free unmalloc'd memory and then return NULL
2245 if (checkfrom(rqstp
, &uid
) == 0) {
2246 res
->name
.GSS_BUFFER_T_val
= NULL
;
2247 res
->name_type
.GSS_OID_val
= NULL
;
2248 res
->mechanisms
.GSS_OID_SET_val
= NULL
;
2252 /* set the uid sent as the RPC argument */
2257 cred_handle
= (argp
->cred_handle
.GSS_CRED_ID_T_len
== 0 ?
2258 GSS_C_NO_CREDENTIAL
:
2260 *((gss_cred_id_t
*)argp
->cred_handle
.
2261 GSS_CRED_ID_T_val
));
2263 /* call the gssapi routine */
2265 res
->status
= (OM_uint32
)gss_inquire_cred(&res
->minor_status
,
2272 if (res
->status
!= GSS_S_COMPLETE
) {
2273 syslog_gss_error(res
->status
, res
->minor_status
,
2278 /* convert the returned name from internal to external format */
2280 if (gss_display_name(&minor_status
, internal_name
,
2281 &external_name
, &name_type
)
2282 != GSS_S_COMPLETE
) {
2284 res
->status
= (OM_uint32
)GSS_S_FAILURE
;
2285 res
->minor_status
= minor_status
;
2287 gss_release_name(&minor_status
, &internal_name
);
2289 if (mechanisms
!= GSS_C_NULL_OID_SET
) {
2290 for (i
= 0; i
< mechanisms
->count
; i
++)
2291 free(mechanisms
->elements
[i
].elements
);
2292 free(mechanisms
->elements
);
2300 * convert the output args from the parameter given in the call to the
2301 * variable in the XDR result
2305 res
->name
.GSS_BUFFER_T_len
= (uint_t
)external_name
.length
;
2306 res
->name
.GSS_BUFFER_T_val
= (void *)external_name
.value
;
2309 * we have to allocate storage for name_type here, since the value
2310 * returned from gss_display_name points to the underlying mechanism
2311 * static storage. If we didn't allocate storage, the next time
2312 * through this routine, the xdr_free() call at the beginning would
2313 * try to free up that static storage.
2316 res
->name_type
.GSS_OID_len
= (uint_t
)name_type
->length
;
2317 res
->name_type
.GSS_OID_val
= (void *)malloc(name_type
->length
);
2318 if (!res
->name_type
.GSS_OID_val
) {
2319 return (GSS_S_FAILURE
);
2321 memcpy(res
->name_type
.GSS_OID_val
, name_type
->elements
,
2324 if (mechanisms
!= GSS_C_NULL_OID_SET
) {
2325 res
->mechanisms
.GSS_OID_SET_len
=
2326 (uint_t
)mechanisms
->count
;
2327 res
->mechanisms
.GSS_OID_SET_val
= (GSS_OID
*)
2328 malloc(sizeof (GSS_OID
) * mechanisms
->count
);
2329 if (!res
->mechanisms
.GSS_OID_SET_val
) {
2330 free(res
->name_type
.GSS_OID_val
);
2331 return (GSS_S_FAILURE
);
2333 for (i
= 0; i
< mechanisms
->count
; i
++) {
2334 res
->mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_len
=
2335 (uint_t
)mechanisms
->elements
[i
].length
;
2336 res
->mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_val
=
2337 (char *)malloc(mechanisms
->elements
[i
].
2339 if (!res
->mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_val
) {
2340 free(res
->name_type
.GSS_OID_val
);
2341 for (j
= 0; j
< i
; j
++) {
2342 free(res
->mechanisms
.
2343 GSS_OID_SET_val
[i
].GSS_OID_val
);
2345 free(res
->mechanisms
.GSS_OID_SET_val
);
2346 return (GSS_S_FAILURE
);
2348 memcpy(res
->mechanisms
.GSS_OID_SET_val
[i
].GSS_OID_val
,
2349 mechanisms
->elements
[i
].elements
,
2350 mechanisms
->elements
[i
].length
);
2353 res
->mechanisms
.GSS_OID_SET_len
= 0;
2355 /* release the space allocated for internal_name and mechanisms */
2356 gss_release_name(&minor_status
, &internal_name
);
2358 if (mechanisms
!= GSS_C_NULL_OID_SET
) {
2359 for (i
= 0; i
< mechanisms
->count
; i
++)
2360 free(mechanisms
->elements
[i
].elements
);
2361 free(mechanisms
->elements
);
2365 /* return to caller */
2371 gss_inquire_cred_by_mech_1_svc(argp
, res
, rqstp
)
2372 gss_inquire_cred_by_mech_arg
*argp
;
2373 gss_inquire_cred_by_mech_res
*res
;
2374 struct svc_req
*rqstp
;
2379 gss_cred_id_t cred_handle
;
2380 gss_OID_desc mech_type_desc
;
2381 gss_OID mech_type
= &mech_type_desc
;
2383 memset(res
, 0, sizeof (*res
));
2386 fprintf(stderr
, gettext("gss_inquire_cred\n"));
2388 /* verify the verifier_cred_handle */
2390 if (argp
->gssd_cred_verifier
!= gssd_time_verf
) {
2391 res
->status
= (OM_uint32
) GSS_S_DEFECTIVE_CREDENTIAL
;
2392 res
->minor_status
= 0;
2397 * if the request isn't from root, null out the result pointer
2398 * entries, so the next time through xdr_free won't try to
2399 * free unmalloc'd memory and then return NULL
2402 if (checkfrom(rqstp
, &uid
) == 0) {
2406 /* set the uid sent as the RPC argument */
2411 cred_handle
= (argp
->cred_handle
.GSS_CRED_ID_T_len
== 0 ?
2412 GSS_C_NO_CREDENTIAL
:
2414 *((gss_cred_id_t
*)argp
->cred_handle
.
2415 GSS_CRED_ID_T_val
));
2417 /* call the gssapi routine */
2419 if (argp
->mech_type
.GSS_OID_len
== 0)
2420 mech_type
= GSS_C_NULL_OID
;
2423 (OM_uint32
)argp
->mech_type
.GSS_OID_len
;
2424 mech_type
->elements
=
2425 (void *)malloc(mech_type
->length
);
2426 if (!mech_type
->elements
) {
2427 return (GSS_S_FAILURE
);
2429 memcpy(mech_type
->elements
,
2430 argp
->mech_type
.GSS_OID_val
,
2433 res
->status
= (OM_uint32
)gss_inquire_cred_by_mech(
2434 &res
->minor_status
, cred_handle
,
2435 mech_type
, NULL
, NULL
,
2438 /* return to caller */
2444 gsscred_name_to_unix_cred_1_svc(argsp
, res
, rqstp
)
2445 gsscred_name_to_unix_cred_arg
*argsp
;
2446 gsscred_name_to_unix_cred_res
*res
;
2447 struct svc_req
*rqstp
;
2452 gss_buffer_desc gssBuf
= GSS_C_EMPTY_BUFFER
;
2455 gid_t
*gids
, gidOut
;
2458 fprintf(stderr
, gettext("gsscred_name_to_unix_cred\n"));
2460 memset(res
, 0, sizeof (*res
));
2463 * check the request originator
2465 if (checkfrom(rqstp
, &uid
) == 0)
2468 /* set the uid from the rpc request */
2473 * convert the principal name to gss internal format
2474 * need not malloc the input parameters
2476 gssBuf
.length
= argsp
->pname
.GSS_BUFFER_T_len
;
2477 gssBuf
.value
= (void*)argsp
->pname
.GSS_BUFFER_T_val
;
2478 oid
.length
= argsp
->name_type
.GSS_OID_len
;
2479 oid
.elements
= (void*)argsp
->name_type
.GSS_OID_val
;
2481 res
->major
= gss_import_name(&minor
, &gssBuf
, &oid
, &gssName
);
2482 if (res
->major
!= GSS_S_COMPLETE
)
2485 /* retrieve the mechanism type from the arguments */
2486 oid
.length
= argsp
->mech_type
.GSS_OID_len
;
2487 oid
.elements
= (void*)argsp
->mech_type
.GSS_OID_val
;
2489 /* call the gss extensions to map the principal name to unix creds */
2490 res
->major
= gsscred_name_to_unix_cred(gssName
, &oid
, &uid
, &gidOut
,
2492 gss_release_name(&minor
, &gssName
);
2494 if (res
->major
== GSS_S_COMPLETE
) {
2497 res
->gids
.GSSCRED_GIDS_val
= gids
;
2498 res
->gids
.GSSCRED_GIDS_len
= gidsLen
;
2502 } /* gsscred_name_to_unix_cred_svc_1 */
2505 gsscred_expname_to_unix_cred_1_svc(argsp
, res
, rqstp
)
2506 gsscred_expname_to_unix_cred_arg
*argsp
;
2507 gsscred_expname_to_unix_cred_res
*res
;
2508 struct svc_req
*rqstp
;
2511 gss_buffer_desc expName
= GSS_C_EMPTY_BUFFER
;
2513 gid_t
*gids
, gidOut
;
2516 fprintf(stderr
, gettext("gsscred_expname_to_unix_cred\n"));
2518 memset(res
, 0, sizeof (*res
));
2521 * check the request originator
2523 if (checkfrom(rqstp
, &uid
) == 0)
2526 /* set the uid from the rpc request */
2531 * extract the export name from arguments
2532 * need not malloc the input parameters
2534 expName
.length
= argsp
->expname
.GSS_BUFFER_T_len
;
2535 expName
.value
= (void*)argsp
->expname
.GSS_BUFFER_T_val
;
2537 res
->major
= gsscred_expname_to_unix_cred(&expName
, &uid
,
2538 &gidOut
, &gids
, &gidsLen
);
2540 if (res
->major
== GSS_S_COMPLETE
) {
2543 res
->gids
.GSSCRED_GIDS_val
= gids
;
2544 res
->gids
.GSSCRED_GIDS_len
= gidsLen
;
2548 } /* gsscred_expname_to_unix_cred_1_svc */
2551 gss_get_group_info_1_svc(argsp
, res
, rqstp
)
2552 gss_get_group_info_arg
*argsp
;
2553 gss_get_group_info_res
*res
;
2554 struct svc_req
*rqstp
;
2558 gid_t
*gids
, gidOut
;
2561 fprintf(stderr
, gettext("gss_get_group_info\n"));
2563 memset(res
, 0, sizeof (*res
));
2566 * check the request originator
2568 if (checkfrom(rqstp
, &uid
) == 0)
2571 /* set the uid from the rpc request */
2576 * extract the uid from the arguments
2579 res
->major
= gss_get_group_info(uid
, &gidOut
, &gids
, &gidsLen
);
2580 if (res
->major
== GSS_S_COMPLETE
) {
2582 res
->gids
.GSSCRED_GIDS_val
= gids
;
2583 res
->gids
.GSSCRED_GIDS_len
= gidsLen
;
2587 } /* gss_get_group_info_1_svc */
2591 gss_get_kmod_1_svc(argsp
, res
, rqstp
)
2592 gss_get_kmod_arg
*argsp
;
2593 gss_get_kmod_res
*res
;
2594 struct svc_req
*rqstp
;
2600 fprintf(stderr
, gettext("gss_get_kmod\n"));
2602 res
->module_follow
= FALSE
;
2603 oid
.length
= argsp
->mech_oid
.GSS_OID_len
;
2604 oid
.elements
= (void *)argsp
->mech_oid
.GSS_OID_val
;
2605 kmodName
= __gss_get_kmodName(&oid
);
2607 if (kmodName
!= NULL
) {
2608 res
->module_follow
= TRUE
;
2609 res
->gss_get_kmod_res_u
.modname
= kmodName
;
2616 * Returns 1 if caller is ok, else 0.
2617 * If caller ok, the uid is returned in uidp.
2620 checkfrom(rqstp
, uidp
)
2621 struct svc_req
*rqstp
;
2624 SVCXPRT
*xprt
= rqstp
->rq_xprt
;
2625 struct authunix_parms
*aup
;
2628 /* check client agent uid to ensure it is privileged */
2629 if (__rpc_get_local_uid(xprt
, &uid
) < 0) {
2630 syslog(LOG_ERR
, gettext("__rpc_get_local_uid failed %s %s"),
2631 xprt
->xp_netid
, xprt
->xp_tp
);
2635 fprintf(stderr
, gettext("checkfrom: local_uid %d\n"), uid
);
2638 gettext("checkfrom: caller (uid %d) not privileged"),
2644 * Request came from local privileged process.
2645 * Proceed to get uid of client if needed by caller.
2648 if (rqstp
->rq_cred
.oa_flavor
!= AUTH_SYS
) {
2649 syslog(LOG_ERR
, gettext("checkfrom: not UNIX credentials"));
2652 CTASSERT(sizeof (struct authunix_parms
) <= RQCRED_SIZE
);
2654 aup
= (struct authunix_parms
*)rqstp
->rq_clntcred
;
2655 *uidp
= aup
->aup_uid
;
2658 gettext("checkfrom: caller's uid %d\n"), *uidp
);
2664 svcerr_weakauth(xprt
);