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