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 2017 Joyent Inc
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * RPC server procedures for the gssapi usermode daemon gssd.
28 */
29
30 #include <stdio.h>
31 #include <stdio_ext.h>
32 #include <unistd.h>
33 #include <pwd.h>
34 #include <grp.h>
35 #include <strings.h>
36 #include <limits.h>
37 #include <sys/param.h>
38 #include <mechglueP.h>
39 #include "gssd.h"
40 #include <gssapi/gssapi.h>
41 #include <rpc/rpc.h>
42 #include <stdlib.h>
43 #include <syslog.h>
44 #include <sys/resource.h>
45 #include <sys/debug.h>
46
47 #define SRVTAB ""
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 */
51
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 */
55
56 struct gssd_ctx_slot {
57 struct gssd_ctx_slot *lru_next;
58 struct gssd_ctx_slot *lru_prev;
59 bool_t inuse;
60 OM_uint32 create_time;
61 OM_uint32 verf;
62 gss_ctx_id_t ctx;
63 gss_ctx_id_t rpcctx;
64 };
65
66 struct gssd_ctx_slot *gssd_ctx_slot_tbl;
67 struct gssd_ctx_slot *gssd_lru_head;
68
69 static int max_contexts;
70
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 *);
74
75 /*
76 * Syslog (and output to stderr if debug set) the GSSAPI major
77 * and minor numbers.
78 */
79 static void
syslog_gss_error(OM_uint32 maj_stat,OM_uint32 min_stat,char * errstr)80 syslog_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *errstr)
81 {
82 OM_uint32 gmaj_stat, gmin_stat;
83 gss_buffer_desc msg;
84 OM_uint32 msg_ctx = 0;
85
86
87 if (gssd_debug)
88 fprintf(stderr,
89 "gssd: syslog_gss_err: called from %s: maj=%d min=%d\n",
90 errstr ? errstr : "<null>", maj_stat, min_stat);
91
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,
95 GSS_C_GSS_CODE,
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);
101 if (gssd_debug)
102 (void) fprintf(stderr,
103 "gssd: GSSAPI error major: %s\n",
104 (char *)msg.value);
105
106 (void) gss_release_buffer(&gmin_stat, &msg);
107 }
108
109 /* Print the minor status error from the mech. */
110 msg_ctx = 0;
111 /* msg_ctx - skip the check for it as is probably unnecesary */
112 gmaj_stat = gss_display_status(&gmin_stat, min_stat,
113 GSS_C_MECH_CODE,
114 GSS_C_NULL_OID,
115 &msg_ctx, &msg);
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",
120 (char *)msg.value);
121 if (gssd_debug)
122 (void) fprintf(stderr,
123 "gssd: GSSAPI error minor: %s\n",
124 (char *)msg.value);
125 (void) gss_release_buffer(&gmin_stat, &msg);
126 }
127 }
128
129 void
gssd_setup(char * arg)130 gssd_setup(char *arg)
131 {
132 int i;
133 struct rlimit rl;
134 hrtime_t high_res_time;
135
136 gssd_time_verf = (OM_uint32)time(NULL);
137 max_contexts = FDCACHE_DEFAULT;
138
139 /*
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.
143 */
144 high_res_time = gethrtime();
145 context_verf = (OM_uint32)high_res_time;
146
147 /*
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.
152 */
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);
159 }
160
161 gssd_ctx_slot_tbl = (struct gssd_ctx_slot *)
162 malloc(sizeof (struct gssd_ctx_slot) * max_contexts);
163
164 if (gssd_ctx_slot_tbl == NULL) {
165 (void) fprintf(stderr,
166 gettext("[%s] could not allocate %d byte context table"
167 "\n"), arg,
168 (sizeof (struct gssd_ctx_slot) * max_contexts));
169 exit(1);
170 }
171
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);
179 }
180
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;
187
188 gssd_lru_head = &gssd_ctx_slot_tbl[0];
189 }
190
191 static OM_uint32 syslog_interval = 60;
192
193 static struct gssd_ctx_slot *
gssd_alloc_slot(gss_ctx_id_t ctx)194 gssd_alloc_slot(gss_ctx_id_t ctx)
195 {
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;
200 static int tooks;
201 OM_uint32 minor_status;
202
203 lru = gssd_lru_head;
204 gssd_lru_head = lru->lru_next;
205
206 current_time = (OM_uint32) time(NULL);
207
208 if (last_syslog == 0)
209 last_syslog = current_time; /* Save 1st alloc time */
210
211 if (lru->inuse) {
212 if (lru->ctx != GSS_C_NO_CONTEXT)
213 (void) gss_delete_sec_context(&minor_status,
214 &lru->ctx, NULL);
215 tooks++;
216
217 if (((current_time - last_syslog) > syslog_interval) ||
218 first_take) {
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);
224
225 last_syslog = current_time;
226 tooks = 0;
227 first_take = FALSE;
228 }
229 }
230
231 /*
232 * Assign the next context verifier to the context (avoiding zero).
233 */
234 context_verf++;
235 if (context_verf == 0)
236 context_verf = 1;
237 lru->verf = context_verf;
238
239 lru->create_time = current_time;
240 lru->ctx = ctx;
241 lru->inuse = TRUE;
242 return (lru);
243 }
244
245 /*
246 * We always add 1 because we don't want slot 0 to be confused
247 * with GSS_C_NO_CONTEXT.
248 */
249
250 static struct gssd_ctx_slot *
gssd_handle_to_slot(GSS_CTX_ID_T * h)251 gssd_handle_to_slot(GSS_CTX_ID_T *h)
252 {
253 intptr_t i;
254
255 if (h->GSS_CTX_ID_T_len == 0) {
256 return (NULL);
257 }
258 if (h->GSS_CTX_ID_T_len != sizeof (i))
259 return (NULL);
260
261 i = (*(intptr_t *)(h->GSS_CTX_ID_T_val)) - 1;
262
263 if (i < 0 || i >= max_contexts)
264 return (NULL);
265
266 return (&gssd_ctx_slot_tbl[i]);
267 }
268
269 static void
gssd_rel_slot(struct gssd_ctx_slot * lru)270 gssd_rel_slot(struct gssd_ctx_slot *lru)
271 {
272 struct gssd_ctx_slot *prev, *next;
273
274 if (lru == NULL)
275 return;
276
277 lru->inuse = FALSE;
278
279 /*
280 * Remove entry from its current location in list
281 */
282 prev = lru->lru_prev;
283 next = lru->lru_next;
284 prev->lru_next = next;
285 next->lru_prev = prev;
286
287 /*
288 * Since it is no longer in use, it is the least recently
289 * used.
290 */
291 prev = gssd_lru_head->lru_prev;
292 next = gssd_lru_head;
293
294 prev->lru_next = lru;
295 lru->lru_prev = prev;
296
297 next->lru_prev = lru;
298 lru->lru_next = next;
299
300 gssd_lru_head = lru;
301 }
302
303 static void
gssd_convert_context_handle(GSS_CTX_ID_T * h,gss_ctx_id_t * context_handle,OM_uint32 verf,bool_t * context_verf_ok,struct gssd_ctx_slot ** slotp)304 gssd_convert_context_handle(GSS_CTX_ID_T *h,
305 gss_ctx_id_t *context_handle,
306 OM_uint32 verf,
307 bool_t *context_verf_ok,
308 struct gssd_ctx_slot **slotp)
309 {
310 struct gssd_ctx_slot *slot;
311
312 *context_verf_ok = FALSE;
313 *context_handle = (gss_ctx_id_t)1;
314 if (slotp != NULL)
315 *slotp = NULL;
316
317 if (h->GSS_CTX_ID_T_len == 0) {
318 *context_handle = GSS_C_NO_CONTEXT;
319 *context_verf_ok = TRUE;
320 return;
321 }
322
323 slot = gssd_handle_to_slot(h);
324
325 if (slot == NULL)
326 return;
327
328 if (verf != slot->verf)
329 return;
330
331 *context_verf_ok = TRUE;
332 *context_handle = slot->ctx;
333 if (slotp != NULL)
334 *slotp = slot;
335 }
336
337 bool_t
gss_acquire_cred_1_svc(argp,res,rqstp)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;
342 {
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;
347 OM_uint32 time_req;
348 gss_OID_set_desc desired_mechs_desc;
349 gss_OID_set desired_mechs;
350 int cred_usage;
351 gss_cred_id_t output_cred_handle;
352 gss_OID_set actual_mechs;
353 gss_buffer_desc external_name;
354 uid_t uid;
355 int i, j;
356
357 if (gssd_debug)
358 fprintf(stderr, gettext("gss_acquire_cred\n"));
359
360 memset(res, 0, sizeof (*res));
361
362 /*
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
366 */
367
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;
371 return (FALSE);
372 }
373
374 /* set the uid sent as the RPC argument */
375
376 uid = argp->uid;
377 set_gssd_uid(uid);
378
379 /* convert the desired name from external to internal format */
380
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);
387
388 if (argp->name_type.GSS_OID_len == 0) {
389 name_type = GSS_C_NULL_OID;
390 } else {
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);
396 }
397 memcpy(name_type->elements, argp->name_type.GSS_OID_val,
398 name_type->length);
399 }
400
401 if (gss_import_name(&minor_status, &external_name, name_type,
402 &desired_name) != GSS_S_COMPLETE) {
403
404 res->status = (OM_uint32) GSS_S_FAILURE;
405 res->minor_status = minor_status;
406
407 free(external_name.value);
408 if (name_type != GSS_C_NULL_OID)
409 free(name_type->elements);
410
411 return (TRUE);
412 }
413
414 /*
415 * copy the XDR structured arguments into their corresponding local GSSAPI
416 * variables.
417 */
418
419 cred_usage = argp->cred_usage;
420 time_req = argp->time_req;
421
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);
432 }
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].
439 length);
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++) {
444 free
445 (desired_mechs->elements[j].elements);
446 }
447 free(desired_mechs->elements);
448 return (GSS_S_FAILURE);
449 }
450 memcpy(desired_mechs->elements[i].elements,
451 argp->desired_mechs.GSS_OID_SET_val[i].
452 GSS_OID_val,
453 desired_mechs->elements[i].length);
454 }
455 } else
456 desired_mechs = GSS_C_NULL_OID_SET;
457
458 /* call the gssapi routine */
459
460 res->status = (OM_uint32)gss_acquire_cred(&res->minor_status,
461 desired_name,
462 time_req,
463 desired_mechs,
464 cred_usage,
465 &output_cred_handle,
466 &actual_mechs,
467 &res->time_rec);
468
469 /*
470 * convert the output args from the parameter given in the call to the
471 * variable in the XDR result
472 */
473
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);
482 }
483 free(desired_mechs->elements);
484 return (GSS_S_FAILURE);
485 }
486 memcpy(res->output_cred_handle.GSS_CRED_ID_T_val, &output_cred_handle,
487 sizeof (gss_cred_id_t));
488
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);
499 }
500 free(desired_mechs->elements);
501 free(res->output_cred_handle.GSS_CRED_ID_T_val);
502 return (GSS_S_FAILURE);
503 }
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].
509 length);
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++) {
515 free
516 (desired_mechs->elements[i].elements);
517 }
518 free(res->actual_mechs.GSS_OID_SET_val);
519 for (j = 0; j < (i - 1); j++) {
520 free
521 (res->actual_mechs.
522 GSS_OID_SET_val[j].GSS_OID_val);
523 }
524 return (GSS_S_FAILURE);
525 }
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);
529 }
530 } else
531 res->actual_mechs.GSS_OID_SET_len = 0;
532
533 /*
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)
538 */
539
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) {
543 sleep(1);
544 gssd_time_verf = (OM_uint32)time(NULL);
545 }
546 res->gssd_cred_verifier = gssd_time_verf;
547 } else
548 syslog_gss_error(res->status, res->minor_status,
549 "acquire_cred");
550
551 /*
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
555 */
556
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);
561
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);
566 free(actual_mechs);
567 }
568
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);
573
574 }
575
576 /* return to caller */
577
578 return (TRUE);
579 }
580
581 bool_t
gss_add_cred_1_svc(argp,res,rqstp)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;
586 {
587
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;
594 int cred_usage;
595 gss_cred_id_t input_cred_handle;
596 gss_OID_set actual_mechs;
597 gss_buffer_desc external_name;
598 uid_t uid;
599 int i, j;
600
601 if (gssd_debug)
602 fprintf(stderr, gettext("gss_add_cred\n"));
603
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"));
612 return (TRUE);
613 }
614 memset(res, 0, sizeof (*res));
615
616 /*
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
620 */
621
622 if (checkfrom(rqstp, &uid) == 0) {
623 return (FALSE);
624 }
625
626 /* set the uid sent as the RPC argument */
627
628 uid = argp->uid;
629 set_gssd_uid(uid);
630
631 /* convert the desired name from external to internal format */
632
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;
637
638 if (gss_import_name(&minor_status, &external_name, name_type,
639 &desired_name) != GSS_S_COMPLETE) {
640
641 if (gssd_debug)
642 fprintf(stderr,
643 gettext("gss_add_cred:import name"),
644 gettext(" failed status %d \n"),
645 res->status);
646 res->status = (OM_uint32)GSS_S_FAILURE;
647 res->minor_status = minor_status;
648 return (TRUE);
649 }
650
651 /*
652 * copy the XDR structured arguments into their corresponding local GSSAPI
653 * variables.
654 */
655
656 cred_usage = argp->cred_usage;
657 if (argp->desired_mech_type.GSS_OID_len == 0)
658 desired_mech_type = GSS_C_NULL_OID;
659 else {
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);
666 }
667 memcpy(desired_mech_type->elements,
668 argp->desired_mech_type.GSS_OID_val,
669 desired_mech_type->length);
670 }
671 input_cred_handle =
672 (argp->input_cred_handle.GSS_CRED_ID_T_len == 0 ?
673 GSS_C_NO_CREDENTIAL :
674 /*LINTED*/
675 *((gss_cred_id_t *)argp->input_cred_handle.
676 GSS_CRED_ID_T_val));
677
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;
683 return (TRUE);
684 }
685
686 /* call the gssapi routine */
687
688 res->status = (OM_uint32)gss_add_cred(&res->minor_status,
689 input_cred_handle,
690 desired_name,
691 desired_mech_type,
692 cred_usage,
693 argp->initiator_time_req,
694 argp->acceptor_time_req,
695 NULL,
696 &actual_mechs,
697 &res->initiator_time_rec,
698 &res->acceptor_time_rec);
699
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");
703
704 /*
705 * convert the output args from the parameter given in the call to the
706 * variable in the XDR result
707 */
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);
717 }
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].
723 length);
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++) {
729 free
730 (res->actual_mechs.
731 GSS_OID_SET_val[j].GSS_OID_val);
732 }
733 return (GSS_S_FAILURE);
734 }
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);
738 }
739 } else
740 res->actual_mechs.GSS_OID_SET_len = 0;
741
742 /*
743 * now release the space allocated for
744 * desired_name and desired_mech_type
745 */
746
747 gss_release_name(&minor_status, &desired_name);
748 free(desired_mech_type->elements);
749 gss_release_oid_set(&minor_status, &actual_mechs);
750 /*
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);
756 * }
757 */
758
759
760 /* return to caller */
761
762 return (TRUE);
763 }
764
765 bool_t
gss_release_cred_1_svc(argp,res,rqstp)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;
770 {
771
772 uid_t uid;
773 gss_cred_id_t cred_handle;
774
775 memset(res, 0, sizeof (*res));
776
777 if (gssd_debug)
778 fprintf(stderr, gettext("gss_release_cred\n"));
779
780 if (checkfrom(rqstp, &uid) == 0)
781 return (FALSE);
782
783 /* set the uid sent as the RPC argument */
784
785 uid = argp->uid;
786 set_gssd_uid(uid);
787
788 /*
789 * if the cred_handle verifier is not correct,
790 * set status to GSS_S_DEFECTIVE_CREDENTIAL and return
791 */
792
793 if (argp->gssd_cred_verifier != gssd_time_verf) {
794 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
795 return (TRUE);
796 }
797
798 /*
799 * if the cred_handle length is 0
800 * set cred_handle argument to GSS_S_NO_CREDENTIAL
801 */
802
803 if (argp->cred_handle.GSS_CRED_ID_T_len == 0)
804 cred_handle = GSS_C_NO_CREDENTIAL;
805 else
806 cred_handle =
807 (gss_cred_id_t)argp->cred_handle.GSS_CRED_ID_T_val;
808
809 /* call the gssapi routine */
810
811 res->status = (OM_uint32)gss_release_cred(&res->minor_status,
812 &cred_handle);
813
814 /* return to caller */
815
816 return (TRUE);
817 }
818
819 bool_t
gss_init_sec_context_1_svc(argp,res,rqstp)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;
824 {
825
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;
834
835 gss_OID_desc mech_type_desc;
836 gss_OID mech_type = &mech_type_desc;
837 struct gss_channel_bindings_struct
838 input_chan_bindings;
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;
845
846 uid_t uid;
847
848 memset(res, 0, sizeof (*res));
849
850 if (gssd_debug)
851 fprintf(stderr, gettext("gss_init_sec_context\n"));
852
853 /*
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
857 */
858
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;
863 return (FALSE);
864 }
865
866 /* set the uid sent as the RPC argument */
867
868 uid = argp->uid;
869 set_gssd_uid(uid);
870
871 /*
872 * copy the supplied context handle into the local context handle, so it
873 * can be supplied to the gss_init_sec_context call
874 */
875
876 gssd_convert_context_handle(&argp->context_handle, &context_handle,
877 argp->gssd_context_verifier, &context_verf_ok, &slot);
878
879 claimant_cred_handle =
880 (argp->claimant_cred_handle.GSS_CRED_ID_T_len == 0 ?
881 GSS_C_NO_CREDENTIAL :
882 /*LINTED*/
883 *((gss_cred_id_t *)argp->claimant_cred_handle.
884 GSS_CRED_ID_T_val));
885
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;
897 return (TRUE);
898 }
899 }
900
901 if (context_handle != GSS_C_NO_CONTEXT) {
902 /* verify the verifier_context_handle */
903
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;
913 return (TRUE);
914 }
915 }
916
917 /* convert the target name from external to internal format */
918
919 external_name.length = argp->target_name.GSS_BUFFER_T_len;
920 external_name.value = (void *)argp->target_name.GSS_BUFFER_T_val;
921
922 if (argp->name_type.GSS_OID_len == 0) {
923 name_type = GSS_C_NULL_OID;
924 } else {
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,
930 name_type->length);
931 }
932
933 if (argp->mech_type.GSS_OID_len == 0)
934 mech_type = GSS_C_NULL_OID;
935 else {
936 mech_type->length = (OM_uint32)argp->mech_type.GSS_OID_len;
937 mech_type->elements = (void *)argp->mech_type.GSS_OID_val;
938 }
939
940 if (gss_import_name(&minor_status, &external_name, name_type,
941 &internal_name) != GSS_S_COMPLETE) {
942
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;
947
948 return (TRUE);
949 }
950 /*
951 * copy the XDR structured arguments into their corresponding local GSSAPI
952 * variables.
953 */
954
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.
959 initiator_addrtype;
960 input_chan_bindings.initiator_address.length =
961 (uint_t)argp->input_chan_bindings.initiator_address.
962 GSS_BUFFER_T_len;
963 input_chan_bindings.initiator_address.value =
964 (void *)argp->input_chan_bindings.initiator_address.
965 GSS_BUFFER_T_val;
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.
970 GSS_BUFFER_T_len;
971 input_chan_bindings.acceptor_address.value =
972 (void *)argp->input_chan_bindings.acceptor_address.
973 GSS_BUFFER_T_val;
974 input_chan_bindings.application_data.length =
975 (uint_t)argp->input_chan_bindings.application_data.
976 GSS_BUFFER_T_len;
977 input_chan_bindings.application_data.value =
978 (void *)argp->input_chan_bindings.application_data.
979 GSS_BUFFER_T_val;
980 } else {
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;
990 }
991
992 if (argp->input_token.GSS_BUFFER_T_len == 0) {
993 input_token_ptr = GSS_C_NO_BUFFER;
994 } else {
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;
999 }
1000
1001 /* call the gssapi routine */
1002
1003 res->status = (OM_uint32)gss_init_sec_context(&res->minor_status,
1004 (gss_cred_id_t)argp->claimant_cred_handle.
1005 GSS_CRED_ID_T_val,
1006 &context_handle,
1007 internal_name,
1008 mech_type,
1009 argp->req_flags,
1010 argp->time_req,
1011 input_chan_bindings_ptr,
1012 input_token_ptr,
1013 &actual_mech_type,
1014 &output_token,
1015 &res->ret_flags,
1016 &res->time_rec);
1017
1018 /*
1019 * convert the output args from the parameter given in the call to the
1020 * variable in the XDR result
1021 */
1022
1023 if (res->status == (OM_uint32)GSS_S_COMPLETE ||
1024 res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
1025
1026 if (slot == NULL || slot->ctx != context_handle) {
1027 /*
1028 * Note that gssd_alloc_slot() will delete ctx's as long
1029 * as we don't call gssd_rel_slot().
1030 */
1031 slot = gssd_alloc_slot(context_handle);
1032 }
1033
1034 res->gssd_context_verifier = slot->verf;
1035
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);
1042 }
1043
1044 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1045 sizeof (gss_ctx_id_t));
1046
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;
1051
1052 /*
1053 * the actual mech type parameter
1054 * is ready only upon GSS_S_COMPLETE
1055 */
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);
1065 }
1066 memcpy(res->actual_mech_type.GSS_OID_val,
1067 (char *)actual_mech_type->elements,
1068 actual_mech_type->length);
1069 } else
1070 res->actual_mech_type.GSS_OID_len = 0;
1071 } else {
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);
1077 }
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;
1081 }
1082
1083 /*
1084 * now release the space allocated by the underlying gssapi mechanism
1085 * library for internal_name and for the name_type.
1086 */
1087
1088 gss_release_name(&minor_status, &internal_name);
1089 if (name_type != GSS_C_NULL_OID)
1090 free(name_type->elements);
1091
1092
1093 /* return to caller */
1094 return (TRUE);
1095 }
1096
1097 bool_t
gss_accept_sec_context_1_svc(argp,res,rqstp)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;
1102 {
1103 uid_t uid;
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;
1109
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;
1115 gss_OID mech_type;
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;
1120
1121 memset(res, 0, sizeof (*res));
1122
1123 if (gssd_debug)
1124 fprintf(stderr, gettext("gss_accept_sec_context\n"));
1125
1126 /*
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
1130 */
1131
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;
1138 return (FALSE);
1139 }
1140
1141 /* set the uid sent as the RPC argument */
1142
1143 uid = argp->uid;
1144 set_gssd_uid(uid);
1145
1146 /*
1147 * copy the supplied context handle into the local context handle, so
1148 * it can be supplied to the gss_accept_sec_context call
1149 */
1150
1151 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1152 argp->gssd_context_verifier, &context_verf_ok, &slot);
1153
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;
1169 return (TRUE);
1170 }
1171
1172 /*
1173 * copy the XDR structured arguments into their corresponding local
1174 * GSSAPI variable equivalents.
1175 */
1176
1177
1178 verifier_cred_handle =
1179 (argp->verifier_cred_handle.GSS_CRED_ID_T_len == 0 ?
1180 GSS_C_NO_CREDENTIAL :
1181 /*LINTED*/
1182 *((gss_cred_id_t *)argp->verifier_cred_handle.
1183 GSS_CRED_ID_T_val));
1184
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;
1200 return (TRUE);
1201 }
1202
1203 input_token_buffer_ptr = &input_token_buffer;
1204 input_token_buffer.length = (size_t)argp->input_token_buffer.
1205 GSS_BUFFER_T_len;
1206 input_token_buffer.value = (void *)argp->input_token_buffer.
1207 GSS_BUFFER_T_val;
1208
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.
1213 initiator_addrtype;
1214 input_chan_bindings.initiator_address.length =
1215 (uint_t)argp->input_chan_bindings.initiator_address.
1216 GSS_BUFFER_T_len;
1217 input_chan_bindings.initiator_address.value =
1218 (void *)argp->input_chan_bindings.initiator_address.
1219 GSS_BUFFER_T_val;
1220 input_chan_bindings.acceptor_addrtype =
1221 (OM_uint32)argp->input_chan_bindings.
1222 acceptor_addrtype;
1223 input_chan_bindings.acceptor_address.length =
1224 (uint_t)argp->input_chan_bindings.acceptor_address.
1225 GSS_BUFFER_T_len;
1226 input_chan_bindings.acceptor_address.value =
1227 (void *)argp->input_chan_bindings.acceptor_address.
1228 GSS_BUFFER_T_val;
1229 input_chan_bindings.application_data.length =
1230 (uint_t)argp->input_chan_bindings.application_data.
1231 GSS_BUFFER_T_len;
1232 input_chan_bindings.application_data.value =
1233 (void *)argp->input_chan_bindings.application_data.
1234 GSS_BUFFER_T_val;
1235 } else {
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;
1245 }
1246
1247
1248 /* call the gssapi routine */
1249
1250 res->status = (OM_uint32)gss_accept_sec_context(&res->minor_status,
1251 &context_handle,
1252 verifier_cred_handle,
1253 input_token_buffer_ptr,
1254 input_chan_bindings_ptr,
1255 &internal_name,
1256 &mech_type,
1257 &output_token,
1258 &res->ret_flags,
1259 &res->time_rec,
1260 &delegated_cred_handle);
1261
1262 /* convert the src name from internal to external format */
1263
1264 if (res->status == (OM_uint32)GSS_S_COMPLETE ||
1265 res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
1266
1267 /*
1268 * upon GSS_S_CONTINUE_NEEDED only the following
1269 * parameters are ready: minor, ctxt, and output token
1270 */
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;
1277 return (TRUE);
1278 }
1279
1280 if (slot == NULL || slot->ctx != context_handle) {
1281 /*
1282 * Note that gssd_alloc_slot() will delete ctx's as long
1283 * as we don't call gssd_rel_slot().
1284 */
1285 slot = gssd_alloc_slot(context_handle);
1286 }
1287
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;
1291
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;
1296
1297 if (res->status == GSS_S_COMPLETE) {
1298 if (gss_export_name(&minor_status, internal_name,
1299 &external_name)
1300 != GSS_S_COMPLETE) {
1301
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,
1311 &output_token);
1312 res->output_token.GSS_BUFFER_T_len = 0;
1313 res->output_token.GSS_BUFFER_T_val = NULL;
1314 return (TRUE);
1315 }
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;
1320
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,
1331 &external_name);
1332 res->status = (OM_uint32)GSS_S_FAILURE;
1333 res->minor_status = 0;
1334 return (TRUE);
1335 }
1336 memcpy(res->delegated_cred_handle.GSS_CRED_ID_T_val,
1337 &delegated_cred_handle,
1338 sizeof (gss_cred_id_t));
1339
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;
1352 return (TRUE);
1353 }
1354 memcpy(res->mech_type.GSS_OID_val, mech_type->elements,
1355 mech_type->length);
1356
1357 /* release the space allocated for internal_name */
1358 gss_release_name(&minor_status, &internal_name);
1359
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;
1364 }
1365 } else {
1366 syslog_gss_error(res->status, res->minor_status,
1367 "accept_sec_context");
1368
1369 if (context_handle != GSS_C_NO_CONTEXT) {
1370 (void) gss_delete_sec_context(&minor_status,
1371 &context_handle, NULL);
1372 }
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;
1380
1381 res->mech_type.GSS_OID_len = 0;
1382 }
1383
1384 /* return to caller */
1385
1386 return (TRUE);
1387 }
1388
1389 bool_t
gss_process_context_token_1_svc(argp,res,rqstp)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;
1394 {
1395
1396 uid_t uid;
1397 gss_buffer_desc token_buffer;
1398 gss_ctx_id_t context_handle;
1399 bool_t context_verf_ok;
1400
1401 memset(res, 0, sizeof (*res));
1402
1403 if (gssd_debug)
1404 fprintf(stderr, gettext("gss_process_context_token\n"));
1405
1406 if (checkfrom(rqstp, &uid) == 0)
1407 return (FALSE);
1408
1409 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1410 argp->gssd_context_verifier, &context_verf_ok, NULL);
1411
1412 /* verify the context_handle */
1413
1414 if (!context_verf_ok) {
1415 res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1416 res->minor_status = 0;
1417 return (TRUE);
1418 }
1419
1420 /* set the uid sent as the RPC argument */
1421
1422 uid = argp->uid;
1423 set_gssd_uid(uid);
1424
1425 /*
1426 * copy the XDR structured arguments into their corresponding local
1427 * GSSAPI variable equivalents.
1428 */
1429
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;
1432
1433
1434 /* call the gssapi routine */
1435
1436 res->status = (OM_uint32)gss_process_context_token(&res->minor_status,
1437 context_handle,
1438 &token_buffer);
1439
1440 if (GSS_ERROR(res->status))
1441 syslog_gss_error(res->status, res->minor_status,
1442 "process_context_token");
1443
1444 /* return to caller */
1445
1446 return (TRUE);
1447 }
1448
1449 bool_t
gss_delete_sec_context_1_svc(argp,res,rqstp)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;
1454 {
1455 uid_t uid;
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;
1460
1461 memset(res, 0, sizeof (*res));
1462
1463 if (gssd_debug)
1464 fprintf(stderr, gettext("gss_delete_sec_context\n"));
1465
1466
1467 /*
1468 * copy the supplied context handle into the local context handle, so it
1469 * can be supplied to the gss_delete_sec_context call
1470 */
1471 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1472 argp->gssd_context_verifier, &context_verf_ok, &slot);
1473
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;
1482 return (TRUE);
1483 }
1484
1485 /*
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
1489 */
1490
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;
1494 return (FALSE);
1495 }
1496
1497 /* call the gssapi routine */
1498
1499 res->status = (OM_uint32)gss_delete_sec_context(&res->minor_status,
1500 &context_handle,
1501 &output_token);
1502
1503 /*
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
1506 * context handle.
1507 */
1508
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;
1518
1519 if (slot != NULL) {
1520 /*
1521 * gss_delete_sec_context deletes the context if it
1522 * succeeds so clear slot->ctx to avoid a dangling
1523 * reference.
1524 */
1525 slot->ctx = GSS_C_NO_CONTEXT;
1526 gssd_rel_slot(slot);
1527 }
1528 } else {
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);
1534 }
1535
1536 if (slot == NULL || slot->ctx != context_handle) {
1537 /*
1538 * Note that gssd_alloc_slot() will delete ctx's as long
1539 * as we don't call gssd_rel_slot().
1540 */
1541 slot = gssd_alloc_slot(context_handle);
1542 /*
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
1546 * be LRUed out.
1547 */
1548 }
1549
1550 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1551 sizeof (gss_ctx_id_t));
1552
1553 res->output_token.GSS_BUFFER_T_len = 0;
1554 res->output_token.GSS_BUFFER_T_val = NULL;
1555 }
1556
1557 /* return to caller */
1558
1559
1560 return (TRUE);
1561 }
1562
1563
1564 bool_t
gss_export_sec_context_1_svc(argp,res,rqstp)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;
1569 {
1570
1571 uid_t uid;
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;
1576
1577 memset(res, 0, sizeof (*res));
1578
1579 if (gssd_debug)
1580 fprintf(stderr, "gss_export_sec_context\n");
1581
1582 /*
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
1586 */
1587
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;
1591 return (FALSE);
1592 }
1593
1594 /*
1595 * copy the supplied context handle into the local context handle, so it
1596 * can be supplied to the gss_export_sec_context call
1597 */
1598
1599 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1600 argp->gssd_context_verifier, &context_verf_ok, &slot);
1601
1602 /* verify the context_handle */
1603
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() */
1607 return (TRUE);
1608 }
1609
1610 /* call the gssapi routine */
1611
1612 res->status = (OM_uint32)gss_export_sec_context(&res->minor_status,
1613 &context_handle,
1614 &output_token);
1615
1616 /*
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
1619 * handle.
1620 */
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;
1630
1631 if (slot != NULL) {
1632 /*
1633 * gss_export_sec_context deletes the context if it
1634 * succeeds so set slot->ctx to avoid a dangling
1635 * reference.
1636 */
1637 slot->ctx = GSS_C_NO_CONTEXT;
1638 gssd_rel_slot(slot);
1639 }
1640 } else {
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));
1644
1645 if (slot == NULL || slot->ctx != context_handle) {
1646 /*
1647 * Note that gssd_alloc_slot() will delete ctx's as long
1648 * as we don't call gssd_rel_slot().
1649 */
1650 slot = gssd_alloc_slot(context_handle);
1651 /*
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
1655 * be LRUed out.
1656 */
1657 }
1658
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;
1663 }
1664
1665
1666 /* return to caller */
1667
1668 return (TRUE);
1669 }
1670
1671 /*
1672 * This routine doesn't appear to ever be called.
1673 */
1674 bool_t
gss_import_sec_context_1_svc(argp,res,rqstp)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;
1679 {
1680
1681 uid_t uid;
1682 gss_ctx_id_t context_handle;
1683 gss_buffer_desc input_token;
1684 gss_buffer_t input_token_ptr;
1685
1686 memset(res, 0, sizeof (*res));
1687
1688 if (gssd_debug)
1689 fprintf(stderr, "gss_export_sec_context\n");
1690
1691 /*
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
1695 */
1696
1697 if (checkfrom(rqstp, &uid) == 0) {
1698 res->context_handle.GSS_CTX_ID_T_val = NULL;
1699 return (FALSE);
1700 }
1701
1702
1703 if (argp->input_token.GSS_BUFFER_T_len == 0) {
1704 input_token_ptr = GSS_C_NO_BUFFER;
1705 } else {
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;
1710 }
1711
1712
1713 /* call the gssapi routine */
1714
1715 res->status = (OM_uint32) gss_import_sec_context(&res->minor_status,
1716 input_token_ptr,
1717 &context_handle);
1718
1719 /*
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
1722 * handle.
1723 */
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));
1730 } else {
1731 res->context_handle.GSS_CTX_ID_T_len = 0;
1732 res->context_handle.GSS_CTX_ID_T_val = NULL;
1733 }
1734
1735
1736 /* return to caller */
1737
1738 return (TRUE);
1739 }
1740
1741 bool_t
gss_context_time_1_svc(argp,res,rqstp)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;
1746 {
1747 uid_t uid;
1748
1749 memset(res, 0, sizeof (*res));
1750
1751 if (gssd_debug)
1752 fprintf(stderr, gettext("gss_context_time\n"));
1753
1754 /*
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
1758 */
1759
1760 if (checkfrom(rqstp, &uid) == 0)
1761 return (FALSE);
1762
1763 /* set the uid sent as the RPC argument */
1764
1765 uid = argp->uid;
1766 set_gssd_uid(uid);
1767
1768 /* Semantics go here */
1769
1770 return (TRUE);
1771 }
1772
1773 bool_t
gss_sign_1_svc(argp,res,rqstp)1774 gss_sign_1_svc(argp, res, rqstp)
1775 gss_sign_arg *argp;
1776 gss_sign_res *res;
1777 struct svc_req *rqstp;
1778 {
1779
1780 uid_t uid;
1781
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;
1786
1787 memset(res, 0, sizeof (*res));
1788
1789 if (gssd_debug)
1790 fprintf(stderr, gettext("gss_sign\n"));
1791
1792 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1793 argp->gssd_context_verifier, &context_verf_ok, NULL);
1794
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;
1801 return (TRUE);
1802 }
1803
1804
1805 /*
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
1809 */
1810
1811 if (checkfrom(rqstp, &uid) == 0) {
1812 res->msg_token.GSS_BUFFER_T_val = NULL;
1813 return (FALSE);
1814 }
1815
1816 /*
1817 * copy the XDR structured arguments into their corresponding local
1818 * GSSAPI variable equivalents.
1819 */
1820
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;
1823
1824 /* call the gssapi routine */
1825
1826 res->status = (OM_uint32)gss_sign(&res->minor_status,
1827 context_handle,
1828 argp->qop_req,
1829 (gss_buffer_t)&message_buffer,
1830 (gss_buffer_t)&msg_token);
1831 /*
1832 * convert the output args from the parameter given in the call to
1833 * the variable in the XDR result
1834 */
1835
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;
1839 } else
1840 syslog_gss_error(res->status, res->minor_status, "sign");
1841
1842 /* return to caller */
1843
1844 return (TRUE);
1845 }
1846
1847 bool_t
gss_verify_1_svc(argp,res,rqstp)1848 gss_verify_1_svc(argp, res, rqstp)
1849 gss_verify_arg *argp;
1850 gss_verify_res *res;
1851 struct svc_req *rqstp;
1852 {
1853
1854 uid_t uid;
1855
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;
1860
1861 memset(res, 0, sizeof (*res));
1862
1863 if (gssd_debug)
1864 fprintf(stderr, gettext("gss_verify\n"));
1865
1866 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1867 argp->gssd_context_verifier, &context_verf_ok, NULL);
1868
1869 /* verify the context_handle */
1870 if (!context_verf_ok) {
1871 res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1872 res->minor_status = 0;
1873 return (TRUE);
1874 }
1875
1876 /*
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
1880 */
1881
1882 if (checkfrom(rqstp, &uid) == 0)
1883 return (FALSE);
1884
1885 /*
1886 * copy the XDR structured arguments into their corresponding local
1887 * GSSAPI variable equivalents.
1888 */
1889
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;
1892
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;
1895
1896 /* call the gssapi routine */
1897
1898 res->status = (OM_uint32)gss_verify(&res->minor_status,
1899 context_handle,
1900 &message_buffer,
1901 &token_buffer,
1902 &res->qop_state);
1903
1904 if (GSS_ERROR(res->status))
1905 syslog_gss_error(res->status, res->minor_status, "verify");
1906
1907 /* return to caller */
1908 return (TRUE);
1909 }
1910
1911 bool_t
gss_seal_1_svc(argp,res,rqstp)1912 gss_seal_1_svc(argp, res, rqstp)
1913 gss_seal_arg *argp;
1914 gss_seal_res *res;
1915 struct svc_req *rqstp;
1916 {
1917 uid_t uid;
1918
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;
1923
1924 memset(res, 0, sizeof (*res));
1925
1926 if (gssd_debug)
1927 fprintf(stderr, gettext("gss_seal\n"));
1928
1929 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1930 argp->gssd_context_verifier, &context_verf_ok, NULL);
1931
1932 /* verify the context_handle */
1933
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;
1939 return (TRUE);
1940 }
1941
1942 /*
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
1946 */
1947
1948 if (checkfrom(rqstp, &uid) == 0) {
1949 res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1950 return (FALSE);
1951
1952 }
1953
1954
1955 /*
1956 * copy the XDR structured arguments into their corresponding local
1957 * GSSAPI variable equivalents.
1958 */
1959
1960 input_message_buffer.length = (size_t)argp->input_message_buffer.
1961 GSS_BUFFER_T_len;
1962 input_message_buffer.value = (void *)argp->input_message_buffer.
1963 GSS_BUFFER_T_val;
1964
1965
1966 /* call the gssapi routine */
1967
1968 res->status = (OM_uint32)gss_seal(&res->minor_status,
1969 context_handle,
1970 argp->conf_req_flag,
1971 argp->qop_req,
1972 &input_message_buffer,
1973 &res->conf_state,
1974 &output_message_buffer);
1975 /*
1976 * convert the output args from the parameter given in the call to the
1977 * variable in the XDR result
1978 */
1979
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;
1985 } else
1986 syslog_gss_error(res->status, res->minor_status, "seal");
1987
1988 /* return to caller */
1989
1990 return (TRUE);
1991 }
1992
1993 bool_t
gss_unseal_1_svc(argp,res,rqstp)1994 gss_unseal_1_svc(argp, res, rqstp)
1995 gss_unseal_arg *argp;
1996 gss_unseal_res *res;
1997 struct svc_req *rqstp;
1998 {
1999
2000 uid_t uid;
2001
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;
2006
2007 memset(res, 0, sizeof (*res));
2008
2009 if (gssd_debug)
2010 fprintf(stderr, gettext("gss_unseal\n"));
2011
2012 /* verify the context_handle */
2013 gssd_convert_context_handle(&argp->context_handle, &context_handle,
2014 argp->gssd_context_verifier, &context_verf_ok, NULL);
2015
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;
2022 return (TRUE);
2023 }
2024
2025 /*
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
2029 */
2030
2031 if (checkfrom(rqstp, &uid) == 0) {
2032 res->output_message_buffer.GSS_BUFFER_T_val = NULL;
2033 return (FALSE);
2034 }
2035
2036
2037 /*
2038 * copy the XDR structured arguments into their corresponding local
2039 * GSSAPI variable equivalents.
2040 */
2041
2042 input_message_buffer.length = (size_t)argp->input_message_buffer.
2043 GSS_BUFFER_T_len;
2044 input_message_buffer.value = (void *)argp->input_message_buffer.
2045 GSS_BUFFER_T_val;
2046
2047 /* call the gssapi routine */
2048
2049 res->status = (OM_uint32)gss_unseal(&res->minor_status,
2050 context_handle,
2051 &input_message_buffer,
2052 &output_message_buffer,
2053 &res->conf_state,
2054 &res->qop_state);
2055
2056 /*
2057 * convert the output args from the parameter given in the call to the
2058 * variable in the XDR result
2059 */
2060
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;
2066 } else
2067 syslog_gss_error(res->status, res->minor_status, "unseal");
2068
2069
2070 /* return to caller */
2071
2072 return (TRUE);
2073 }
2074
2075 bool_t
gss_display_status_1_svc(argp,res,rqstp)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;
2080 {
2081 uid_t uid;
2082 gss_OID mech_type;
2083 gss_OID_desc mech_type_desc;
2084 gss_buffer_desc status_string;
2085
2086 memset(res, 0, sizeof (*res));
2087
2088 if (gssd_debug)
2089 fprintf(stderr, gettext("gss_display_status\n"));
2090
2091 /*
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
2095 */
2096
2097 if (checkfrom(rqstp, &uid) == 0) {
2098 res->status_string.GSS_BUFFER_T_val = NULL;
2099 return (FALSE);
2100 }
2101
2102 /* set the uid sent as the RPC argument */
2103
2104 uid = argp->uid;
2105 set_gssd_uid(uid);
2106
2107 /*
2108 * copy the XDR structured arguments into their corresponding local
2109 * GSSAPI variables.
2110 */
2111
2112 if (argp->mech_type.GSS_OID_len == 0)
2113 mech_type = GSS_C_NULL_OID;
2114 else {
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;
2118 }
2119
2120
2121 /* call the gssapi routine */
2122
2123 res->status = (OM_uint32) gss_display_status(&res->minor_status,
2124 argp->status_value,
2125 argp->status_type,
2126 mech_type,
2127 (OM_uint32 *)&res->message_context,
2128 &status_string);
2129
2130 /*
2131 * convert the output args from the parameter given in the call to the
2132 * variable in the XDR result
2133 */
2134
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;
2140 }
2141
2142 return (TRUE);
2143
2144 }
2145
2146 /*ARGSUSED*/
2147 bool_t
gss_indicate_mechs_1_svc(argp,res,rqstp)2148 gss_indicate_mechs_1_svc(argp, res, rqstp)
2149 void *argp;
2150 gss_indicate_mechs_res *res;
2151 struct svc_req *rqstp;
2152 {
2153 gss_OID_set oid_set;
2154 uid_t uid;
2155
2156 memset(res, 0, sizeof (*res));
2157
2158 if (gssd_debug)
2159 fprintf(stderr, gettext("gss_indicate_mechs\n"));
2160
2161 res->mech_set.GSS_OID_SET_val = NULL;
2162
2163 /*
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
2167 */
2168
2169 if (checkfrom(rqstp, &uid) == 0) {
2170 return (FALSE);
2171 }
2172
2173 res->status = gss_indicate_mechs(&res->minor_status, &oid_set);
2174
2175 if (res->status == GSS_S_COMPLETE) {
2176 int i, j;
2177
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);
2183 }
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++) {
2191 free
2192 (res->mech_set.GSS_OID_SET_val[i].GSS_OID_val);
2193 }
2194 free(res->mech_set.GSS_OID_SET_val);
2195 return (GSS_S_FAILURE);
2196 }
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);
2200 }
2201 }
2202
2203 return (TRUE);
2204 }
2205
2206 bool_t
gss_inquire_cred_1_svc(argp,res,rqstp)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;
2211 {
2212
2213 uid_t uid;
2214
2215 OM_uint32 minor_status;
2216 gss_cred_id_t cred_handle;
2217 gss_buffer_desc external_name;
2218 gss_OID name_type;
2219 gss_name_t internal_name;
2220 gss_OID_set mechanisms;
2221 int i, j;
2222
2223 memset(res, 0, sizeof (*res));
2224
2225 if (gssd_debug)
2226 fprintf(stderr, gettext("gss_inquire_cred\n"));
2227
2228 /* verify the verifier_cred_handle */
2229
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;
2236 return (TRUE);
2237 }
2238
2239 /*
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
2243 */
2244
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;
2249 return (FALSE);
2250 }
2251
2252 /* set the uid sent as the RPC argument */
2253
2254 uid = argp->uid;
2255 set_gssd_uid(uid);
2256
2257 cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2258 GSS_C_NO_CREDENTIAL :
2259 /*LINTED*/
2260 *((gss_cred_id_t *)argp->cred_handle.
2261 GSS_CRED_ID_T_val));
2262
2263 /* call the gssapi routine */
2264
2265 res->status = (OM_uint32)gss_inquire_cred(&res->minor_status,
2266 cred_handle,
2267 &internal_name,
2268 &res->lifetime,
2269 &res->cred_usage,
2270 &mechanisms);
2271
2272 if (res->status != GSS_S_COMPLETE) {
2273 syslog_gss_error(res->status, res->minor_status,
2274 "inquire_cred");
2275 return (TRUE);
2276 }
2277
2278 /* convert the returned name from internal to external format */
2279
2280 if (gss_display_name(&minor_status, internal_name,
2281 &external_name, &name_type)
2282 != GSS_S_COMPLETE) {
2283
2284 res->status = (OM_uint32)GSS_S_FAILURE;
2285 res->minor_status = minor_status;
2286
2287 gss_release_name(&minor_status, &internal_name);
2288
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);
2293 free(mechanisms);
2294 }
2295
2296 return (TRUE);
2297 }
2298
2299 /*
2300 * convert the output args from the parameter given in the call to the
2301 * variable in the XDR result
2302 */
2303
2304
2305 res->name.GSS_BUFFER_T_len = (uint_t)external_name.length;
2306 res->name.GSS_BUFFER_T_val = (void *)external_name.value;
2307
2308 /*
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.
2314 */
2315
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);
2320 }
2321 memcpy(res->name_type.GSS_OID_val, name_type->elements,
2322 name_type->length);
2323
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);
2332 }
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].
2338 length);
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);
2344 }
2345 free(res->mechanisms.GSS_OID_SET_val);
2346 return (GSS_S_FAILURE);
2347 }
2348 memcpy(res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
2349 mechanisms->elements[i].elements,
2350 mechanisms->elements[i].length);
2351 }
2352 } else
2353 res->mechanisms.GSS_OID_SET_len = 0;
2354
2355 /* release the space allocated for internal_name and mechanisms */
2356 gss_release_name(&minor_status, &internal_name);
2357
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);
2362 free(mechanisms);
2363 }
2364
2365 /* return to caller */
2366 return (TRUE);
2367 }
2368
2369
2370 bool_t
gss_inquire_cred_by_mech_1_svc(argp,res,rqstp)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;
2375 {
2376
2377 uid_t uid;
2378
2379 gss_cred_id_t cred_handle;
2380 gss_OID_desc mech_type_desc;
2381 gss_OID mech_type = &mech_type_desc;
2382
2383 memset(res, 0, sizeof (*res));
2384
2385 if (gssd_debug)
2386 fprintf(stderr, gettext("gss_inquire_cred\n"));
2387
2388 /* verify the verifier_cred_handle */
2389
2390 if (argp->gssd_cred_verifier != gssd_time_verf) {
2391 res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2392 res->minor_status = 0;
2393 return (TRUE);
2394 }
2395
2396 /*
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
2400 */
2401
2402 if (checkfrom(rqstp, &uid) == 0) {
2403 return (FALSE);
2404 }
2405
2406 /* set the uid sent as the RPC argument */
2407
2408 uid = argp->uid;
2409 set_gssd_uid(uid);
2410
2411 cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2412 GSS_C_NO_CREDENTIAL :
2413 /*LINTED*/
2414 *((gss_cred_id_t *)argp->cred_handle.
2415 GSS_CRED_ID_T_val));
2416
2417 /* call the gssapi routine */
2418
2419 if (argp->mech_type.GSS_OID_len == 0)
2420 mech_type = GSS_C_NULL_OID;
2421 else {
2422 mech_type->length =
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);
2428 }
2429 memcpy(mech_type->elements,
2430 argp->mech_type.GSS_OID_val,
2431 mech_type->length);
2432 }
2433 res->status = (OM_uint32)gss_inquire_cred_by_mech(
2434 &res->minor_status, cred_handle,
2435 mech_type, NULL, NULL,
2436 NULL, NULL);
2437
2438 /* return to caller */
2439 return (TRUE);
2440 }
2441
2442
2443 bool_t
gsscred_name_to_unix_cred_1_svc(argsp,res,rqstp)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;
2448 {
2449 uid_t uid;
2450 gss_OID_desc oid;
2451 gss_name_t gssName;
2452 gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
2453 OM_uint32 minor;
2454 int gidsLen;
2455 gid_t *gids, gidOut;
2456
2457 if (gssd_debug)
2458 fprintf(stderr, gettext("gsscred_name_to_unix_cred\n"));
2459
2460 memset(res, 0, sizeof (*res));
2461
2462 /*
2463 * check the request originator
2464 */
2465 if (checkfrom(rqstp, &uid) == 0)
2466 return (FALSE);
2467
2468 /* set the uid from the rpc request */
2469 uid = argsp->uid;
2470 set_gssd_uid(uid);
2471
2472 /*
2473 * convert the principal name to gss internal format
2474 * need not malloc the input parameters
2475 */
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;
2480
2481 res->major = gss_import_name(&minor, &gssBuf, &oid, &gssName);
2482 if (res->major != GSS_S_COMPLETE)
2483 return (TRUE);
2484
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;
2488
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,
2491 &gids, &gidsLen);
2492 gss_release_name(&minor, &gssName);
2493
2494 if (res->major == GSS_S_COMPLETE) {
2495 res->uid = uid;
2496 res->gid = gidOut;
2497 res->gids.GSSCRED_GIDS_val = gids;
2498 res->gids.GSSCRED_GIDS_len = gidsLen;
2499 }
2500
2501 return (TRUE);
2502 } /* gsscred_name_to_unix_cred_svc_1 */
2503
2504 bool_t
gsscred_expname_to_unix_cred_1_svc(argsp,res,rqstp)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;
2509 {
2510 uid_t uid;
2511 gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
2512 int gidsLen;
2513 gid_t *gids, gidOut;
2514
2515 if (gssd_debug)
2516 fprintf(stderr, gettext("gsscred_expname_to_unix_cred\n"));
2517
2518 memset(res, 0, sizeof (*res));
2519
2520 /*
2521 * check the request originator
2522 */
2523 if (checkfrom(rqstp, &uid) == 0)
2524 return (FALSE);
2525
2526 /* set the uid from the rpc request */
2527 uid = argsp->uid;
2528 set_gssd_uid(uid);
2529
2530 /*
2531 * extract the export name from arguments
2532 * need not malloc the input parameters
2533 */
2534 expName.length = argsp->expname.GSS_BUFFER_T_len;
2535 expName.value = (void*)argsp->expname.GSS_BUFFER_T_val;
2536
2537 res->major = gsscred_expname_to_unix_cred(&expName, &uid,
2538 &gidOut, &gids, &gidsLen);
2539
2540 if (res->major == GSS_S_COMPLETE) {
2541 res->uid = uid;
2542 res->gid = gidOut;
2543 res->gids.GSSCRED_GIDS_val = gids;
2544 res->gids.GSSCRED_GIDS_len = gidsLen;
2545 }
2546
2547 return (TRUE);
2548 } /* gsscred_expname_to_unix_cred_1_svc */
2549
2550 bool_t
gss_get_group_info_1_svc(argsp,res,rqstp)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;
2555 {
2556 uid_t uid;
2557 int gidsLen;
2558 gid_t *gids, gidOut;
2559
2560 if (gssd_debug)
2561 fprintf(stderr, gettext("gss_get_group_info\n"));
2562
2563 memset(res, 0, sizeof (*res));
2564
2565 /*
2566 * check the request originator
2567 */
2568 if (checkfrom(rqstp, &uid) == 0)
2569 return (FALSE);
2570
2571 /* set the uid from the rpc request */
2572 uid = argsp->uid;
2573 set_gssd_uid(uid);
2574
2575 /*
2576 * extract the uid from the arguments
2577 */
2578 uid = argsp->puid;
2579 res->major = gss_get_group_info(uid, &gidOut, &gids, &gidsLen);
2580 if (res->major == GSS_S_COMPLETE) {
2581 res->gid = gidOut;
2582 res->gids.GSSCRED_GIDS_val = gids;
2583 res->gids.GSSCRED_GIDS_len = gidsLen;
2584 }
2585
2586 return (TRUE);
2587 } /* gss_get_group_info_1_svc */
2588
2589 /*ARGSUSED*/
2590 bool_t
gss_get_kmod_1_svc(argsp,res,rqstp)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;
2595 {
2596 gss_OID_desc oid;
2597 char *kmodName;
2598
2599 if (gssd_debug)
2600 fprintf(stderr, gettext("gss_get_kmod\n"));
2601
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);
2606
2607 if (kmodName != NULL) {
2608 res->module_follow = TRUE;
2609 res->gss_get_kmod_res_u.modname = kmodName;
2610 }
2611
2612 return (TRUE);
2613 }
2614
2615 /*
2616 * Returns 1 if caller is ok, else 0.
2617 * If caller ok, the uid is returned in uidp.
2618 */
2619 static int
checkfrom(rqstp,uidp)2620 checkfrom(rqstp, uidp)
2621 struct svc_req *rqstp;
2622 uid_t *uidp;
2623 {
2624 SVCXPRT *xprt = rqstp->rq_xprt;
2625 struct authunix_parms *aup;
2626 uid_t uid;
2627
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);
2632 goto weakauth;
2633 }
2634 if (gssd_debug)
2635 fprintf(stderr, gettext("checkfrom: local_uid %d\n"), uid);
2636 if (uid != 0) {
2637 syslog(LOG_ERR,
2638 gettext("checkfrom: caller (uid %d) not privileged"),
2639 uid);
2640 goto weakauth;
2641 }
2642
2643 /*
2644 * Request came from local privileged process.
2645 * Proceed to get uid of client if needed by caller.
2646 */
2647 if (uidp) {
2648 if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
2649 syslog(LOG_ERR, gettext("checkfrom: not UNIX credentials"));
2650 goto weakauth;
2651 }
2652 CTASSERT(sizeof (struct authunix_parms) <= RQCRED_SIZE);
2653 /*LINTED*/
2654 aup = (struct authunix_parms *)rqstp->rq_clntcred;
2655 *uidp = aup->aup_uid;
2656 if (gssd_debug) {
2657 fprintf(stderr,
2658 gettext("checkfrom: caller's uid %d\n"), *uidp);
2659 }
2660 }
2661 return (1);
2662
2663 weakauth:
2664 svcerr_weakauth(xprt);
2665 return (0);
2666 }
2667