1 /*
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
4 /*
5 * CDDL HEADER START
6 *
7 * The contents of this file are subject to the terms of the
8 * Common Development and Distribution License (the "License").
9 * You may not use this file except in compliance with the License.
10 *
11 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12 * or http://www.opensolaris.org/os/licensing.
13 * See the License for the specific language governing permissions
14 * and limitations under the License.
15 *
16 * When distributing Covered Code, include this CDDL HEADER in each
17 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18 * If applicable, add the following below this CDDL HEADER, with the
19 * fields enclosed by brackets "[]" replaced with your own identifying
20 * information: Portions Copyright [yyyy] [name of copyright owner]
21 *
22 * CDDL HEADER END
23 */
24
25 /*
26 * RPC server procedures for the gssapi usermode daemon gssd.
27 */
28
29 #include <stdio.h>
30 #include <stdio_ext.h>
31 #include <unistd.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <strings.h>
35 #include <limits.h>
36 #include <sys/param.h>
37 #include <mechglueP.h>
38 #include "gssd.h"
39 #include <gssapi/gssapi.h>
40 #include <rpc/rpc.h>
41 #include <stdlib.h>
42 #include <syslog.h>
43 #include <sys/resource.h>
44
45 #define SRVTAB ""
46 #define FDCACHE_PERCENTAGE .75 /* Percentage of total FD limit */
47 #define FDCACHE_DEFAULT 16 /* Default LRU cache size */
48 #define GSSD_FD_LIMIT 255 /* Increase number of fds allowed */
49
50 extern int gssd_debug; /* declared in gssd.c */
51 static OM_uint32 gssd_time_verf; /* verifies same gssd */
52 static OM_uint32 context_verf; /* context sequence numbers */
53
54 struct gssd_ctx_slot {
55 struct gssd_ctx_slot *lru_next;
56 struct gssd_ctx_slot *lru_prev;
57 bool_t inuse;
58 OM_uint32 create_time;
59 OM_uint32 verf;
60 gss_ctx_id_t ctx;
61 gss_ctx_id_t rpcctx;
62 };
63
64 struct gssd_ctx_slot *gssd_ctx_slot_tbl;
65 struct gssd_ctx_slot *gssd_lru_head;
66
67 static int max_contexts;
68
69 static int checkfrom(struct svc_req *, uid_t *);
70 extern void set_gssd_uid(uid_t);
71 extern int __rpc_get_local_uid(SVCXPRT *, uid_t *);
72
73 /*
74 * Syslog (and output to stderr if debug set) the GSSAPI major
75 * and minor numbers.
76 */
77 static void
syslog_gss_error(OM_uint32 maj_stat,OM_uint32 min_stat,char * errstr)78 syslog_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *errstr)
79 {
80 OM_uint32 gmaj_stat, gmin_stat;
81 gss_buffer_desc msg;
82 OM_uint32 msg_ctx = 0;
83
84
85 if (gssd_debug)
86 fprintf(stderr,
87 "gssd: syslog_gss_err: called from %s: maj=%d min=%d\n",
88 errstr ? errstr : "<null>", maj_stat, min_stat);
89
90 /* Print the major status error from the mech. */
91 /* msg_ctx - skip the check for it as is probably unnecesary */
92 gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
93 GSS_C_GSS_CODE,
94 GSS_C_NULL_OID, &msg_ctx, &msg);
95 if ((gmaj_stat == GSS_S_COMPLETE)||
96 (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
97 syslog(LOG_DAEMON|LOG_NOTICE,
98 "GSSAPI error major: %s", (char *)msg.value);
99 if (gssd_debug)
100 (void) fprintf(stderr,
101 "gssd: GSSAPI error major: %s\n",
102 (char *)msg.value);
103
104 (void) gss_release_buffer(&gmin_stat, &msg);
105 }
106
107 /* Print the minor status error from the mech. */
108 msg_ctx = 0;
109 /* msg_ctx - skip the check for it as is probably unnecesary */
110 gmaj_stat = gss_display_status(&gmin_stat, min_stat,
111 GSS_C_MECH_CODE,
112 GSS_C_NULL_OID,
113 &msg_ctx, &msg);
114 if ((gmaj_stat == GSS_S_COMPLETE)||
115 (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
116 syslog(LOG_DAEMON|LOG_NOTICE,
117 "GSSAPI error minor: %s",
118 (char *)msg.value);
119 if (gssd_debug)
120 (void) fprintf(stderr,
121 "gssd: GSSAPI error minor: %s\n",
122 (char *)msg.value);
123 (void) gss_release_buffer(&gmin_stat, &msg);
124 }
125 }
126
127 void
gssd_setup(char * arg)128 gssd_setup(char *arg)
129 {
130 int i;
131 struct rlimit rl;
132 hrtime_t high_res_time;
133
134 gssd_time_verf = (OM_uint32)time(NULL);
135 max_contexts = FDCACHE_DEFAULT;
136
137 /*
138 * Use low order bits of high resolution time to get a reasonably
139 * random number to start the context sequencing. This alternative
140 * to using a time value avoid clock resets via NTP or ntpdate.
141 */
142 high_res_time = gethrtime();
143 context_verf = (OM_uint32)high_res_time;
144
145 /*
146 * Increase resource limit of FDs in case we get alot accept/init_
147 * sec_context calls before we're able to export them. This can
148 * happen in very heavily load environments where gssd doesn't get
149 * much time to work on its backlog.
150 */
151 if ((getrlimit(RLIMIT_NOFILE, &rl)) == 0) {
152 rl.rlim_cur = (rl.rlim_max >= GSSD_FD_LIMIT) ?
153 GSSD_FD_LIMIT : rl.rlim_max;
154 if ((setrlimit(RLIMIT_NOFILE, &rl)) == 0)
155 max_contexts = rl.rlim_cur * FDCACHE_PERCENTAGE;
156 (void) enable_extended_FILE_stdio(-1, -1);
157 }
158
159 gssd_ctx_slot_tbl = (struct gssd_ctx_slot *)
160 malloc(sizeof (struct gssd_ctx_slot) * max_contexts);
161
162 if (gssd_ctx_slot_tbl == NULL) {
163 (void) fprintf(stderr,
164 gettext("[%s] could not allocate %d byte context table"
165 "\n"), arg,
166 (sizeof (struct gssd_ctx_slot) * max_contexts));
167 exit(1);
168 }
169
170 for (i = 1; i < max_contexts; i++) {
171 gssd_ctx_slot_tbl[i-1].lru_next = &gssd_ctx_slot_tbl[i];
172 gssd_ctx_slot_tbl[i].lru_prev = &gssd_ctx_slot_tbl[i-1];
173 gssd_ctx_slot_tbl[i].inuse = FALSE;
174 gssd_ctx_slot_tbl[i].verf = 0;
175 gssd_ctx_slot_tbl[i].create_time = 0;
176 gssd_ctx_slot_tbl[i].rpcctx = (gss_ctx_id_t)(i + 1);
177 }
178
179 gssd_ctx_slot_tbl[max_contexts - 1].lru_next = &gssd_ctx_slot_tbl[0];
180 gssd_ctx_slot_tbl[0].lru_prev = &gssd_ctx_slot_tbl[max_contexts - 1];
181 gssd_ctx_slot_tbl[0].inuse = FALSE;
182 gssd_ctx_slot_tbl[0].verf = 0;
183 gssd_ctx_slot_tbl[0].create_time = 0;
184 gssd_ctx_slot_tbl[0].rpcctx = (gss_ctx_id_t)1;
185
186 gssd_lru_head = &gssd_ctx_slot_tbl[0];
187 }
188
189 static OM_uint32 syslog_interval = 60;
190
191 static struct gssd_ctx_slot *
gssd_alloc_slot(gss_ctx_id_t ctx)192 gssd_alloc_slot(gss_ctx_id_t ctx)
193 {
194 struct gssd_ctx_slot *lru;
195 OM_uint32 current_time;
196 static OM_uint32 last_syslog = 0;
197 static bool_t first_take = TRUE;
198 static int tooks;
199 OM_uint32 minor_status;
200
201 lru = gssd_lru_head;
202 gssd_lru_head = lru->lru_next;
203
204 current_time = (OM_uint32) time(NULL);
205
206 if (last_syslog == 0)
207 last_syslog = current_time; /* Save 1st alloc time */
208
209 if (lru->inuse) {
210 if (lru->ctx != GSS_C_NO_CONTEXT)
211 (void) gss_delete_sec_context(&minor_status,
212 &lru->ctx, NULL);
213 tooks++;
214
215 if (((current_time - last_syslog) > syslog_interval) ||
216 first_take) {
217 syslog(LOG_WARNING, gettext("re-used an existing "
218 "context slot of age %u seconds (%d slots re-"
219 "used during last %u seconds)"),
220 current_time - lru->create_time, tooks,
221 current_time - last_syslog);
222
223 last_syslog = current_time;
224 tooks = 0;
225 first_take = FALSE;
226 }
227 }
228
229 /*
230 * Assign the next context verifier to the context (avoiding zero).
231 */
232 context_verf++;
233 if (context_verf == 0)
234 context_verf = 1;
235 lru->verf = context_verf;
236
237 lru->create_time = current_time;
238 lru->ctx = ctx;
239 lru->inuse = TRUE;
240 return (lru);
241 }
242
243 /*
244 * We always add 1 because we don't want slot 0 to be confused
245 * with GSS_C_NO_CONTEXT.
246 */
247
248 static struct gssd_ctx_slot *
gssd_handle_to_slot(GSS_CTX_ID_T * h)249 gssd_handle_to_slot(GSS_CTX_ID_T *h)
250 {
251 intptr_t i;
252
253 if (h->GSS_CTX_ID_T_len == 0) {
254 return (NULL);
255 }
256 if (h->GSS_CTX_ID_T_len != sizeof (i))
257 return (NULL);
258
259 i = (*(intptr_t *)(h->GSS_CTX_ID_T_val)) - 1;
260
261 if (i < 0 || i >= max_contexts)
262 return (NULL);
263
264 return (&gssd_ctx_slot_tbl[i]);
265 }
266
267 static void
gssd_rel_slot(struct gssd_ctx_slot * lru)268 gssd_rel_slot(struct gssd_ctx_slot *lru)
269 {
270 struct gssd_ctx_slot *prev, *next;
271
272 if (lru == NULL)
273 return;
274
275 lru->inuse = FALSE;
276
277 /*
278 * Remove entry from its current location in list
279 */
280 prev = lru->lru_prev;
281 next = lru->lru_next;
282 prev->lru_next = next;
283 next->lru_prev = prev;
284
285 /*
286 * Since it is no longer in use, it is the least recently
287 * used.
288 */
289 prev = gssd_lru_head->lru_prev;
290 next = gssd_lru_head;
291
292 prev->lru_next = lru;
293 lru->lru_prev = prev;
294
295 next->lru_prev = lru;
296 lru->lru_next = next;
297
298 gssd_lru_head = lru;
299 }
300
301 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)302 gssd_convert_context_handle(GSS_CTX_ID_T *h,
303 gss_ctx_id_t *context_handle,
304 OM_uint32 verf,
305 bool_t *context_verf_ok,
306 struct gssd_ctx_slot **slotp)
307 {
308 struct gssd_ctx_slot *slot;
309
310 *context_verf_ok = FALSE;
311 *context_handle = (gss_ctx_id_t)1;
312 if (slotp != NULL)
313 *slotp = NULL;
314
315 if (h->GSS_CTX_ID_T_len == 0) {
316 *context_handle = GSS_C_NO_CONTEXT;
317 *context_verf_ok = TRUE;
318 return;
319 }
320
321 slot = gssd_handle_to_slot(h);
322
323 if (slot == NULL)
324 return;
325
326 if (verf != slot->verf)
327 return;
328
329 *context_verf_ok = TRUE;
330 *context_handle = slot->ctx;
331 if (slotp != NULL)
332 *slotp = slot;
333 }
334
335 bool_t
gss_acquire_cred_1_svc(argp,res,rqstp)336 gss_acquire_cred_1_svc(argp, res, rqstp)
337 gss_acquire_cred_arg *argp;
338 gss_acquire_cred_res *res;
339 struct svc_req *rqstp;
340 {
341 OM_uint32 minor_status;
342 gss_name_t desired_name;
343 gss_OID_desc name_type_desc;
344 gss_OID name_type = &name_type_desc;
345 OM_uint32 time_req;
346 gss_OID_set_desc desired_mechs_desc;
347 gss_OID_set desired_mechs;
348 int cred_usage;
349 gss_cred_id_t output_cred_handle;
350 gss_OID_set actual_mechs;
351 gss_buffer_desc external_name;
352 uid_t uid;
353 int i, j;
354
355 if (gssd_debug)
356 fprintf(stderr, gettext("gss_acquire_cred\n"));
357
358 memset(res, 0, sizeof (*res));
359
360 /*
361 * if the request isn't from root, null out the result pointer
362 * entries, so the next time through xdr_free won't try to
363 * free unmalloc'd memory and then return NULL
364 */
365
366 if (checkfrom(rqstp, &uid) == 0) {
367 res->output_cred_handle.GSS_CRED_ID_T_val = NULL;
368 res->actual_mechs.GSS_OID_SET_val = NULL;
369 return (FALSE);
370 }
371
372 /* set the uid sent as the RPC argument */
373
374 uid = argp->uid;
375 set_gssd_uid(uid);
376
377 /* convert the desired name from external to internal format */
378
379 external_name.length = argp->desired_name.GSS_BUFFER_T_len;
380 external_name.value = (void *)malloc(external_name.length);
381 if (!external_name.value)
382 return (GSS_S_FAILURE);
383 memcpy(external_name.value, argp->desired_name.GSS_BUFFER_T_val,
384 external_name.length);
385
386 if (argp->name_type.GSS_OID_len == 0) {
387 name_type = GSS_C_NULL_OID;
388 } else {
389 name_type->length = argp->name_type.GSS_OID_len;
390 name_type->elements = (void *)malloc(name_type->length);
391 if (!name_type->elements) {
392 free(external_name.value);
393 return (GSS_S_FAILURE);
394 }
395 memcpy(name_type->elements, argp->name_type.GSS_OID_val,
396 name_type->length);
397 }
398
399 if (gss_import_name(&minor_status, &external_name, name_type,
400 &desired_name) != GSS_S_COMPLETE) {
401
402 res->status = (OM_uint32) GSS_S_FAILURE;
403 res->minor_status = minor_status;
404
405 free(external_name.value);
406 if (name_type != GSS_C_NULL_OID)
407 free(name_type->elements);
408
409 return (TRUE);
410 }
411
412 /*
413 * copy the XDR structured arguments into their corresponding local GSSAPI
414 * variables.
415 */
416
417 cred_usage = argp->cred_usage;
418 time_req = argp->time_req;
419
420 if (argp->desired_mechs.GSS_OID_SET_len != 0) {
421 desired_mechs = &desired_mechs_desc;
422 desired_mechs->count =
423 (int)argp->desired_mechs.GSS_OID_SET_len;
424 desired_mechs->elements = (gss_OID)
425 malloc(sizeof (gss_OID_desc) * desired_mechs->count);
426 if (!desired_mechs->elements) {
427 free(external_name.value);
428 free(name_type->elements);
429 return (GSS_S_FAILURE);
430 }
431 for (i = 0; i < desired_mechs->count; i++) {
432 desired_mechs->elements[i].length =
433 (OM_uint32)argp->desired_mechs.
434 GSS_OID_SET_val[i].GSS_OID_len;
435 desired_mechs->elements[i].elements =
436 (void *)malloc(desired_mechs->elements[i].
437 length);
438 if (!desired_mechs->elements[i].elements) {
439 free(external_name.value);
440 free(name_type->elements);
441 for (j = 0; j < (i -1); j++) {
442 free
443 (desired_mechs->elements[j].elements);
444 }
445 free(desired_mechs->elements);
446 return (GSS_S_FAILURE);
447 }
448 memcpy(desired_mechs->elements[i].elements,
449 argp->desired_mechs.GSS_OID_SET_val[i].
450 GSS_OID_val,
451 desired_mechs->elements[i].length);
452 }
453 } else
454 desired_mechs = GSS_C_NULL_OID_SET;
455
456 /* call the gssapi routine */
457
458 res->status = (OM_uint32)gss_acquire_cred(&res->minor_status,
459 desired_name,
460 time_req,
461 desired_mechs,
462 cred_usage,
463 &output_cred_handle,
464 &actual_mechs,
465 &res->time_rec);
466
467 /*
468 * convert the output args from the parameter given in the call to the
469 * variable in the XDR result
470 */
471
472 res->output_cred_handle.GSS_CRED_ID_T_len = sizeof (gss_cred_id_t);
473 res->output_cred_handle.GSS_CRED_ID_T_val =
474 (void *)malloc(sizeof (gss_cred_id_t));
475 if (!res->output_cred_handle.GSS_CRED_ID_T_val) {
476 free(external_name.value);
477 free(name_type->elements);
478 for (i = 0; i < desired_mechs->count; i++) {
479 free(desired_mechs->elements[i].elements);
480 }
481 free(desired_mechs->elements);
482 return (GSS_S_FAILURE);
483 }
484 memcpy(res->output_cred_handle.GSS_CRED_ID_T_val, &output_cred_handle,
485 sizeof (gss_cred_id_t));
486
487 if (actual_mechs != GSS_C_NULL_OID_SET) {
488 res->actual_mechs.GSS_OID_SET_len =
489 (uint_t)actual_mechs->count;
490 res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
491 malloc(sizeof (GSS_OID) * actual_mechs->count);
492 if (!res->actual_mechs.GSS_OID_SET_val) {
493 free(external_name.value);
494 free(name_type->elements);
495 for (i = 0; i < desired_mechs->count; i++) {
496 free(desired_mechs->elements[i].elements);
497 }
498 free(desired_mechs->elements);
499 free(res->output_cred_handle.GSS_CRED_ID_T_val);
500 return (GSS_S_FAILURE);
501 }
502 for (i = 0; i < actual_mechs->count; i++) {
503 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
504 (uint_t)actual_mechs->elements[i].length;
505 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
506 (char *)malloc(actual_mechs->elements[i].
507 length);
508 if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
509 free(external_name.value);
510 free(name_type->elements);
511 free(desired_mechs->elements);
512 for (j = 0; j < desired_mechs->count; j++) {
513 free
514 (desired_mechs->elements[i].elements);
515 }
516 free(res->actual_mechs.GSS_OID_SET_val);
517 for (j = 0; j < (i - 1); j++) {
518 free
519 (res->actual_mechs.
520 GSS_OID_SET_val[j].GSS_OID_val);
521 }
522 return (GSS_S_FAILURE);
523 }
524 memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
525 actual_mechs->elements[i].elements,
526 actual_mechs->elements[i].length);
527 }
528 } else
529 res->actual_mechs.GSS_OID_SET_len = 0;
530
531 /*
532 * set the time verifier for credential handle. To ensure that the
533 * timestamp is not the same as previous gssd process, verify that
534 * time is not the same as set earlier at start of process. If it
535 * is, sleep one second and reset. (due to one second granularity)
536 */
537
538 if (res->status == GSS_S_COMPLETE) {
539 res->gssd_cred_verifier = (OM_uint32)time(NULL);
540 if (res->gssd_cred_verifier == gssd_time_verf) {
541 sleep(1);
542 gssd_time_verf = (OM_uint32)time(NULL);
543 }
544 res->gssd_cred_verifier = gssd_time_verf;
545 } else
546 syslog_gss_error(res->status, res->minor_status,
547 "acquire_cred");
548
549 /*
550 * now release the space allocated by the underlying gssapi mechanism
551 * library for actual_mechs as well as by this routine for
552 * external_name, name_type and desired_name
553 */
554
555 free(external_name.value);
556 if (name_type != GSS_C_NULL_OID)
557 free(name_type->elements);
558 gss_release_name(&minor_status, &desired_name);
559
560 if (actual_mechs != GSS_C_NULL_OID_SET) {
561 for (i = 0; i < actual_mechs->count; i++)
562 free(actual_mechs->elements[i].elements);
563 free(actual_mechs->elements);
564 free(actual_mechs);
565 }
566
567 if (desired_mechs != GSS_C_NULL_OID_SET) {
568 for (i = 0; i < desired_mechs->count; i++)
569 free(desired_mechs->elements[i].elements);
570 free(desired_mechs->elements);
571
572 }
573
574 /* return to caller */
575
576 return (TRUE);
577 }
578
579 bool_t
gss_add_cred_1_svc(argp,res,rqstp)580 gss_add_cred_1_svc(argp, res, rqstp)
581 gss_add_cred_arg *argp;
582 gss_add_cred_res *res;
583 struct svc_req *rqstp;
584 {
585
586 OM_uint32 minor_status;
587 gss_name_t desired_name;
588 gss_OID_desc name_type_desc;
589 gss_OID name_type = &name_type_desc;
590 gss_OID_desc desired_mech_type_desc;
591 gss_OID desired_mech_type = &desired_mech_type_desc;
592 int cred_usage;
593 gss_cred_id_t input_cred_handle;
594 gss_OID_set actual_mechs;
595 gss_buffer_desc external_name;
596 uid_t uid;
597 int i, j;
598
599 if (gssd_debug)
600 fprintf(stderr, gettext("gss_add_cred\n"));
601
602 if (argp->gssd_cred_verifier != gssd_time_verf) {
603 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
604 res->minor_status = 0;
605 res->actual_mechs.GSS_OID_SET_len = 0;
606 res->actual_mechs.GSS_OID_SET_val = NULL;
607 res->initiator_time_rec = 0;
608 res->acceptor_time_rec = 0;
609 fprintf(stderr, gettext("gss_add_cred defective cred\n"));
610 return (TRUE);
611 }
612 memset(res, 0, sizeof (*res));
613
614 /*
615 * if the request isn't from root, null out the result pointer
616 * entries, so the next time through xdr_free won't try to
617 * free unmalloc'd memory and then return NULL
618 */
619
620 if (checkfrom(rqstp, &uid) == 0) {
621 return (FALSE);
622 }
623
624 /* set the uid sent as the RPC argument */
625
626 uid = argp->uid;
627 set_gssd_uid(uid);
628
629 /* convert the desired name from external to internal format */
630
631 external_name.length = argp->desired_name.GSS_BUFFER_T_len;
632 external_name.value = (void *)argp->desired_name.GSS_BUFFER_T_val;
633 name_type->length = argp->name_type.GSS_OID_len;
634 name_type->elements = (void *)argp->name_type.GSS_OID_val;
635
636 if (gss_import_name(&minor_status, &external_name, name_type,
637 &desired_name) != GSS_S_COMPLETE) {
638
639 if (gssd_debug)
640 fprintf(stderr,
641 gettext("gss_add_cred:import name"),
642 gettext(" failed status %d \n"),
643 res->status);
644 res->status = (OM_uint32)GSS_S_FAILURE;
645 res->minor_status = minor_status;
646 return (TRUE);
647 }
648
649 /*
650 * copy the XDR structured arguments into their corresponding local GSSAPI
651 * variables.
652 */
653
654 cred_usage = argp->cred_usage;
655 if (argp->desired_mech_type.GSS_OID_len == 0)
656 desired_mech_type = GSS_C_NULL_OID;
657 else {
658 desired_mech_type->length =
659 (OM_uint32)argp->desired_mech_type.GSS_OID_len;
660 desired_mech_type->elements =
661 (void *)malloc(desired_mech_type->length);
662 if (!desired_mech_type->elements) {
663 return (GSS_S_FAILURE);
664 }
665 memcpy(desired_mech_type->elements,
666 argp->desired_mech_type.GSS_OID_val,
667 desired_mech_type->length);
668 }
669 input_cred_handle =
670 (argp->input_cred_handle.GSS_CRED_ID_T_len == 0 ?
671 GSS_C_NO_CREDENTIAL :
672 /*LINTED*/
673 *((gss_cred_id_t *)argp->input_cred_handle.
674 GSS_CRED_ID_T_val));
675
676 if (input_cred_handle != GSS_C_NO_CREDENTIAL)
677 /* verify the input_cred_handle */
678 if (argp->gssd_cred_verifier != gssd_time_verf) {
679 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
680 res->minor_status = 0;
681 return (TRUE);
682 }
683
684 /* call the gssapi routine */
685
686 res->status = (OM_uint32)gss_add_cred(&res->minor_status,
687 input_cred_handle,
688 desired_name,
689 desired_mech_type,
690 cred_usage,
691 argp->initiator_time_req,
692 argp->acceptor_time_req,
693 NULL,
694 &actual_mechs,
695 &res->initiator_time_rec,
696 &res->acceptor_time_rec);
697
698 if ((res->status != GSS_S_COMPLETE) &&
699 (res->status != GSS_S_DUPLICATE_ELEMENT))
700 syslog_gss_error(res->status, res->minor_status, "add_cred");
701
702 /*
703 * convert the output args from the parameter given in the call to the
704 * variable in the XDR result
705 */
706 if (actual_mechs != GSS_C_NULL_OID_SET) {
707 res->actual_mechs.GSS_OID_SET_len =
708 (uint_t)actual_mechs->count;
709 res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
710 malloc(sizeof (GSS_OID) * actual_mechs->count);
711 if (!res->actual_mechs.GSS_OID_SET_val) {
712 free(desired_mech_type->elements);
713 free(desired_mech_type);
714 return (GSS_S_FAILURE);
715 }
716 for (i = 0; i < actual_mechs->count; i++) {
717 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
718 (uint_t)actual_mechs->elements[i].length;
719 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
720 (char *)malloc(actual_mechs->elements[i].
721 length);
722 if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
723 free(desired_mech_type->elements);
724 free(desired_mech_type);
725 free(res->actual_mechs.GSS_OID_SET_val);
726 for (j = 0; j < (i - 1); j++) {
727 free
728 (res->actual_mechs.
729 GSS_OID_SET_val[j].GSS_OID_val);
730 }
731 return (GSS_S_FAILURE);
732 }
733 memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
734 actual_mechs->elements[i].elements,
735 actual_mechs->elements[i].length);
736 }
737 } else
738 res->actual_mechs.GSS_OID_SET_len = 0;
739
740 /*
741 * now release the space allocated for
742 * desired_name and desired_mech_type
743 */
744
745 gss_release_name(&minor_status, &desired_name);
746 free(desired_mech_type->elements);
747 gss_release_oid_set(&minor_status, &actual_mechs);
748 /*
749 * if (actual_mechs != GSS_C_NULL_OID_SET) {
750 * for (i = 0; i < actual_mechs->count; i++)
751 * free(actual_mechs->elements[i].elements);
752 * free(actual_mechs->elements);
753 * free(actual_mechs);
754 * }
755 */
756
757
758 /* return to caller */
759
760 return (TRUE);
761 }
762
763 bool_t
gss_release_cred_1_svc(argp,res,rqstp)764 gss_release_cred_1_svc(argp, res, rqstp)
765 gss_release_cred_arg *argp;
766 gss_release_cred_res *res;
767 struct svc_req *rqstp;
768 {
769
770 uid_t uid;
771 gss_cred_id_t cred_handle;
772
773 memset(res, 0, sizeof (*res));
774
775 if (gssd_debug)
776 fprintf(stderr, gettext("gss_release_cred\n"));
777
778 if (checkfrom(rqstp, &uid) == 0)
779 return (FALSE);
780
781 /* set the uid sent as the RPC argument */
782
783 uid = argp->uid;
784 set_gssd_uid(uid);
785
786 /*
787 * if the cred_handle verifier is not correct,
788 * set status to GSS_S_DEFECTIVE_CREDENTIAL and return
789 */
790
791 if (argp->gssd_cred_verifier != gssd_time_verf) {
792 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
793 return (TRUE);
794 }
795
796 /*
797 * if the cred_handle length is 0
798 * set cred_handle argument to GSS_S_NO_CREDENTIAL
799 */
800
801 if (argp->cred_handle.GSS_CRED_ID_T_len == 0)
802 cred_handle = GSS_C_NO_CREDENTIAL;
803 else
804 cred_handle =
805 (gss_cred_id_t)argp->cred_handle.GSS_CRED_ID_T_val;
806
807 /* call the gssapi routine */
808
809 res->status = (OM_uint32)gss_release_cred(&res->minor_status,
810 &cred_handle);
811
812 /* return to caller */
813
814 return (TRUE);
815 }
816
817 bool_t
gss_init_sec_context_1_svc(argp,res,rqstp)818 gss_init_sec_context_1_svc(argp, res, rqstp)
819 gss_init_sec_context_arg *argp;
820 gss_init_sec_context_res *res;
821 struct svc_req *rqstp;
822 {
823
824 OM_uint32 minor_status;
825 gss_ctx_id_t context_handle;
826 bool_t context_verf_ok;
827 gss_cred_id_t claimant_cred_handle;
828 gss_buffer_desc external_name;
829 gss_OID_desc name_type_desc;
830 gss_OID name_type = &name_type_desc;
831 gss_name_t internal_name;
832
833 gss_OID_desc mech_type_desc;
834 gss_OID mech_type = &mech_type_desc;
835 struct gss_channel_bindings_struct
836 input_chan_bindings;
837 gss_channel_bindings_t input_chan_bindings_ptr;
838 gss_buffer_desc input_token;
839 gss_buffer_desc output_token;
840 gss_buffer_t input_token_ptr;
841 gss_OID actual_mech_type;
842 struct gssd_ctx_slot *slot = NULL;
843
844 uid_t uid;
845
846 memset(res, 0, sizeof (*res));
847
848 if (gssd_debug)
849 fprintf(stderr, gettext("gss_init_sec_context\n"));
850
851 /*
852 * if the request isn't from root, null out the result pointer
853 * entries, so the next time through xdr_free won't try to
854 * free unmalloc'd memory and then return NULL
855 */
856
857 if (checkfrom(rqstp, &uid) == 0) {
858 res->context_handle.GSS_CTX_ID_T_val = NULL;
859 res->actual_mech_type.GSS_OID_val = NULL;
860 res->output_token.GSS_BUFFER_T_val = NULL;
861 return (FALSE);
862 }
863
864 /* set the uid sent as the RPC argument */
865
866 uid = argp->uid;
867 set_gssd_uid(uid);
868
869 /*
870 * copy the supplied context handle into the local context handle, so it
871 * can be supplied to the gss_init_sec_context call
872 */
873
874 gssd_convert_context_handle(&argp->context_handle, &context_handle,
875 argp->gssd_context_verifier, &context_verf_ok, &slot);
876
877 claimant_cred_handle =
878 (argp->claimant_cred_handle.GSS_CRED_ID_T_len == 0 ?
879 GSS_C_NO_CREDENTIAL :
880 /*LINTED*/
881 *((gss_cred_id_t *)argp->claimant_cred_handle.
882 GSS_CRED_ID_T_val));
883
884 if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
885 /* verify the verifier_cred_handle */
886 if (argp->gssd_cred_verifier != gssd_time_verf) {
887 res->context_handle.GSS_CTX_ID_T_val = NULL;
888 res->output_token.GSS_BUFFER_T_val = NULL;
889 res->actual_mech_type.GSS_OID_val = NULL;
890 res->context_handle.GSS_CTX_ID_T_len = 0;
891 res->output_token.GSS_BUFFER_T_len = 0;
892 res->actual_mech_type.GSS_OID_len = 0;
893 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
894 res->minor_status = 0;
895 return (TRUE);
896 }
897 }
898
899 if (context_handle != GSS_C_NO_CONTEXT) {
900 /* verify the verifier_context_handle */
901
902 if (!context_verf_ok) {
903 res->context_handle.GSS_CTX_ID_T_val = NULL;
904 res->output_token.GSS_BUFFER_T_val = NULL;
905 res->actual_mech_type.GSS_OID_val = NULL;
906 res->context_handle.GSS_CTX_ID_T_len = 0;
907 res->output_token.GSS_BUFFER_T_len = 0;
908 res->actual_mech_type.GSS_OID_len = 0;
909 res->status = (OM_uint32)GSS_S_NO_CONTEXT;
910 res->minor_status = 0;
911 return (TRUE);
912 }
913 }
914
915 /* convert the target name from external to internal format */
916
917 external_name.length = argp->target_name.GSS_BUFFER_T_len;
918 external_name.value = (void *)argp->target_name.GSS_BUFFER_T_val;
919
920 if (argp->name_type.GSS_OID_len == 0) {
921 name_type = GSS_C_NULL_OID;
922 } else {
923 name_type->length = argp->name_type.GSS_OID_len;
924 name_type->elements = (void *)malloc(name_type->length);
925 if (!name_type->elements)
926 return (GSS_S_FAILURE);
927 memcpy(name_type->elements, argp->name_type.GSS_OID_val,
928 name_type->length);
929 }
930
931 if (argp->mech_type.GSS_OID_len == 0)
932 mech_type = GSS_C_NULL_OID;
933 else {
934 mech_type->length = (OM_uint32)argp->mech_type.GSS_OID_len;
935 mech_type->elements = (void *)argp->mech_type.GSS_OID_val;
936 }
937
938 if (gss_import_name(&minor_status, &external_name, name_type,
939 &internal_name) != GSS_S_COMPLETE) {
940
941 if (name_type != GSS_C_NULL_OID)
942 free(name_type->elements);
943 res->status = (OM_uint32)GSS_S_FAILURE;
944 res->minor_status = minor_status;
945
946 return (TRUE);
947 }
948 /*
949 * copy the XDR structured arguments into their corresponding local GSSAPI
950 * variables.
951 */
952
953 if (argp->input_chan_bindings.present == YES) {
954 input_chan_bindings_ptr = &input_chan_bindings;
955 input_chan_bindings.initiator_addrtype =
956 (OM_uint32)argp->input_chan_bindings.
957 initiator_addrtype;
958 input_chan_bindings.initiator_address.length =
959 (uint_t)argp->input_chan_bindings.initiator_address.
960 GSS_BUFFER_T_len;
961 input_chan_bindings.initiator_address.value =
962 (void *)argp->input_chan_bindings.initiator_address.
963 GSS_BUFFER_T_val;
964 input_chan_bindings.acceptor_addrtype =
965 (OM_uint32)argp->input_chan_bindings.acceptor_addrtype;
966 input_chan_bindings.acceptor_address.length =
967 (uint_t)argp->input_chan_bindings.acceptor_address.
968 GSS_BUFFER_T_len;
969 input_chan_bindings.acceptor_address.value =
970 (void *)argp->input_chan_bindings.acceptor_address.
971 GSS_BUFFER_T_val;
972 input_chan_bindings.application_data.length =
973 (uint_t)argp->input_chan_bindings.application_data.
974 GSS_BUFFER_T_len;
975 input_chan_bindings.application_data.value =
976 (void *)argp->input_chan_bindings.application_data.
977 GSS_BUFFER_T_val;
978 } else {
979 input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
980 input_chan_bindings.initiator_addrtype = 0;
981 input_chan_bindings.initiator_address.length = 0;
982 input_chan_bindings.initiator_address.value = 0;
983 input_chan_bindings.acceptor_addrtype = 0;
984 input_chan_bindings.acceptor_address.length = 0;
985 input_chan_bindings.acceptor_address.value = 0;
986 input_chan_bindings.application_data.length = 0;
987 input_chan_bindings.application_data.value = 0;
988 }
989
990 if (argp->input_token.GSS_BUFFER_T_len == 0) {
991 input_token_ptr = GSS_C_NO_BUFFER;
992 } else {
993 input_token_ptr = &input_token;
994 input_token.length = (size_t)
995 argp->input_token.GSS_BUFFER_T_len;
996 input_token.value = (void *)argp->input_token.GSS_BUFFER_T_val;
997 }
998
999 /* call the gssapi routine */
1000
1001 res->status = (OM_uint32)gss_init_sec_context(&res->minor_status,
1002 (gss_cred_id_t)argp->claimant_cred_handle.
1003 GSS_CRED_ID_T_val,
1004 &context_handle,
1005 internal_name,
1006 mech_type,
1007 argp->req_flags,
1008 argp->time_req,
1009 input_chan_bindings_ptr,
1010 input_token_ptr,
1011 &actual_mech_type,
1012 &output_token,
1013 &res->ret_flags,
1014 &res->time_rec);
1015
1016 /*
1017 * convert the output args from the parameter given in the call to the
1018 * variable in the XDR result
1019 */
1020
1021 if (res->status == (OM_uint32)GSS_S_COMPLETE ||
1022 res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
1023
1024 if (slot == NULL || slot->ctx != context_handle) {
1025 /*
1026 * Note that gssd_alloc_slot() will delete ctx's as long
1027 * as we don't call gssd_rel_slot().
1028 */
1029 slot = gssd_alloc_slot(context_handle);
1030 }
1031
1032 res->gssd_context_verifier = slot->verf;
1033
1034 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1035 res->context_handle.GSS_CTX_ID_T_val =
1036 (void *)malloc(sizeof (gss_ctx_id_t));
1037 if (!res->context_handle.GSS_CTX_ID_T_val) {
1038 free(name_type->elements);
1039 return (GSS_S_FAILURE);
1040 }
1041
1042 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1043 sizeof (gss_ctx_id_t));
1044
1045 res->output_token.GSS_BUFFER_T_len =
1046 (uint_t)output_token.length;
1047 res->output_token.GSS_BUFFER_T_val =
1048 (char *)output_token.value;
1049
1050 /*
1051 * the actual mech type parameter
1052 * is ready only upon GSS_S_COMPLETE
1053 */
1054 if (res->status == GSS_S_COMPLETE) {
1055 res->actual_mech_type.GSS_OID_len =
1056 (uint_t)actual_mech_type->length;
1057 res->actual_mech_type.GSS_OID_val =
1058 (void *)malloc(actual_mech_type->length);
1059 if (!res->actual_mech_type.GSS_OID_val) {
1060 free(name_type->elements);
1061 free(res->context_handle.GSS_CTX_ID_T_val);
1062 return (GSS_S_FAILURE);
1063 }
1064 memcpy(res->actual_mech_type.GSS_OID_val,
1065 (char *)actual_mech_type->elements,
1066 actual_mech_type->length);
1067 } else
1068 res->actual_mech_type.GSS_OID_len = 0;
1069 } else {
1070 syslog_gss_error(res->status, res->minor_status,
1071 "init_sec_context");
1072 if (context_handle != GSS_C_NO_CONTEXT) {
1073 (void) gss_delete_sec_context(&minor_status,
1074 &context_handle, NULL);
1075 }
1076 res->context_handle.GSS_CTX_ID_T_len = 0;
1077 res->actual_mech_type.GSS_OID_len = 0;
1078 res->output_token.GSS_BUFFER_T_len = 0;
1079 }
1080
1081 /*
1082 * now release the space allocated by the underlying gssapi mechanism
1083 * library for internal_name and for the name_type.
1084 */
1085
1086 gss_release_name(&minor_status, &internal_name);
1087 if (name_type != GSS_C_NULL_OID)
1088 free(name_type->elements);
1089
1090
1091 /* return to caller */
1092 return (TRUE);
1093 }
1094
1095 bool_t
gss_accept_sec_context_1_svc(argp,res,rqstp)1096 gss_accept_sec_context_1_svc(argp, res, rqstp)
1097 gss_accept_sec_context_arg *argp;
1098 gss_accept_sec_context_res *res;
1099 struct svc_req *rqstp;
1100 {
1101 uid_t uid;
1102 OM_uint32 minor_status;
1103 gss_ctx_id_t context_handle = NULL;
1104 gss_cred_id_t verifier_cred_handle;
1105 gss_buffer_desc external_name;
1106 gss_name_t internal_name = NULL;
1107
1108 gss_buffer_desc input_token_buffer;
1109 gss_buffer_t input_token_buffer_ptr;
1110 struct gss_channel_bindings_struct
1111 input_chan_bindings;
1112 gss_channel_bindings_t input_chan_bindings_ptr;
1113 gss_OID mech_type;
1114 gss_buffer_desc output_token;
1115 gss_cred_id_t delegated_cred_handle;
1116 bool_t context_verf_ok;
1117 struct gssd_ctx_slot *slot = NULL;
1118
1119 memset(res, 0, sizeof (*res));
1120
1121 if (gssd_debug)
1122 fprintf(stderr, gettext("gss_accept_sec_context\n"));
1123
1124 /*
1125 * if the request isn't from root, null out the result pointer
1126 * entries, so the next time through xdr_free won't try to
1127 * free unmalloc'd memory and then return NULL
1128 */
1129
1130 if (checkfrom(rqstp, &uid) == 0) {
1131 res->context_handle.GSS_CTX_ID_T_val = NULL;
1132 res->src_name.GSS_BUFFER_T_val = NULL;
1133 res->mech_type.GSS_OID_val = NULL;
1134 res->output_token.GSS_BUFFER_T_val = NULL;
1135 res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1136 return (FALSE);
1137 }
1138
1139 /* set the uid sent as the RPC argument */
1140
1141 uid = argp->uid;
1142 set_gssd_uid(uid);
1143
1144 /*
1145 * copy the supplied context handle into the local context handle, so
1146 * it can be supplied to the gss_accept_sec_context call
1147 */
1148
1149 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1150 argp->gssd_context_verifier, &context_verf_ok, &slot);
1151
1152 if (context_handle != GSS_C_NO_CONTEXT)
1153 /* verify the context_handle */
1154 if (!context_verf_ok) {
1155 res->context_handle.GSS_CTX_ID_T_val = NULL;
1156 res->src_name.GSS_BUFFER_T_val = NULL;
1157 res->mech_type.GSS_OID_val = NULL;
1158 res->output_token.GSS_BUFFER_T_val = NULL;
1159 res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1160 res->src_name.GSS_BUFFER_T_len = 0;
1161 res->context_handle.GSS_CTX_ID_T_len = 0;
1162 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1163 res->output_token.GSS_BUFFER_T_len = 0;
1164 res->mech_type.GSS_OID_len = 0;
1165 res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1166 res->minor_status = 0;
1167 return (TRUE);
1168 }
1169
1170 /*
1171 * copy the XDR structured arguments into their corresponding local
1172 * GSSAPI variable equivalents.
1173 */
1174
1175
1176 verifier_cred_handle =
1177 (argp->verifier_cred_handle.GSS_CRED_ID_T_len == 0 ?
1178 GSS_C_NO_CREDENTIAL :
1179 /*LINTED*/
1180 *((gss_cred_id_t *)argp->verifier_cred_handle.
1181 GSS_CRED_ID_T_val));
1182
1183 if (verifier_cred_handle != GSS_C_NO_CREDENTIAL)
1184 /* verify the verifier_cred_handle */
1185 if (argp->gssd_cred_verifier != gssd_time_verf) {
1186 res->context_handle.GSS_CTX_ID_T_val = NULL;
1187 res->src_name.GSS_BUFFER_T_val = NULL;
1188 res->mech_type.GSS_OID_val = NULL;
1189 res->output_token.GSS_BUFFER_T_val = NULL;
1190 res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1191 res->src_name.GSS_BUFFER_T_len = 0;
1192 res->context_handle.GSS_CTX_ID_T_len = 0;
1193 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1194 res->output_token.GSS_BUFFER_T_len = 0;
1195 res->mech_type.GSS_OID_len = 0;
1196 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
1197 res->minor_status = 0;
1198 return (TRUE);
1199 }
1200
1201 input_token_buffer_ptr = &input_token_buffer;
1202 input_token_buffer.length = (size_t)argp->input_token_buffer.
1203 GSS_BUFFER_T_len;
1204 input_token_buffer.value = (void *)argp->input_token_buffer.
1205 GSS_BUFFER_T_val;
1206
1207 if (argp->input_chan_bindings.present == YES) {
1208 input_chan_bindings_ptr = &input_chan_bindings;
1209 input_chan_bindings.initiator_addrtype =
1210 (OM_uint32)argp->input_chan_bindings.
1211 initiator_addrtype;
1212 input_chan_bindings.initiator_address.length =
1213 (uint_t)argp->input_chan_bindings.initiator_address.
1214 GSS_BUFFER_T_len;
1215 input_chan_bindings.initiator_address.value =
1216 (void *)argp->input_chan_bindings.initiator_address.
1217 GSS_BUFFER_T_val;
1218 input_chan_bindings.acceptor_addrtype =
1219 (OM_uint32)argp->input_chan_bindings.
1220 acceptor_addrtype;
1221 input_chan_bindings.acceptor_address.length =
1222 (uint_t)argp->input_chan_bindings.acceptor_address.
1223 GSS_BUFFER_T_len;
1224 input_chan_bindings.acceptor_address.value =
1225 (void *)argp->input_chan_bindings.acceptor_address.
1226 GSS_BUFFER_T_val;
1227 input_chan_bindings.application_data.length =
1228 (uint_t)argp->input_chan_bindings.application_data.
1229 GSS_BUFFER_T_len;
1230 input_chan_bindings.application_data.value =
1231 (void *)argp->input_chan_bindings.application_data.
1232 GSS_BUFFER_T_val;
1233 } else {
1234 input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
1235 input_chan_bindings.initiator_addrtype = 0;
1236 input_chan_bindings.initiator_address.length = 0;
1237 input_chan_bindings.initiator_address.value = 0;
1238 input_chan_bindings.acceptor_addrtype = 0;
1239 input_chan_bindings.acceptor_address.length = 0;
1240 input_chan_bindings.acceptor_address.value = 0;
1241 input_chan_bindings.application_data.length = 0;
1242 input_chan_bindings.application_data.value = 0;
1243 }
1244
1245
1246 /* call the gssapi routine */
1247
1248 res->status = (OM_uint32)gss_accept_sec_context(&res->minor_status,
1249 &context_handle,
1250 verifier_cred_handle,
1251 input_token_buffer_ptr,
1252 input_chan_bindings_ptr,
1253 &internal_name,
1254 &mech_type,
1255 &output_token,
1256 &res->ret_flags,
1257 &res->time_rec,
1258 &delegated_cred_handle);
1259
1260 /* convert the src name from internal to external format */
1261
1262 if (res->status == (OM_uint32)GSS_S_COMPLETE ||
1263 res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
1264
1265 /*
1266 * upon GSS_S_CONTINUE_NEEDED only the following
1267 * parameters are ready: minor, ctxt, and output token
1268 */
1269 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1270 res->context_handle.GSS_CTX_ID_T_val =
1271 (void *)malloc(sizeof (gss_ctx_id_t));
1272 if (!res->context_handle.GSS_CTX_ID_T_val) {
1273 res->status = (OM_uint32)GSS_S_FAILURE;
1274 res->minor_status = 0;
1275 return (TRUE);
1276 }
1277
1278 if (slot == NULL || slot->ctx != context_handle) {
1279 /*
1280 * Note that gssd_alloc_slot() will delete ctx's as long
1281 * as we don't call gssd_rel_slot().
1282 */
1283 slot = gssd_alloc_slot(context_handle);
1284 }
1285
1286 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1287 sizeof (gss_ctx_id_t));
1288 res->gssd_context_verifier = slot->verf;
1289
1290 res->output_token.GSS_BUFFER_T_len =
1291 (uint_t)output_token.length;
1292 res->output_token.GSS_BUFFER_T_val =
1293 (char *)output_token.value;
1294
1295 if (res->status == GSS_S_COMPLETE) {
1296 if (gss_export_name(&minor_status, internal_name,
1297 &external_name)
1298 != GSS_S_COMPLETE) {
1299
1300 res->status = (OM_uint32)GSS_S_FAILURE;
1301 res->minor_status = minor_status;
1302 gss_release_name(&minor_status, &internal_name);
1303 gss_delete_sec_context(&minor_status,
1304 &context_handle, NULL);
1305 free(res->context_handle.GSS_CTX_ID_T_val);
1306 res->context_handle.GSS_CTX_ID_T_val = NULL;
1307 res->context_handle.GSS_CTX_ID_T_len = 0;
1308 gss_release_buffer(&minor_status,
1309 &output_token);
1310 res->output_token.GSS_BUFFER_T_len = 0;
1311 res->output_token.GSS_BUFFER_T_val = NULL;
1312 return (TRUE);
1313 }
1314 res->src_name.GSS_BUFFER_T_len =
1315 (uint_t)external_name.length;
1316 res->src_name.GSS_BUFFER_T_val =
1317 (void *)external_name.value;
1318
1319 res->delegated_cred_handle.GSS_CRED_ID_T_len =
1320 sizeof (gss_cred_id_t);
1321 res->delegated_cred_handle.GSS_CRED_ID_T_val =
1322 (void *)malloc(sizeof (gss_cred_id_t));
1323 if (!res->delegated_cred_handle.GSS_CRED_ID_T_val) {
1324 free(res->context_handle.GSS_CTX_ID_T_val);
1325 gss_release_name(&minor_status, &internal_name);
1326 gss_delete_sec_context(&minor_status,
1327 &context_handle, NULL);
1328 gss_release_buffer(&minor_status,
1329 &external_name);
1330 res->status = (OM_uint32)GSS_S_FAILURE;
1331 res->minor_status = 0;
1332 return (TRUE);
1333 }
1334 memcpy(res->delegated_cred_handle.GSS_CRED_ID_T_val,
1335 &delegated_cred_handle,
1336 sizeof (gss_cred_id_t));
1337
1338 res->mech_type.GSS_OID_len = (uint_t)mech_type->length;
1339 res->mech_type.GSS_OID_val =
1340 (void *)malloc(mech_type->length);
1341 if (!res->mech_type.GSS_OID_val) {
1342 free(res->context_handle.GSS_CTX_ID_T_val);
1343 free(res->delegated_cred_handle.GSS_CRED_ID_T_val);
1344 gss_release_name(&minor_status, &internal_name);
1345 gss_delete_sec_context(&minor_status,
1346 &context_handle, NULL);
1347 gss_release_buffer(&minor_status, &external_name);
1348 res->status = (OM_uint32)GSS_S_FAILURE;
1349 res->minor_status = 0;
1350 return (TRUE);
1351 }
1352 memcpy(res->mech_type.GSS_OID_val, mech_type->elements,
1353 mech_type->length);
1354
1355 /* release the space allocated for internal_name */
1356 gss_release_name(&minor_status, &internal_name);
1357
1358 } else { /* GSS_S_CONTINUE_NEEDED */
1359 res->src_name.GSS_BUFFER_T_len = 0;
1360 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1361 res->mech_type.GSS_OID_len = 0;
1362 }
1363 } else {
1364 syslog_gss_error(res->status, res->minor_status,
1365 "accept_sec_context");
1366
1367 if (context_handle != GSS_C_NO_CONTEXT) {
1368 (void) gss_delete_sec_context(&minor_status,
1369 &context_handle, NULL);
1370 }
1371 res->src_name.GSS_BUFFER_T_len = 0;
1372 res->context_handle.GSS_CTX_ID_T_len = 0;
1373 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1374 res->output_token.GSS_BUFFER_T_len =
1375 (uint_t)output_token.length;
1376 res->output_token.GSS_BUFFER_T_val =
1377 (char *)output_token.value;
1378
1379 res->mech_type.GSS_OID_len = 0;
1380 }
1381
1382 /* return to caller */
1383
1384 return (TRUE);
1385 }
1386
1387 bool_t
gss_process_context_token_1_svc(argp,res,rqstp)1388 gss_process_context_token_1_svc(argp, res, rqstp)
1389 gss_process_context_token_arg *argp;
1390 gss_process_context_token_res *res;
1391 struct svc_req *rqstp;
1392 {
1393
1394 uid_t uid;
1395 gss_buffer_desc token_buffer;
1396 gss_ctx_id_t context_handle;
1397 bool_t context_verf_ok;
1398
1399 memset(res, 0, sizeof (*res));
1400
1401 if (gssd_debug)
1402 fprintf(stderr, gettext("gss_process_context_token\n"));
1403
1404 if (checkfrom(rqstp, &uid) == 0)
1405 return (FALSE);
1406
1407 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1408 argp->gssd_context_verifier, &context_verf_ok, NULL);
1409
1410 /* verify the context_handle */
1411
1412 if (!context_verf_ok) {
1413 res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1414 res->minor_status = 0;
1415 return (TRUE);
1416 }
1417
1418 /* set the uid sent as the RPC argument */
1419
1420 uid = argp->uid;
1421 set_gssd_uid(uid);
1422
1423 /*
1424 * copy the XDR structured arguments into their corresponding local
1425 * GSSAPI variable equivalents.
1426 */
1427
1428 token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
1429 token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
1430
1431
1432 /* call the gssapi routine */
1433
1434 res->status = (OM_uint32)gss_process_context_token(&res->minor_status,
1435 context_handle,
1436 &token_buffer);
1437
1438 if (GSS_ERROR(res->status))
1439 syslog_gss_error(res->status, res->minor_status,
1440 "process_context_token");
1441
1442 /* return to caller */
1443
1444 return (TRUE);
1445 }
1446
1447 bool_t
gss_delete_sec_context_1_svc(argp,res,rqstp)1448 gss_delete_sec_context_1_svc(argp, res, rqstp)
1449 gss_delete_sec_context_arg *argp;
1450 gss_delete_sec_context_res *res;
1451 struct svc_req *rqstp;
1452 {
1453 uid_t uid;
1454 gss_ctx_id_t context_handle;
1455 gss_buffer_desc output_token;
1456 bool_t context_verf_ok;
1457 struct gssd_ctx_slot *slot = NULL;
1458
1459 memset(res, 0, sizeof (*res));
1460
1461 if (gssd_debug)
1462 fprintf(stderr, gettext("gss_delete_sec_context\n"));
1463
1464
1465 /*
1466 * copy the supplied context handle into the local context handle, so it
1467 * can be supplied to the gss_delete_sec_context call
1468 */
1469 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1470 argp->gssd_context_verifier, &context_verf_ok, &slot);
1471
1472 /* verify the context_handle */
1473 if (!context_verf_ok) {
1474 res->context_handle.GSS_CTX_ID_T_val = NULL;
1475 res->context_handle.GSS_CTX_ID_T_len = 0;
1476 res->output_token.GSS_BUFFER_T_val = NULL;
1477 res->output_token.GSS_BUFFER_T_len = 0;
1478 res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1479 res->minor_status = 0;
1480 return (TRUE);
1481 }
1482
1483 /*
1484 * if the request isn't from root, null out the result pointer
1485 * entries, so the next time through xdr_free won't try to
1486 * free unmalloc'd memory and then return NULL
1487 */
1488
1489 if (checkfrom(rqstp, &uid) == 0) {
1490 res->context_handle.GSS_CTX_ID_T_val = NULL;
1491 res->output_token.GSS_BUFFER_T_val = NULL;
1492 return (FALSE);
1493 }
1494
1495 /* call the gssapi routine */
1496
1497 res->status = (OM_uint32)gss_delete_sec_context(&res->minor_status,
1498 &context_handle,
1499 &output_token);
1500
1501 /*
1502 * convert the output args from the parameter given in the call to the
1503 * variable in the XDR result. If the delete succeeded, return a zero
1504 * context handle.
1505 */
1506
1507 if (res->status == GSS_S_COMPLETE) {
1508 if (context_handle != GSS_C_NO_CONTEXT)
1509 return (GSS_S_FAILURE);
1510 res->context_handle.GSS_CTX_ID_T_len = 0;
1511 res->context_handle.GSS_CTX_ID_T_val = NULL;
1512 res->output_token.GSS_BUFFER_T_len =
1513 (uint_t)output_token.length;
1514 res->output_token.GSS_BUFFER_T_val =
1515 (char *)output_token.value;
1516
1517 if (slot != NULL) {
1518 /*
1519 * gss_delete_sec_context deletes the context if it
1520 * succeeds so clear slot->ctx to avoid a dangling
1521 * reference.
1522 */
1523 slot->ctx = GSS_C_NO_CONTEXT;
1524 gssd_rel_slot(slot);
1525 }
1526 } else {
1527 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1528 res->context_handle.GSS_CTX_ID_T_val =
1529 (void *)malloc(sizeof (gss_ctx_id_t));
1530 if (!res->context_handle.GSS_CTX_ID_T_val) {
1531 return (GSS_S_FAILURE);
1532 }
1533
1534 if (slot == NULL || slot->ctx != context_handle) {
1535 /*
1536 * Note that gssd_alloc_slot() will delete ctx's as long
1537 * as we don't call gssd_rel_slot().
1538 */
1539 slot = gssd_alloc_slot(context_handle);
1540 /*
1541 * Note that no verifier is returned in the .x
1542 * protocol. So if the context changes, we won't
1543 * be able to release it now. So it will have to
1544 * be LRUed out.
1545 */
1546 }
1547
1548 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1549 sizeof (gss_ctx_id_t));
1550
1551 res->output_token.GSS_BUFFER_T_len = 0;
1552 res->output_token.GSS_BUFFER_T_val = NULL;
1553 }
1554
1555 /* return to caller */
1556
1557
1558 return (TRUE);
1559 }
1560
1561
1562 bool_t
gss_export_sec_context_1_svc(argp,res,rqstp)1563 gss_export_sec_context_1_svc(argp, res, rqstp)
1564 gss_export_sec_context_arg *argp;
1565 gss_export_sec_context_res *res;
1566 struct svc_req *rqstp;
1567 {
1568
1569 uid_t uid;
1570 gss_ctx_id_t context_handle;
1571 gss_buffer_desc output_token;
1572 bool_t context_verf_ok;
1573 struct gssd_ctx_slot *slot = NULL;
1574
1575 memset(res, 0, sizeof (*res));
1576
1577 if (gssd_debug)
1578 fprintf(stderr, "gss_export_sec_context\n");
1579
1580 /*
1581 * if the request isn't from root, null out the result pointer
1582 * entries, so the next time through xdr_free won't try to
1583 * free unmalloc'd memory and then return NULL
1584 */
1585
1586 if (checkfrom(rqstp, &uid) == 0) {
1587 res->context_handle.GSS_CTX_ID_T_val = NULL;
1588 res->output_token.GSS_BUFFER_T_val = NULL;
1589 return (FALSE);
1590 }
1591
1592 /*
1593 * copy the supplied context handle into the local context handle, so it
1594 * can be supplied to the gss_export_sec_context call
1595 */
1596
1597 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1598 argp->gssd_context_verifier, &context_verf_ok, &slot);
1599
1600 /* verify the context_handle */
1601
1602 if (!context_verf_ok) {
1603 res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1604 /* the rest of "res" was cleared by a previous memset() */
1605 return (TRUE);
1606 }
1607
1608 /* call the gssapi routine */
1609
1610 res->status = (OM_uint32)gss_export_sec_context(&res->minor_status,
1611 &context_handle,
1612 &output_token);
1613
1614 /*
1615 * convert the output args from the parameter given in the call to the
1616 * variable in the XDR result. If the delete succeeded, return a zero context
1617 * handle.
1618 */
1619 if (res->status == GSS_S_COMPLETE) {
1620 if (context_handle != GSS_C_NO_CONTEXT)
1621 return (GSS_S_FAILURE);
1622 res->context_handle.GSS_CTX_ID_T_len = 0;
1623 res->context_handle.GSS_CTX_ID_T_val = NULL;
1624 res->output_token.GSS_BUFFER_T_len =
1625 (uint_t)output_token.length;
1626 res->output_token.GSS_BUFFER_T_val =
1627 (char *)output_token.value;
1628
1629 if (slot != NULL) {
1630 /*
1631 * gss_export_sec_context deletes the context if it
1632 * succeeds so set slot->ctx to avoid a dangling
1633 * reference.
1634 */
1635 slot->ctx = GSS_C_NO_CONTEXT;
1636 gssd_rel_slot(slot);
1637 }
1638 } else {
1639 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1640 res->context_handle.GSS_CTX_ID_T_val =
1641 (void *)malloc(sizeof (gss_ctx_id_t));
1642
1643 if (slot == NULL || slot->ctx != context_handle) {
1644 /*
1645 * Note that gssd_alloc_slot() will delete ctx's as long
1646 * as we don't call gssd_rel_slot().
1647 */
1648 slot = gssd_alloc_slot(context_handle);
1649 /*
1650 * Note that no verifier is returned in the .x
1651 * protocol. So if the context changes, we won't
1652 * be able to release it now. So it will have to
1653 * be LRUed out.
1654 */
1655 }
1656
1657 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1658 sizeof (gss_ctx_id_t));
1659 res->output_token.GSS_BUFFER_T_len = 0;
1660 res->output_token.GSS_BUFFER_T_val = NULL;
1661 }
1662
1663
1664 /* return to caller */
1665
1666 return (TRUE);
1667 }
1668
1669 /*
1670 * This routine doesn't appear to ever be called.
1671 */
1672 bool_t
gss_import_sec_context_1_svc(argp,res,rqstp)1673 gss_import_sec_context_1_svc(argp, res, rqstp)
1674 gss_import_sec_context_arg *argp;
1675 gss_import_sec_context_res *res;
1676 struct svc_req *rqstp;
1677 {
1678
1679 uid_t uid;
1680 gss_ctx_id_t context_handle;
1681 gss_buffer_desc input_token;
1682 gss_buffer_t input_token_ptr;
1683
1684 memset(res, 0, sizeof (*res));
1685
1686 if (gssd_debug)
1687 fprintf(stderr, "gss_export_sec_context\n");
1688
1689 /*
1690 * if the request isn't from root, null out the result pointer
1691 * entries, so the next time through xdr_free won't try to
1692 * free unmalloc'd memory and then return NULL
1693 */
1694
1695 if (checkfrom(rqstp, &uid) == 0) {
1696 res->context_handle.GSS_CTX_ID_T_val = NULL;
1697 return (FALSE);
1698 }
1699
1700
1701 if (argp->input_token.GSS_BUFFER_T_len == 0) {
1702 input_token_ptr = GSS_C_NO_BUFFER;
1703 } else {
1704 input_token_ptr = &input_token;
1705 input_token.length = (size_t)
1706 argp->input_token.GSS_BUFFER_T_len;
1707 input_token.value = (void *) argp->input_token.GSS_BUFFER_T_val;
1708 }
1709
1710
1711 /* call the gssapi routine */
1712
1713 res->status = (OM_uint32) gss_import_sec_context(&res->minor_status,
1714 input_token_ptr,
1715 &context_handle);
1716
1717 /*
1718 * convert the output args from the parameter given in the call to the
1719 * variable in the XDR result. If the delete succeeded, return a zero context
1720 * handle.
1721 */
1722 if (res->status == GSS_S_COMPLETE) {
1723 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1724 res->context_handle.GSS_CTX_ID_T_val =
1725 (void *) malloc(sizeof (gss_ctx_id_t));
1726 memcpy(res->context_handle.GSS_CTX_ID_T_val, &context_handle,
1727 sizeof (gss_ctx_id_t));
1728 } else {
1729 res->context_handle.GSS_CTX_ID_T_len = 0;
1730 res->context_handle.GSS_CTX_ID_T_val = NULL;
1731 }
1732
1733
1734 /* return to caller */
1735
1736 return (TRUE);
1737 }
1738
1739 bool_t
gss_context_time_1_svc(argp,res,rqstp)1740 gss_context_time_1_svc(argp, res, rqstp)
1741 gss_context_time_arg *argp;
1742 gss_context_time_res *res;
1743 struct svc_req *rqstp;
1744 {
1745 uid_t uid;
1746
1747 memset(res, 0, sizeof (*res));
1748
1749 if (gssd_debug)
1750 fprintf(stderr, gettext("gss_context_time\n"));
1751
1752 /*
1753 * if the request isn't from root, null out the result pointer
1754 * entries, so the next time through xdr_free won't try to
1755 * free unmalloc'd memory and then return NULL
1756 */
1757
1758 if (checkfrom(rqstp, &uid) == 0)
1759 return (FALSE);
1760
1761 /* set the uid sent as the RPC argument */
1762
1763 uid = argp->uid;
1764 set_gssd_uid(uid);
1765
1766 /* Semantics go here */
1767
1768 return (TRUE);
1769 }
1770
1771 bool_t
gss_sign_1_svc(argp,res,rqstp)1772 gss_sign_1_svc(argp, res, rqstp)
1773 gss_sign_arg *argp;
1774 gss_sign_res *res;
1775 struct svc_req *rqstp;
1776 {
1777
1778 uid_t uid;
1779
1780 gss_buffer_desc message_buffer;
1781 gss_buffer_desc msg_token;
1782 gss_ctx_id_t context_handle;
1783 bool_t context_verf_ok;
1784
1785 memset(res, 0, sizeof (*res));
1786
1787 if (gssd_debug)
1788 fprintf(stderr, gettext("gss_sign\n"));
1789
1790 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1791 argp->gssd_context_verifier, &context_verf_ok, NULL);
1792
1793 /* verify the context_handle */
1794 if (!context_verf_ok) {
1795 res->msg_token.GSS_BUFFER_T_val = NULL;
1796 res->msg_token.GSS_BUFFER_T_len = 0;
1797 res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1798 res->minor_status = 0;
1799 return (TRUE);
1800 }
1801
1802
1803 /*
1804 * if the request isn't from root, null out the result pointer
1805 * entries, so the next time through xdr_free won't try to
1806 * free unmalloc'd memory and then return NULL
1807 */
1808
1809 if (checkfrom(rqstp, &uid) == 0) {
1810 res->msg_token.GSS_BUFFER_T_val = NULL;
1811 return (FALSE);
1812 }
1813
1814 /*
1815 * copy the XDR structured arguments into their corresponding local
1816 * GSSAPI variable equivalents.
1817 */
1818
1819 message_buffer.length = (size_t)argp->message_buffer.GSS_BUFFER_T_len;
1820 message_buffer.value = (void *)argp->message_buffer.GSS_BUFFER_T_val;
1821
1822 /* call the gssapi routine */
1823
1824 res->status = (OM_uint32)gss_sign(&res->minor_status,
1825 context_handle,
1826 argp->qop_req,
1827 (gss_buffer_t)&message_buffer,
1828 (gss_buffer_t)&msg_token);
1829 /*
1830 * convert the output args from the parameter given in the call to
1831 * the variable in the XDR result
1832 */
1833
1834 if (res->status == GSS_S_COMPLETE) {
1835 res->msg_token.GSS_BUFFER_T_len = (uint_t)msg_token.length;
1836 res->msg_token.GSS_BUFFER_T_val = (char *)msg_token.value;
1837 } else
1838 syslog_gss_error(res->status, res->minor_status, "sign");
1839
1840 /* return to caller */
1841
1842 return (TRUE);
1843 }
1844
1845 bool_t
gss_verify_1_svc(argp,res,rqstp)1846 gss_verify_1_svc(argp, res, rqstp)
1847 gss_verify_arg *argp;
1848 gss_verify_res *res;
1849 struct svc_req *rqstp;
1850 {
1851
1852 uid_t uid;
1853
1854 gss_buffer_desc message_buffer;
1855 gss_buffer_desc token_buffer;
1856 gss_ctx_id_t context_handle;
1857 bool_t context_verf_ok;
1858
1859 memset(res, 0, sizeof (*res));
1860
1861 if (gssd_debug)
1862 fprintf(stderr, gettext("gss_verify\n"));
1863
1864 gssd_convert_context_handle(&argp->context_handle, &context_handle,
1865 argp->gssd_context_verifier, &context_verf_ok, NULL);
1866
1867 /* verify the context_handle */
1868 if (!context_verf_ok) {
1869 res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1870 res->minor_status = 0;
1871 return (TRUE);
1872 }
1873
1874 /*
1875 * if the request isn't from root, null out the result pointer
1876 * entries, so the next time through xdr_free won't try to
1877 * free unmalloc'd memory and then return NULL
1878 */
1879
1880 if (checkfrom(rqstp, &uid) == 0)
1881 return (FALSE);
1882
1883 /*
1884 * copy the XDR structured arguments into their corresponding local
1885 * GSSAPI variable equivalents.
1886 */
1887
1888 message_buffer.length = (size_t)argp->message_buffer.GSS_BUFFER_T_len;
1889 message_buffer.value = (void *)argp->message_buffer.GSS_BUFFER_T_val;
1890
1891 token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
1892 token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
1893
1894 /* call the gssapi routine */
1895
1896 res->status = (OM_uint32)gss_verify(&res->minor_status,
1897 context_handle,
1898 &message_buffer,
1899 &token_buffer,
1900 &res->qop_state);
1901
1902 if (GSS_ERROR(res->status))
1903 syslog_gss_error(res->status, res->minor_status, "verify");
1904
1905 /* return to caller */
1906 return (TRUE);
1907 }
1908
1909 /* EXPORT DELETE START */
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 /* EXPORT DELETE END */
2076
2077 bool_t
gss_display_status_1_svc(argp,res,rqstp)2078 gss_display_status_1_svc(argp, res, rqstp)
2079 gss_display_status_arg *argp;
2080 gss_display_status_res *res;
2081 struct svc_req *rqstp;
2082 {
2083 uid_t uid;
2084 gss_OID mech_type;
2085 gss_OID_desc mech_type_desc;
2086 gss_buffer_desc status_string;
2087
2088 memset(res, 0, sizeof (*res));
2089
2090 if (gssd_debug)
2091 fprintf(stderr, gettext("gss_display_status\n"));
2092
2093 /*
2094 * if the request isn't from root, null out the result pointer
2095 * entries, so the next time through xdr_free won't try to
2096 * free unmalloc'd memory and then return NULL
2097 */
2098
2099 if (checkfrom(rqstp, &uid) == 0) {
2100 res->status_string.GSS_BUFFER_T_val = NULL;
2101 return (FALSE);
2102 }
2103
2104 /* set the uid sent as the RPC argument */
2105
2106 uid = argp->uid;
2107 set_gssd_uid(uid);
2108
2109 /*
2110 * copy the XDR structured arguments into their corresponding local
2111 * GSSAPI variables.
2112 */
2113
2114 if (argp->mech_type.GSS_OID_len == 0)
2115 mech_type = GSS_C_NULL_OID;
2116 else {
2117 mech_type = &mech_type_desc;
2118 mech_type_desc.length = (OM_uint32) argp->mech_type.GSS_OID_len;
2119 mech_type_desc.elements = (void *) argp->mech_type.GSS_OID_val;
2120 }
2121
2122
2123 /* call the gssapi routine */
2124
2125 res->status = (OM_uint32) gss_display_status(&res->minor_status,
2126 argp->status_value,
2127 argp->status_type,
2128 mech_type,
2129 (OM_uint32 *)&res->message_context,
2130 &status_string);
2131
2132 /*
2133 * convert the output args from the parameter given in the call to the
2134 * variable in the XDR result
2135 */
2136
2137 if (res->status == GSS_S_COMPLETE) {
2138 res->status_string.GSS_BUFFER_T_len =
2139 (uint_t)status_string.length;
2140 res->status_string.GSS_BUFFER_T_val =
2141 (char *)status_string.value;
2142 }
2143
2144 return (TRUE);
2145
2146 }
2147
2148 /*ARGSUSED*/
2149 bool_t
gss_indicate_mechs_1_svc(argp,res,rqstp)2150 gss_indicate_mechs_1_svc(argp, res, rqstp)
2151 void *argp;
2152 gss_indicate_mechs_res *res;
2153 struct svc_req *rqstp;
2154 {
2155 gss_OID_set oid_set;
2156 uid_t uid;
2157
2158 memset(res, 0, sizeof (*res));
2159
2160 if (gssd_debug)
2161 fprintf(stderr, gettext("gss_indicate_mechs\n"));
2162
2163 res->mech_set.GSS_OID_SET_val = NULL;
2164
2165 /*
2166 * if the request isn't from root, null out the result pointer
2167 * entries, so the next time through xdr_free won't try to
2168 * free unmalloc'd memory and then return NULL
2169 */
2170
2171 if (checkfrom(rqstp, &uid) == 0) {
2172 return (FALSE);
2173 }
2174
2175 res->status = gss_indicate_mechs(&res->minor_status, &oid_set);
2176
2177 if (res->status == GSS_S_COMPLETE) {
2178 int i, j;
2179
2180 res->mech_set.GSS_OID_SET_len = oid_set->count;
2181 res->mech_set.GSS_OID_SET_val = (void *)
2182 malloc(oid_set->count * sizeof (GSS_OID));
2183 if (!res->mech_set.GSS_OID_SET_val) {
2184 return (GSS_S_FAILURE);
2185 }
2186 for (i = 0; i < oid_set->count; i++) {
2187 res->mech_set.GSS_OID_SET_val[i].GSS_OID_len =
2188 oid_set->elements[i].length;
2189 res->mech_set.GSS_OID_SET_val[i].GSS_OID_val =
2190 (char *)malloc(oid_set->elements[i].length);
2191 if (!res->mech_set.GSS_OID_SET_val[i].GSS_OID_val) {
2192 for (j = 0; j < (i -1); j++) {
2193 free
2194 (res->mech_set.GSS_OID_SET_val[i].GSS_OID_val);
2195 }
2196 free(res->mech_set.GSS_OID_SET_val);
2197 return (GSS_S_FAILURE);
2198 }
2199 memcpy(res->mech_set.GSS_OID_SET_val[i].GSS_OID_val,
2200 oid_set->elements[i].elements,
2201 oid_set->elements[i].length);
2202 }
2203 }
2204
2205 return (TRUE);
2206 }
2207
2208 bool_t
gss_inquire_cred_1_svc(argp,res,rqstp)2209 gss_inquire_cred_1_svc(argp, res, rqstp)
2210 gss_inquire_cred_arg *argp;
2211 gss_inquire_cred_res *res;
2212 struct svc_req *rqstp;
2213 {
2214
2215 uid_t uid;
2216
2217 OM_uint32 minor_status;
2218 gss_cred_id_t cred_handle;
2219 gss_buffer_desc external_name;
2220 gss_OID name_type;
2221 gss_name_t internal_name;
2222 gss_OID_set mechanisms;
2223 int i, j;
2224
2225 memset(res, 0, sizeof (*res));
2226
2227 if (gssd_debug)
2228 fprintf(stderr, gettext("gss_inquire_cred\n"));
2229
2230 /* verify the verifier_cred_handle */
2231
2232 if (argp->gssd_cred_verifier != gssd_time_verf) {
2233 res->name.GSS_BUFFER_T_val = NULL;
2234 res->name_type.GSS_OID_val = NULL;
2235 res->mechanisms.GSS_OID_SET_val = NULL;
2236 res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2237 res->minor_status = 0;
2238 return (TRUE);
2239 }
2240
2241 /*
2242 * if the request isn't from root, null out the result pointer
2243 * entries, so the next time through xdr_free won't try to
2244 * free unmalloc'd memory and then return NULL
2245 */
2246
2247 if (checkfrom(rqstp, &uid) == 0) {
2248 res->name.GSS_BUFFER_T_val = NULL;
2249 res->name_type.GSS_OID_val = NULL;
2250 res->mechanisms.GSS_OID_SET_val = NULL;
2251 return (FALSE);
2252 }
2253
2254 /* set the uid sent as the RPC argument */
2255
2256 uid = argp->uid;
2257 set_gssd_uid(uid);
2258
2259 cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2260 GSS_C_NO_CREDENTIAL :
2261 /*LINTED*/
2262 *((gss_cred_id_t *)argp->cred_handle.
2263 GSS_CRED_ID_T_val));
2264
2265 /* call the gssapi routine */
2266
2267 res->status = (OM_uint32)gss_inquire_cred(&res->minor_status,
2268 cred_handle,
2269 &internal_name,
2270 &res->lifetime,
2271 &res->cred_usage,
2272 &mechanisms);
2273
2274 if (res->status != GSS_S_COMPLETE) {
2275 syslog_gss_error(res->status, res->minor_status,
2276 "inquire_cred");
2277 return (TRUE);
2278 }
2279
2280 /* convert the returned name from internal to external format */
2281
2282 if (gss_display_name(&minor_status, internal_name,
2283 &external_name, &name_type)
2284 != GSS_S_COMPLETE) {
2285
2286 res->status = (OM_uint32)GSS_S_FAILURE;
2287 res->minor_status = minor_status;
2288
2289 gss_release_name(&minor_status, &internal_name);
2290
2291 if (mechanisms != GSS_C_NULL_OID_SET) {
2292 for (i = 0; i < mechanisms->count; i++)
2293 free(mechanisms->elements[i].elements);
2294 free(mechanisms->elements);
2295 free(mechanisms);
2296 }
2297
2298 return (TRUE);
2299 }
2300
2301 /*
2302 * convert the output args from the parameter given in the call to the
2303 * variable in the XDR result
2304 */
2305
2306
2307 res->name.GSS_BUFFER_T_len = (uint_t)external_name.length;
2308 res->name.GSS_BUFFER_T_val = (void *)external_name.value;
2309
2310 /*
2311 * we have to allocate storage for name_type here, since the value
2312 * returned from gss_display_name points to the underlying mechanism
2313 * static storage. If we didn't allocate storage, the next time
2314 * through this routine, the xdr_free() call at the beginning would
2315 * try to free up that static storage.
2316 */
2317
2318 res->name_type.GSS_OID_len = (uint_t)name_type->length;
2319 res->name_type.GSS_OID_val = (void *)malloc(name_type->length);
2320 if (!res->name_type.GSS_OID_val) {
2321 return (GSS_S_FAILURE);
2322 }
2323 memcpy(res->name_type.GSS_OID_val, name_type->elements,
2324 name_type->length);
2325
2326 if (mechanisms != GSS_C_NULL_OID_SET) {
2327 res->mechanisms.GSS_OID_SET_len =
2328 (uint_t)mechanisms->count;
2329 res->mechanisms.GSS_OID_SET_val = (GSS_OID *)
2330 malloc(sizeof (GSS_OID) * mechanisms->count);
2331 if (!res->mechanisms.GSS_OID_SET_val) {
2332 free(res->name_type.GSS_OID_val);
2333 return (GSS_S_FAILURE);
2334 }
2335 for (i = 0; i < mechanisms->count; i++) {
2336 res->mechanisms.GSS_OID_SET_val[i].GSS_OID_len =
2337 (uint_t)mechanisms->elements[i].length;
2338 res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val =
2339 (char *)malloc(mechanisms->elements[i].
2340 length);
2341 if (!res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val) {
2342 free(res->name_type.GSS_OID_val);
2343 for (j = 0; j < i; j++) {
2344 free(res->mechanisms.
2345 GSS_OID_SET_val[i].GSS_OID_val);
2346 }
2347 free(res->mechanisms.GSS_OID_SET_val);
2348 return (GSS_S_FAILURE);
2349 }
2350 memcpy(res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
2351 mechanisms->elements[i].elements,
2352 mechanisms->elements[i].length);
2353 }
2354 } else
2355 res->mechanisms.GSS_OID_SET_len = 0;
2356
2357 /* release the space allocated for internal_name and mechanisms */
2358 gss_release_name(&minor_status, &internal_name);
2359
2360 if (mechanisms != GSS_C_NULL_OID_SET) {
2361 for (i = 0; i < mechanisms->count; i++)
2362 free(mechanisms->elements[i].elements);
2363 free(mechanisms->elements);
2364 free(mechanisms);
2365 }
2366
2367 /* return to caller */
2368 return (TRUE);
2369 }
2370
2371
2372 bool_t
gss_inquire_cred_by_mech_1_svc(argp,res,rqstp)2373 gss_inquire_cred_by_mech_1_svc(argp, res, rqstp)
2374 gss_inquire_cred_by_mech_arg *argp;
2375 gss_inquire_cred_by_mech_res *res;
2376 struct svc_req *rqstp;
2377 {
2378
2379 uid_t uid;
2380
2381 gss_cred_id_t cred_handle;
2382 gss_OID_desc mech_type_desc;
2383 gss_OID mech_type = &mech_type_desc;
2384
2385 memset(res, 0, sizeof (*res));
2386
2387 if (gssd_debug)
2388 fprintf(stderr, gettext("gss_inquire_cred\n"));
2389
2390 /* verify the verifier_cred_handle */
2391
2392 if (argp->gssd_cred_verifier != gssd_time_verf) {
2393 res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2394 res->minor_status = 0;
2395 return (TRUE);
2396 }
2397
2398 /*
2399 * if the request isn't from root, null out the result pointer
2400 * entries, so the next time through xdr_free won't try to
2401 * free unmalloc'd memory and then return NULL
2402 */
2403
2404 if (checkfrom(rqstp, &uid) == 0) {
2405 return (FALSE);
2406 }
2407
2408 /* set the uid sent as the RPC argument */
2409
2410 uid = argp->uid;
2411 set_gssd_uid(uid);
2412
2413 cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2414 GSS_C_NO_CREDENTIAL :
2415 /*LINTED*/
2416 *((gss_cred_id_t *)argp->cred_handle.
2417 GSS_CRED_ID_T_val));
2418
2419 /* call the gssapi routine */
2420
2421 if (argp->mech_type.GSS_OID_len == 0)
2422 mech_type = GSS_C_NULL_OID;
2423 else {
2424 mech_type->length =
2425 (OM_uint32)argp->mech_type.GSS_OID_len;
2426 mech_type->elements =
2427 (void *)malloc(mech_type->length);
2428 if (!mech_type->elements) {
2429 return (GSS_S_FAILURE);
2430 }
2431 memcpy(mech_type->elements,
2432 argp->mech_type.GSS_OID_val,
2433 mech_type->length);
2434 }
2435 res->status = (OM_uint32)gss_inquire_cred_by_mech(
2436 &res->minor_status, cred_handle,
2437 mech_type, NULL, NULL,
2438 NULL, NULL);
2439
2440 /* return to caller */
2441 return (TRUE);
2442 }
2443
2444
2445 bool_t
gsscred_name_to_unix_cred_1_svc(argsp,res,rqstp)2446 gsscred_name_to_unix_cred_1_svc(argsp, res, rqstp)
2447 gsscred_name_to_unix_cred_arg *argsp;
2448 gsscred_name_to_unix_cred_res *res;
2449 struct svc_req *rqstp;
2450 {
2451 uid_t uid;
2452 gss_OID_desc oid;
2453 gss_name_t gssName;
2454 gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
2455 OM_uint32 minor;
2456 int gidsLen;
2457 gid_t *gids, gidOut;
2458
2459 if (gssd_debug)
2460 fprintf(stderr, gettext("gsscred_name_to_unix_cred\n"));
2461
2462 memset(res, 0, sizeof (*res));
2463
2464 /*
2465 * check the request originator
2466 */
2467 if (checkfrom(rqstp, &uid) == 0)
2468 return (FALSE);
2469
2470 /* set the uid from the rpc request */
2471 uid = argsp->uid;
2472 set_gssd_uid(uid);
2473
2474 /*
2475 * convert the principal name to gss internal format
2476 * need not malloc the input parameters
2477 */
2478 gssBuf.length = argsp->pname.GSS_BUFFER_T_len;
2479 gssBuf.value = (void*)argsp->pname.GSS_BUFFER_T_val;
2480 oid.length = argsp->name_type.GSS_OID_len;
2481 oid.elements = (void*)argsp->name_type.GSS_OID_val;
2482
2483 res->major = gss_import_name(&minor, &gssBuf, &oid, &gssName);
2484 if (res->major != GSS_S_COMPLETE)
2485 return (TRUE);
2486
2487 /* retrieve the mechanism type from the arguments */
2488 oid.length = argsp->mech_type.GSS_OID_len;
2489 oid.elements = (void*)argsp->mech_type.GSS_OID_val;
2490
2491 /* call the gss extensions to map the principal name to unix creds */
2492 res->major = gsscred_name_to_unix_cred(gssName, &oid, &uid, &gidOut,
2493 &gids, &gidsLen);
2494 gss_release_name(&minor, &gssName);
2495
2496 if (res->major == GSS_S_COMPLETE) {
2497 res->uid = uid;
2498 res->gid = gidOut;
2499 res->gids.GSSCRED_GIDS_val = gids;
2500 res->gids.GSSCRED_GIDS_len = gidsLen;
2501 }
2502
2503 return (TRUE);
2504 } /* gsscred_name_to_unix_cred_svc_1 */
2505
2506 bool_t
gsscred_expname_to_unix_cred_1_svc(argsp,res,rqstp)2507 gsscred_expname_to_unix_cred_1_svc(argsp, res, rqstp)
2508 gsscred_expname_to_unix_cred_arg *argsp;
2509 gsscred_expname_to_unix_cred_res *res;
2510 struct svc_req *rqstp;
2511 {
2512 uid_t uid;
2513 gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
2514 int gidsLen;
2515 gid_t *gids, gidOut;
2516
2517 if (gssd_debug)
2518 fprintf(stderr, gettext("gsscred_expname_to_unix_cred\n"));
2519
2520 memset(res, 0, sizeof (*res));
2521
2522 /*
2523 * check the request originator
2524 */
2525 if (checkfrom(rqstp, &uid) == 0)
2526 return (FALSE);
2527
2528 /* set the uid from the rpc request */
2529 uid = argsp->uid;
2530 set_gssd_uid(uid);
2531
2532 /*
2533 * extract the export name from arguments
2534 * need not malloc the input parameters
2535 */
2536 expName.length = argsp->expname.GSS_BUFFER_T_len;
2537 expName.value = (void*)argsp->expname.GSS_BUFFER_T_val;
2538
2539 res->major = gsscred_expname_to_unix_cred(&expName, &uid,
2540 &gidOut, &gids, &gidsLen);
2541
2542 if (res->major == GSS_S_COMPLETE) {
2543 res->uid = uid;
2544 res->gid = gidOut;
2545 res->gids.GSSCRED_GIDS_val = gids;
2546 res->gids.GSSCRED_GIDS_len = gidsLen;
2547 }
2548
2549 return (TRUE);
2550 } /* gsscred_expname_to_unix_cred_1_svc */
2551
2552 bool_t
gss_get_group_info_1_svc(argsp,res,rqstp)2553 gss_get_group_info_1_svc(argsp, res, rqstp)
2554 gss_get_group_info_arg *argsp;
2555 gss_get_group_info_res *res;
2556 struct svc_req *rqstp;
2557 {
2558 uid_t uid;
2559 int gidsLen;
2560 gid_t *gids, gidOut;
2561
2562 if (gssd_debug)
2563 fprintf(stderr, gettext("gss_get_group_info\n"));
2564
2565 memset(res, 0, sizeof (*res));
2566
2567 /*
2568 * check the request originator
2569 */
2570 if (checkfrom(rqstp, &uid) == 0)
2571 return (FALSE);
2572
2573 /* set the uid from the rpc request */
2574 uid = argsp->uid;
2575 set_gssd_uid(uid);
2576
2577 /*
2578 * extract the uid from the arguments
2579 */
2580 uid = argsp->puid;
2581 res->major = gss_get_group_info(uid, &gidOut, &gids, &gidsLen);
2582 if (res->major == GSS_S_COMPLETE) {
2583 res->gid = gidOut;
2584 res->gids.GSSCRED_GIDS_val = gids;
2585 res->gids.GSSCRED_GIDS_len = gidsLen;
2586 }
2587
2588 return (TRUE);
2589 } /* gss_get_group_info_1_svc */
2590
2591 /*ARGSUSED*/
2592 bool_t
gss_get_kmod_1_svc(argsp,res,rqstp)2593 gss_get_kmod_1_svc(argsp, res, rqstp)
2594 gss_get_kmod_arg *argsp;
2595 gss_get_kmod_res *res;
2596 struct svc_req *rqstp;
2597 {
2598 gss_OID_desc oid;
2599 char *kmodName;
2600
2601 if (gssd_debug)
2602 fprintf(stderr, gettext("gss_get_kmod\n"));
2603
2604 res->module_follow = FALSE;
2605 oid.length = argsp->mech_oid.GSS_OID_len;
2606 oid.elements = (void *)argsp->mech_oid.GSS_OID_val;
2607 kmodName = __gss_get_kmodName(&oid);
2608
2609 if (kmodName != NULL) {
2610 res->module_follow = TRUE;
2611 res->gss_get_kmod_res_u.modname = kmodName;
2612 }
2613
2614 return (TRUE);
2615 }
2616
2617 /*
2618 * Returns 1 if caller is ok, else 0.
2619 * If caller ok, the uid is returned in uidp.
2620 */
2621 static int
checkfrom(rqstp,uidp)2622 checkfrom(rqstp, uidp)
2623 struct svc_req *rqstp;
2624 uid_t *uidp;
2625 {
2626 SVCXPRT *xprt = rqstp->rq_xprt;
2627 struct authunix_parms *aup;
2628 uid_t uid;
2629
2630 /* check client agent uid to ensure it is privileged */
2631 if (__rpc_get_local_uid(xprt, &uid) < 0) {
2632 syslog(LOG_ERR, gettext("__rpc_get_local_uid failed %s %s"),
2633 xprt->xp_netid, xprt->xp_tp);
2634 goto weakauth;
2635 }
2636 if (gssd_debug)
2637 fprintf(stderr, gettext("checkfrom: local_uid %d\n"), uid);
2638 if (uid != 0) {
2639 syslog(LOG_ERR,
2640 gettext("checkfrom: caller (uid %d) not privileged"),
2641 uid);
2642 goto weakauth;
2643 }
2644
2645 /*
2646 * Request came from local privileged process.
2647 * Proceed to get uid of client if needed by caller.
2648 */
2649 if (uidp) {
2650 if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
2651 syslog(LOG_ERR, gettext("checkfrom: not UNIX credentials"));
2652 goto weakauth;
2653 }
2654 /*LINTED*/
2655 aup = (struct authunix_parms *)rqstp->rq_clntcred;
2656 *uidp = aup->aup_uid;
2657 if (gssd_debug) {
2658 fprintf(stderr,
2659 gettext("checkfrom: caller's uid %d\n"), *uidp);
2660 }
2661 }
2662 return (1);
2663
2664 weakauth:
2665 svcerr_weakauth(xprt);
2666 return (0);
2667 }
2668