Print this page
NEX-18462 SMB can't view ACL if posix ID can't be mapped
Review by: Gordon Ross <gordon.ross@nexenta.com>
Review by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/idmap/idmap_kapi.c
+++ new/usr/src/uts/common/idmap/idmap_kapi.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + *
26 + * Copyright 2018 Nexenta Systems, Inc.
25 27 */
26 28
27 29 /*
28 30 * Windows to Solaris Identity Mapping kernel API
29 31 * This module provides an API to map Windows SIDs to
30 32 * Solaris UID and GIDs.
31 33 */
32 34
33 35
34 36 #include <sys/types.h>
35 37 #include <sys/ksynch.h>
36 38 #include <sys/door.h>
37 39 #include <rpc/rpc_msg.h>
38 40 #include <rpc/xdr.h>
39 41 #include <rpc/auth.h>
40 42 #include <rpc/rpc_sztypes.h>
41 43 #ifdef DEBUG
42 44 #include <sys/cmn_err.h>
43 45 #endif /* DEBUG */
44 46 #include <sys/proc.h>
45 47 #include <sys/sunddi.h>
46 48 #include <sys/param.h>
47 49 #include <sys/atomic.h>
48 50 #include <sys/sysmacros.h>
49 51 #include <sys/disp.h>
50 52 #include <sys/kidmap.h>
51 53 #include <sys/zone.h>
52 54 #include <rpcsvc/idmap_prot.h>
53 55 #include "kidmap_priv.h"
54 56
55 57
56 58 /*
57 59 * Defined types
58 60 */
59 61
60 62
61 63 /*
62 64 * This structure holds pointers for the
63 65 * batch mapping results.
64 66 */
65 67 typedef struct idmap_get_res {
66 68 idmap_id_type idtype;
67 69 uid_t *uid;
68 70 gid_t *gid;
69 71 uid_t *pid;
70 72 int *is_user;
71 73 const char **sid_prefix;
72 74 uint32_t *rid;
73 75 idmap_stat *stat;
74 76 } idmap_get_res;
75 77
76 78 /* Batch mapping handle structure */
77 79 struct idmap_get_handle {
78 80 struct idmap_zone_specific *zs;
79 81 int mapping_num;
80 82 int mapping_size;
81 83 idmap_mapping *mapping;
82 84 idmap_get_res *result;
83 85 };
84 86
85 87
86 88 /* Zone specific data */
87 89 typedef struct idmap_zone_specific {
88 90 zoneid_t zone_id;
89 91 kmutex_t zone_mutex;
90 92 idmap_cache_t cache;
91 93 door_handle_t door_handle;
92 94 int door_valid;
93 95 int door_retried;
94 96 uint32_t message_id;
95 97 } idmap_zone_specific_t;
96 98
97 99
98 100
99 101 /*
100 102 * Module global data
101 103 */
102 104
103 105 static kmutex_t idmap_zone_mutex;
104 106 static zone_key_t idmap_zone_key;
105 107
106 108
107 109 /*
108 110 * Local function definitions
109 111 */
110 112
111 113
112 114 static int
113 115 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op,
114 116 xdrproc_t xdr_args, caddr_t args, xdrproc_t xdr_res, caddr_t res);
115 117
116 118 static int
117 119 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg);
118 120
119 121 static idmap_zone_specific_t *
120 122 idmap_get_zone_specific(zone_t *zone);
121 123
122 124
123 125
124 126 int
125 127 idmap_reg_dh(zone_t *zone, door_handle_t dh)
126 128 {
127 129 idmap_zone_specific_t *zs;
128 130
129 131 zs = idmap_get_zone_specific(zone);
130 132
131 133 mutex_enter(&zs->zone_mutex);
132 134
133 135 if (zs->door_valid)
134 136 door_ki_rele(zs->door_handle);
135 137
136 138 zs->door_handle = dh;
137 139 zs->door_valid = 1;
138 140
139 141 mutex_exit(&zs->zone_mutex);
140 142
141 143 return (0);
142 144 }
143 145
144 146 /*
145 147 * idmap_unreg_dh
146 148 *
147 149 * This routine is called by system call idmap_unreg().
148 150 * idmap_unreg() calls door_ki_rele() on the supplied
149 151 * door handle after this routine returns. We only
150 152 * need to perform one door release on zs->door_handle
151 153 */
152 154 int
153 155 idmap_unreg_dh(zone_t *zone, door_handle_t dh)
154 156 {
155 157 idmap_zone_specific_t *zs;
156 158
157 159 zs = idmap_get_zone_specific(zone);
158 160
159 161 kidmap_cache_purge(&zs->cache);
160 162
161 163 mutex_enter(&zs->zone_mutex);
162 164
163 165 if (!zs->door_valid || zs->door_handle != dh) {
164 166 mutex_exit(&zs->zone_mutex);
165 167 return (EINVAL);
166 168 }
167 169
168 170 door_ki_rele(zs->door_handle);
169 171
170 172 zs->door_valid = 0;
171 173 zs->door_retried = 0;
172 174 mutex_exit(&zs->zone_mutex);
173 175
174 176 return (0);
175 177 }
176 178
177 179
178 180 /*
179 181 * IMPORTANT. This function idmap_get_cache_data() is project
180 182 * private and is for use of the test system only and should
181 183 * not be used for other purposes.
182 184 */
183 185 void
184 186 idmap_get_cache_data(zone_t *zone, size_t *uidbysid, size_t *gidbysid,
185 187 size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid)
186 188 {
187 189 idmap_zone_specific_t *zs;
188 190
189 191 zs = idmap_get_zone_specific(zone);
190 192
191 193 kidmap_cache_get_data(&zs->cache, uidbysid, gidbysid,
192 194 pidbysid, sidbyuid, sidbygid);
193 195 }
194 196
195 197 static int
196 198 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg)
197 199 {
198 200 door_handle_t dh;
199 201 door_info_t di;
200 202 int status = 0;
201 203 int num_retries = 5;
202 204 int door_retried = 0;
203 205
204 206 retry:
205 207 mutex_enter(&zs->zone_mutex);
206 208 if (zs->door_valid) {
207 209 dh = zs->door_handle;
208 210 door_ki_hold(dh);
209 211 } else {
210 212 dh = NULL;
211 213 door_retried = zs->door_retried;
212 214 }
213 215 mutex_exit(&zs->zone_mutex);
214 216
215 217 if (dh == NULL) {
216 218 /* The door has been retried before so dont wait */
217 219 if (door_retried)
218 220 return (-1);
219 221
220 222 /*
221 223 * There is no door handle yet. Give
222 224 * smf a chance to restart idmapd
223 225 */
224 226 if (num_retries-- > 0) {
225 227 delay(hz);
226 228 goto retry;
227 229 }
228 230
229 231 #ifdef DEBUG
230 232 zcmn_err(zs->zone_id, CE_WARN,
231 233 "idmap: Error no registered door to call the "
232 234 "idmap daemon\n");
233 235 #endif
234 236 mutex_enter(&zs->zone_mutex);
235 237 if (!zs->door_valid)
236 238 zs->door_retried = 1;
237 239 mutex_exit(&zs->zone_mutex);
238 240
239 241 return (-1);
240 242 }
241 243
242 244 status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0);
243 245
244 246 switch (status) {
245 247 case 0: /* Success */
246 248 door_ki_rele(dh);
247 249 return (0);
248 250
249 251 case EINTR:
250 252 /* If we took an interrupt we have to bail out. */
251 253 if (ttolwp(curthread) && ISSIG(curthread, JUSTLOOKING)) {
252 254 door_ki_rele(dh);
253 255 #ifdef DEBUG
254 256 zcmn_err(zs->zone_id, CE_WARN,
255 257 "idmap: Interrupted\n");
256 258 #endif
257 259 return (-1);
258 260 }
259 261 /*
260 262 * Just retry and see what happens.
261 263 */
262 264 /* FALLTHROUGH */
263 265
264 266 case EAGAIN:
265 267 /* A resouce problem */
266 268 door_ki_rele(dh);
267 269 /* Back off before retrying */
268 270 #ifdef DEBUG
269 271 zcmn_err(zs->zone_id, CE_WARN,
270 272 "idmap: Door call returned error %d. Retrying\n", status);
271 273 #endif /* DEBUG */
272 274 delay(hz);
273 275 goto retry;
274 276
275 277 case EBADF:
276 278 /* Stale door handle. See if smf restarts the daemon. */
277 279 door_ki_rele(dh);
278 280 mutex_enter(&zs->zone_mutex);
279 281 if (zs->door_valid && dh == zs->door_handle) {
280 282 zs->door_valid = 0;
281 283 zs->door_retried = 0;
282 284 door_ki_rele(zs->door_handle);
283 285 }
284 286 mutex_exit(&zs->zone_mutex);
285 287 /* Back off before retrying */
286 288 #ifdef DEBUG
287 289 zcmn_err(zs->zone_id, CE_WARN,
288 290 "idmap: Door call returned error %d. Retrying\n", status);
289 291 #endif /* DEBUG */
290 292 delay(hz);
291 293 goto retry;
292 294
293 295 default:
294 296 /* Unknown error */
295 297 #ifdef DEBUG
296 298 zcmn_err(zs->zone_id, CE_WARN,
297 299 "idmap: Door call returned error %d.\n", status);
298 300 #endif /* DEBUG */
299 301 door_ki_rele(dh);
300 302 return (-1);
301 303 }
302 304 }
303 305
304 306
305 307 static idmap_zone_specific_t *
306 308 idmap_get_zone_specific(zone_t *zone)
307 309 {
308 310 idmap_zone_specific_t *zs;
309 311
310 312 ASSERT(zone != NULL);
311 313
312 314 zs = zone_getspecific(idmap_zone_key, zone);
313 315 if (zs != NULL)
314 316 return (zs);
315 317
316 318 mutex_enter(&idmap_zone_mutex);
317 319 zs = zone_getspecific(idmap_zone_key, zone);
318 320 if (zs == NULL) {
319 321 zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP);
320 322 mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL);
321 323 kidmap_cache_create(&zs->cache);
322 324 zs->zone_id = zone->zone_id;
323 325 (void) zone_setspecific(idmap_zone_key, zone, zs);
324 326 mutex_exit(&idmap_zone_mutex);
325 327 return (zs);
326 328 }
327 329 mutex_exit(&idmap_zone_mutex);
328 330
329 331 return (zs);
330 332 }
331 333
332 334
333 335 static void
334 336 /* ARGSUSED */
335 337 idmap_zone_destroy(zoneid_t zone_id, void *arg)
336 338 {
337 339 idmap_zone_specific_t *zs = arg;
338 340 if (zs != NULL) {
339 341 kidmap_cache_delete(&zs->cache);
340 342 if (zs->door_valid) {
341 343 door_ki_rele(zs->door_handle);
342 344 }
343 345 mutex_destroy(&zs->zone_mutex);
344 346 kmem_free(zs, sizeof (idmap_zone_specific_t));
345 347 }
346 348 }
347 349
348 350
349 351 int
350 352 kidmap_start(void)
351 353 {
352 354 mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
353 355 zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy);
354 356 kidmap_sid_prefix_store_init();
355 357
356 358 return (0);
357 359 }
358 360
359 361
360 362 int
361 363 kidmap_stop(void)
362 364 {
363 365 return (EBUSY);
364 366 }
365 367
366 368
367 369 /*
368 370 * idmap_get_door
369 371 *
370 372 * This is called by the system call allocids() to get the door for the
371 373 * given zone.
372 374 */
373 375 door_handle_t
374 376 idmap_get_door(zone_t *zone)
375 377 {
376 378 door_handle_t dh = NULL;
377 379 idmap_zone_specific_t *zs;
378 380
379 381 zs = idmap_get_zone_specific(zone);
380 382
381 383 mutex_enter(&zs->zone_mutex);
382 384 if (zs->door_valid) {
383 385 dh = zs->door_handle;
384 386 door_ki_hold(dh);
385 387 }
386 388 mutex_exit(&zs->zone_mutex);
387 389 return (dh);
388 390 }
389 391
390 392
391 393 /*
392 394 * idmap_purge_cache
393 395 *
394 396 * This is called by the system call allocids() to purge the cache for the
395 397 * given zone.
396 398 */
397 399 void
398 400 idmap_purge_cache(zone_t *zone)
399 401 {
400 402 idmap_zone_specific_t *zs;
401 403
402 404 zs = idmap_get_zone_specific(zone);
403 405
404 406 kidmap_cache_purge(&zs->cache);
405 407 }
406 408
407 409
408 410
409 411
410 412 /*
411 413 * Given Domain SID and RID, get UID
412 414 *
413 415 * Input:
414 416 * sid_prefix - Domain SID in canonical form
415 417 * rid - RID
416 418 *
417 419 * Output:
418 420 * uid - POSIX UID if return == IDMAP_SUCCESS
419 421 *
420 422 * Return:
421 423 * Success return IDMAP_SUCCESS else IDMAP error
422 424 */
423 425 idmap_stat
424 426 kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
425 427 uid_t *uid)
426 428 {
427 429 idmap_zone_specific_t *zs;
428 430 idmap_mapping_batch args;
429 431 idmap_mapping mapping;
430 432 idmap_ids_res results;
431 433 uint32_t op = IDMAP_GET_MAPPED_IDS;
432 434 const char *new_sid_prefix;
433 435 idmap_stat status;
434 436
435 437 if (sid_prefix == NULL || uid == NULL)
436 438 return (IDMAP_ERR_ARG);
437 439
438 440 zs = idmap_get_zone_specific(zone);
439 441
440 442 if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid)
441 443 == IDMAP_SUCCESS)
442 444 return (IDMAP_SUCCESS);
443 445
444 446 bzero(&mapping, sizeof (idmap_mapping));
445 447 mapping.id1.idtype = IDMAP_SID;
446 448 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
447 449 mapping.id1.idmap_id_u.sid.rid = rid;
448 450 mapping.id2.idtype = IDMAP_UID;
449 451
450 452 bzero(&results, sizeof (idmap_ids_res));
451 453
452 454 args.idmap_mapping_batch_len = 1;
453 455 args.idmap_mapping_batch_val = &mapping;
454 456
455 457 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
456 458 (caddr_t)&args, xdr_idmap_ids_res,
457 459 (caddr_t)&results) == 0) {
458 460 /* Door call succeded */
459 461 if (results.retcode != IDMAP_SUCCESS) {
460 462 status = results.retcode;
461 463 *uid = UID_NOBODY;
462 464 } else if (results.ids.ids_len >= 1 &&
463 465 results.ids.ids_val[0].id.idtype == IDMAP_UID) {
464 466 status = results.ids.ids_val[0].retcode;
465 467 *uid = results.ids.ids_val[0].id.idmap_id_u.uid;
466 468 if (status == IDMAP_SUCCESS) {
467 469 new_sid_prefix = kidmap_find_sid_prefix(
468 470 sid_prefix);
469 471 kidmap_cache_add_sid2uid(&zs->cache,
470 472 new_sid_prefix, rid, *uid,
471 473 results.ids.ids_val[0].direction);
472 474 }
473 475 } else {
474 476 status = IDMAP_ERR_NOMAPPING;
475 477 *uid = UID_NOBODY;
476 478 }
477 479 xdr_free(xdr_idmap_ids_res, (char *)&results);
478 480 } else {
479 481 /* Door call failed */
480 482 status = IDMAP_ERR_NOMAPPING;
481 483 *uid = UID_NOBODY;
482 484 }
483 485 return (status);
484 486 }
485 487
486 488
487 489 /*
488 490 * Given Domain SID and RID, get GID
489 491 *
490 492 * Input:
491 493 * sid_prefix - Domain SID in canonical form
492 494 * rid - RID
493 495 *
494 496 * Output:
495 497 * gid - POSIX UID if return == IDMAP_SUCCESS
496 498 *
497 499 * Return:
498 500 * Success return IDMAP_SUCCESS else IDMAP error
499 501 */
500 502 idmap_stat
501 503 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
502 504 gid_t *gid)
503 505 {
504 506 idmap_zone_specific_t *zs;
505 507 idmap_mapping_batch args;
506 508 idmap_mapping mapping;
507 509 idmap_ids_res results;
508 510 uint32_t op = IDMAP_GET_MAPPED_IDS;
509 511 const char *new_sid_prefix;
510 512 idmap_stat status;
511 513
512 514 if (sid_prefix == NULL || gid == NULL)
513 515 return (IDMAP_ERR_ARG);
514 516
515 517 zs = idmap_get_zone_specific(zone);
516 518
517 519 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid)
518 520 == IDMAP_SUCCESS)
519 521 return (IDMAP_SUCCESS);
520 522
521 523 bzero(&mapping, sizeof (idmap_mapping));
522 524 mapping.id1.idtype = IDMAP_SID;
523 525 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
524 526 mapping.id1.idmap_id_u.sid.rid = rid;
525 527 mapping.id2.idtype = IDMAP_GID;
526 528
527 529 bzero(&results, sizeof (idmap_ids_res));
528 530
529 531 args.idmap_mapping_batch_len = 1;
530 532 args.idmap_mapping_batch_val = &mapping;
531 533
532 534 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
533 535 (caddr_t)&args, xdr_idmap_ids_res,
534 536 (caddr_t)&results) == 0) {
535 537 /* Door call succeded */
536 538 if (results.retcode != IDMAP_SUCCESS) {
537 539 status = results.retcode;
538 540 *gid = GID_NOBODY;
539 541 } else if (results.ids.ids_len >= 1 &&
540 542 results.ids.ids_val[0].id.idtype == IDMAP_GID) {
541 543 status = results.ids.ids_val[0].retcode;
542 544 *gid = results.ids.ids_val[0].id.idmap_id_u.gid;
543 545 if (status == IDMAP_SUCCESS) {
544 546 new_sid_prefix = kidmap_find_sid_prefix(
545 547 sid_prefix);
546 548 kidmap_cache_add_sid2gid(&zs->cache,
547 549 new_sid_prefix, rid, *gid,
548 550 results.ids.ids_val[0].direction);
549 551 }
550 552 } else {
551 553 status = IDMAP_ERR_NOMAPPING;
552 554 *gid = GID_NOBODY;
553 555 }
554 556 xdr_free(xdr_idmap_ids_res, (char *)&results);
555 557 } else {
556 558 /* Door call failed */
557 559 status = IDMAP_ERR_NOMAPPING;
558 560 *gid = GID_NOBODY;
559 561 }
560 562 return (status);
561 563 }
562 564
563 565 /*
564 566 * Given Domain SID and RID, get Posix ID
565 567 *
566 568 * Input:
567 569 * sid_prefix - Domain SID in canonical form
568 570 * rid - RID
569 571 *
570 572 * Output:
571 573 * pid - POSIX ID if return == IDMAP_SUCCESS
572 574 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS
573 575 *
574 576 * Return:
575 577 * Success return IDMAP_SUCCESS else IDMAP error
576 578 */
577 579 idmap_stat
578 580 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
579 581 uid_t *pid, int *is_user)
580 582 {
581 583 idmap_zone_specific_t *zs;
582 584 idmap_mapping_batch args;
583 585 idmap_mapping mapping;
584 586 idmap_ids_res results;
585 587 uint32_t op = IDMAP_GET_MAPPED_IDS;
586 588 const char *new_sid_prefix;
587 589 idmap_stat status;
588 590
589 591 if (sid_prefix == NULL || pid == NULL || is_user == NULL)
590 592 return (IDMAP_ERR_ARG);
591 593
592 594 zs = idmap_get_zone_specific(zone);
593 595
594 596 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid,
595 597 is_user) == IDMAP_SUCCESS)
596 598 return (IDMAP_SUCCESS);
597 599
598 600 bzero(&mapping, sizeof (idmap_mapping));
599 601 mapping.id1.idtype = IDMAP_SID;
600 602 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
601 603 mapping.id1.idmap_id_u.sid.rid = rid;
602 604 mapping.id2.idtype = IDMAP_POSIXID;
603 605
604 606 bzero(&results, sizeof (idmap_ids_res));
605 607
606 608 args.idmap_mapping_batch_len = 1;
607 609 args.idmap_mapping_batch_val = &mapping;
608 610
609 611 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
610 612 (caddr_t)&args, xdr_idmap_ids_res,
611 613 (caddr_t)&results) == 0) {
612 614 /* Door call succeded */
613 615 if (results.retcode != IDMAP_SUCCESS) {
614 616 status = results.retcode;
615 617 *is_user = 1;
616 618 *pid = UID_NOBODY;
617 619 } else if (results.ids.ids_len >= 1 && (
618 620 results.ids.ids_val[0].id.idtype == IDMAP_UID ||
619 621 results.ids.ids_val[0].id.idtype == IDMAP_GID)) {
620 622 status = results.ids.ids_val[0].retcode;
621 623 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) {
622 624 *is_user = 1;
623 625 *pid = results.ids.ids_val[0].id.idmap_id_u.uid;
624 626 } else {
625 627 *is_user = 0;
626 628 *pid = results.ids.ids_val[0].id.idmap_id_u.gid;
627 629 }
628 630 if (status == IDMAP_SUCCESS) {
629 631 new_sid_prefix = kidmap_find_sid_prefix(
630 632 sid_prefix);
631 633 kidmap_cache_add_sid2pid(&zs->cache,
632 634 new_sid_prefix, rid, *pid,
633 635 *is_user,
634 636 results.ids.ids_val[0].direction);
635 637 }
636 638 } else {
637 639 status = IDMAP_ERR_NOMAPPING;
638 640 *is_user = 1;
639 641 *pid = UID_NOBODY;
640 642 }
641 643 xdr_free(xdr_idmap_ids_res, (char *)&results);
642 644 } else {
643 645 /* Door call failed */
644 646 status = IDMAP_ERR_NOMAPPING;
645 647 *is_user = 1;
646 648 *pid = UID_NOBODY;
647 649 }
648 650 return (status);
649 651 }
650 652
651 653
652 654 /*
653 655 * Given UID, get Domain SID and RID
654 656 *
655 657 * Input:
656 658 * uid - Posix UID
657 659 *
658 660 * Output:
659 661 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
660 662 * rid - RID if return == IDMAP_SUCCESS
661 663 *
662 664 * Return:
663 665 * Success return IDMAP_SUCCESS else IDMAP error
664 666 */
665 667 idmap_stat
666 668 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix,
667 669 uint32_t *rid)
668 670 {
669 671 idmap_zone_specific_t *zs;
670 672 idmap_mapping_batch args;
671 673 idmap_mapping mapping;
672 674 idmap_ids_res results;
673 675 uint32_t op = IDMAP_GET_MAPPED_IDS;
674 676 idmap_stat status;
675 677 time_t entry_ttl;
676 678 idmap_id *id;
677 679
678 680 if (sid_prefix == NULL || rid == NULL)
679 681 return (IDMAP_ERR_ARG);
680 682
681 683 zs = idmap_get_zone_specific(zone);
682 684
683 685 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid)
684 686 == IDMAP_SUCCESS) {
685 687 return (IDMAP_SUCCESS);
686 688 }
687 689
688 690 bzero(&mapping, sizeof (idmap_mapping));
689 691 mapping.id1.idtype = IDMAP_UID;
690 692 mapping.id1.idmap_id_u.uid = uid;
691 693 mapping.id2.idtype = IDMAP_SID;
692 694
693 695 bzero(&results, sizeof (idmap_ids_res));
694 696
695 697 args.idmap_mapping_batch_len = 1;
696 698 args.idmap_mapping_batch_val = &mapping;
697 699
698 700 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
699 701 (caddr_t)&args, xdr_idmap_ids_res,
700 702 (caddr_t)&results) == 0) {
701 703 /* Door call succeded */
702 704 if (results.retcode != IDMAP_SUCCESS) {
703 705 status = results.retcode;
704 706 *rid = 0;
705 707 *sid_prefix = NULL;
706 708 } else if (results.ids.ids_len >= 1 &&
707 709 (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
708 710 results.ids.ids_val[0].id.idtype == IDMAP_USID ||
709 711 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
710 712 status = results.ids.ids_val[0].retcode;
711 713 id = &results.ids.ids_val[0].id;
712 714 *sid_prefix = kidmap_find_sid_prefix(
713 715 id->idmap_id_u.sid.prefix);
714 716 *rid = id->idmap_id_u.sid.rid;
715 717 if (status == IDMAP_SUCCESS) {
716 718 kidmap_cache_add_sid2uid(&zs->cache,
717 719 *sid_prefix, *rid, uid,
718 720 results.ids.ids_val[0].direction);
719 721 }
720 722 } else {
721 723 status = IDMAP_ERR_NOMAPPING;
722 724 *rid = 0;
723 725 *sid_prefix = NULL;
724 726 }
725 727 xdr_free(xdr_idmap_ids_res, (char *)&results);
726 728 } else {
727 729 /* Door call failed */
728 730 status = IDMAP_ERR_NOMAPPING;
729 731 *rid = 0;
730 732 *sid_prefix = NULL;
731 733 }
732 734 return (status);
733 735 }
734 736
735 737
736 738 /*
737 739 * Given GID, get Domain SID and RID
738 740 *
739 741 * Input:
740 742 * gid - Posix GID
741 743 *
742 744 * Output:
743 745 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
744 746 * rid - RID if return == IDMAP_SUCCESS
745 747 *
746 748 * Return:
747 749 * Success return IDMAP_SUCCESS else IDMAP error
748 750 */
749 751 idmap_stat
750 752 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix,
751 753 uint32_t *rid)
752 754 {
753 755 idmap_zone_specific_t *zs;
754 756 idmap_mapping_batch args;
755 757 idmap_mapping mapping;
756 758 idmap_ids_res results;
757 759 uint32_t op = IDMAP_GET_MAPPED_IDS;
758 760 idmap_stat status;
759 761 idmap_id *id;
760 762
761 763 if (sid_prefix == NULL || rid == NULL)
762 764 return (IDMAP_ERR_ARG);
763 765
764 766 zs = idmap_get_zone_specific(zone);
765 767
766 768 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid)
767 769 == IDMAP_SUCCESS) {
768 770 return (IDMAP_SUCCESS);
769 771 }
770 772
771 773 bzero(&mapping, sizeof (idmap_mapping));
772 774 mapping.id1.idtype = IDMAP_GID;
773 775 mapping.id1.idmap_id_u.uid = gid;
774 776 mapping.id2.idtype = IDMAP_SID;
775 777
776 778 bzero(&results, sizeof (idmap_ids_res));
777 779
778 780 args.idmap_mapping_batch_len = 1;
779 781 args.idmap_mapping_batch_val = &mapping;
780 782
781 783 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
782 784 (caddr_t)&args, xdr_idmap_ids_res,
783 785 (caddr_t)&results) == 0) {
784 786 /* Door call succeded */
785 787 if (results.retcode != IDMAP_SUCCESS) {
786 788 status = results.retcode;
787 789 *rid = 0;
788 790 *sid_prefix = NULL;
789 791 } else if (results.ids.ids_len >= 1 &&
790 792 (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
791 793 results.ids.ids_val[0].id.idtype == IDMAP_USID ||
792 794 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
793 795 status = results.ids.ids_val[0].retcode;
794 796 id = &results.ids.ids_val[0].id;
795 797 *sid_prefix = kidmap_find_sid_prefix(
796 798 id->idmap_id_u.sid.prefix);
797 799 *rid = id->idmap_id_u.sid.rid;
798 800 if (status == IDMAP_SUCCESS) {
799 801 kidmap_cache_add_sid2gid(&zs->cache,
800 802 *sid_prefix, *rid, gid,
801 803 results.ids.ids_val[0].direction);
802 804 }
803 805 } else {
804 806 status = IDMAP_ERR_NOMAPPING;
805 807 *rid = 0;
806 808 *sid_prefix = NULL;
807 809 }
808 810 xdr_free(xdr_idmap_ids_res, (char *)&results);
809 811 } else {
810 812 /* Door call failed */
811 813 status = IDMAP_ERR_NOMAPPING;
812 814 *rid = 0;
813 815 *sid_prefix = NULL;
814 816 }
815 817 return (status);
816 818 }
817 819
818 820 /*
819 821 * Create handle to get SID to UID/GID mapping entries
820 822 *
821 823 * Input:
822 824 * none
823 825 * Return:
824 826 * get_handle
825 827 *
826 828 */
827 829 idmap_get_handle_t *
828 830 kidmap_get_create(zone_t *zone)
829 831 {
830 832 idmap_zone_specific_t *zs;
831 833 idmap_get_handle_t *handle;
832 834 #define INIT_MAPPING_SIZE 32
833 835
834 836 zs = idmap_get_zone_specific(zone);
835 837
836 838 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP);
837 839
838 840 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) *
839 841 INIT_MAPPING_SIZE, KM_SLEEP);
840 842
841 843 handle->result = kmem_zalloc((sizeof (idmap_get_res)) *
842 844 INIT_MAPPING_SIZE, KM_SLEEP);
843 845 handle->mapping_size = INIT_MAPPING_SIZE;
844 846 handle->zs = zs;
845 847
846 848 return (handle);
847 849 }
848 850
849 851 /*
850 852 * Internal routine to extend a "get_handle"
851 853 */
852 854 static void
853 855 kidmap_get_extend(idmap_get_handle_t *get_handle)
854 856 {
855 857 idmap_mapping *mapping;
856 858 idmap_get_res *result;
857 859 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE;
858 860
859 861 mapping = kmem_zalloc((sizeof (idmap_mapping)) *
860 862 new_size, KM_SLEEP);
861 863 (void) memcpy(mapping, get_handle->mapping,
862 864 (sizeof (idmap_mapping)) * get_handle->mapping_size);
863 865
864 866 result = kmem_zalloc((sizeof (idmap_get_res)) *
865 867 new_size, KM_SLEEP);
866 868 (void) memcpy(result, get_handle->result,
867 869 (sizeof (idmap_get_res)) * get_handle->mapping_size);
868 870
869 871 kmem_free(get_handle->mapping,
870 872 (sizeof (idmap_mapping)) * get_handle->mapping_size);
871 873 get_handle->mapping = mapping;
872 874
873 875 kmem_free(get_handle->result,
874 876 (sizeof (idmap_get_res)) * get_handle->mapping_size);
875 877 get_handle->result = result;
876 878
877 879 get_handle->mapping_size = new_size;
878 880 }
879 881
880 882
881 883 /*
882 884 * Given Domain SID and RID, get UID
883 885 *
884 886 * Input:
885 887 * sid_prefix - Domain SID in canonical form
886 888 * rid - RID
887 889 *
888 890 * Output:
889 891 * stat - status of the get request
890 892 * uid - POSIX UID if stat == IDMAP_SUCCESS
891 893 *
892 894 * Notes:
893 895 * The output parameters will be set by idmap_get_mappings()
894 896 * The sid_prefix is copied.
895 897 */
896 898 idmap_stat
897 899 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
898 900 uint32_t rid, uid_t *uid, idmap_stat *stat)
899 901 {
900 902 idmap_mapping *mapping;
901 903 idmap_get_res *result;
902 904
903 905 if (get_handle == NULL || sid_prefix == NULL ||
904 906 uid == NULL || stat == NULL)
905 907 return (IDMAP_ERR_ARG);
906 908
907 909 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix,
908 910 rid, uid) == IDMAP_SUCCESS) {
909 911 *stat = IDMAP_SUCCESS;
910 912 return (IDMAP_SUCCESS);
911 913 }
912 914
913 915 /* Get a copy of sid_prefix */
914 916 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
915 917
916 918 if (get_handle->mapping_num >= get_handle->mapping_size)
917 919 kidmap_get_extend(get_handle);
918 920
919 921 mapping = &get_handle->mapping[get_handle->mapping_num];
920 922 mapping->flag = 0;
921 923 mapping->id1.idtype = IDMAP_SID;
922 924 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
923 925 mapping->id1.idmap_id_u.sid.rid = rid;
924 926 mapping->id2.idtype = IDMAP_UID;
925 927
926 928 result = &get_handle->result[get_handle->mapping_num];
927 929 result->idtype = IDMAP_UID;
928 930 result->uid = uid;
929 931 result->gid = NULL;
930 932 result->pid = NULL;
931 933 result->sid_prefix = NULL;
932 934 result->rid = NULL;
933 935 result->is_user = NULL;
934 936 result->stat = stat;
935 937
936 938 get_handle->mapping_num++;
937 939
938 940 return (IDMAP_SUCCESS);
939 941 }
940 942
941 943
942 944 /*
943 945 * Given Domain SID and RID, get GID
944 946 *
945 947 * Input:
946 948 * sid_prefix - Domain SID in canonical form
947 949 * rid - RID
948 950 *
949 951 * Output:
950 952 * stat - status of the get request
951 953 * gid - POSIX GID if stat == IDMAP_SUCCESS
952 954 *
953 955 * Notes:
954 956 * The output parameters will be set by idmap_get_mappings()
955 957 * The sid_prefix is copied.
956 958 */
957 959 idmap_stat
958 960 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
959 961 uint32_t rid, uid_t *gid, idmap_stat *stat)
960 962 {
961 963 idmap_mapping *mapping;
962 964 idmap_get_res *result;
963 965
964 966 if (get_handle == NULL || sid_prefix == NULL ||
965 967 gid == NULL || stat == NULL)
966 968 return (IDMAP_ERR_ARG);
967 969
968 970 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix,
969 971 rid, gid) == IDMAP_SUCCESS) {
970 972 *stat = IDMAP_SUCCESS;
971 973 return (IDMAP_SUCCESS);
972 974 }
973 975
974 976 /* Get a copy of sid_prefix */
975 977 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
976 978
977 979 if (get_handle->mapping_num >= get_handle->mapping_size)
978 980 kidmap_get_extend(get_handle);
979 981
980 982 mapping = &get_handle->mapping[get_handle->mapping_num];
981 983 mapping->flag = 0;
982 984 mapping->id1.idtype = IDMAP_SID;
983 985 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
984 986 mapping->id1.idmap_id_u.sid.rid = rid;
985 987 mapping->id2.idtype = IDMAP_GID;
986 988
987 989 result = &get_handle->result[get_handle->mapping_num];
988 990 result->idtype = IDMAP_GID;
989 991 result->uid = NULL;
990 992 result->gid = gid;
991 993 result->pid = NULL;
992 994 result->sid_prefix = NULL;
993 995 result->rid = NULL;
994 996 result->is_user = NULL;
995 997 result->stat = stat;
996 998
997 999 get_handle->mapping_num++;
998 1000
999 1001 return (IDMAP_SUCCESS);
1000 1002 }
1001 1003
1002 1004
1003 1005 /*
1004 1006 * Given Domain SID and RID, get Posix ID
1005 1007 *
1006 1008 * Input:
1007 1009 * sid_prefix - Domain SID in canonical form
1008 1010 * rid - RID
1009 1011 *
1010 1012 * Output:
1011 1013 * stat - status of the get request
1012 1014 * is_user - user or group
1013 1015 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1
1014 1016 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0
1015 1017 *
1016 1018 * Notes:
1017 1019 * The output parameters will be set by idmap_get_mappings()
1018 1020 * The sid_prefix is copied.
1019 1021 */
1020 1022 idmap_stat
1021 1023 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
1022 1024 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat)
1023 1025 {
1024 1026 idmap_mapping *mapping;
1025 1027 idmap_get_res *result;
1026 1028
1027 1029 if (get_handle == NULL || sid_prefix == NULL || pid == NULL ||
1028 1030 is_user == NULL || stat == NULL)
1029 1031 return (IDMAP_ERR_ARG);
1030 1032
1031 1033 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix,
1032 1034 rid, pid, is_user) == IDMAP_SUCCESS) {
1033 1035 *stat = IDMAP_SUCCESS;
1034 1036 return (IDMAP_SUCCESS);
1035 1037 }
1036 1038
1037 1039 /* Get a copy of sid_prefix */
1038 1040 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
1039 1041
1040 1042 if (get_handle->mapping_num >= get_handle->mapping_size)
1041 1043 kidmap_get_extend(get_handle);
1042 1044
1043 1045 mapping = &get_handle->mapping[get_handle->mapping_num];
1044 1046 mapping->flag = 0;
1045 1047 mapping->id1.idtype = IDMAP_SID;
1046 1048 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
1047 1049 mapping->id1.idmap_id_u.sid.rid = rid;
1048 1050 mapping->id2.idtype = IDMAP_POSIXID;
1049 1051
1050 1052 result = &get_handle->result[get_handle->mapping_num];
1051 1053 result->idtype = IDMAP_POSIXID;
1052 1054 result->uid = NULL;
1053 1055 result->gid = NULL;
1054 1056 result->pid = pid;
1055 1057 result->sid_prefix = NULL;
1056 1058 result->rid = NULL;
1057 1059 result->is_user = is_user;
1058 1060 result->stat = stat;
1059 1061
1060 1062 get_handle->mapping_num++;
1061 1063
1062 1064 return (IDMAP_SUCCESS);
1063 1065 }
1064 1066
1065 1067
1066 1068 /*
1067 1069 * Given UID, get SID and RID
1068 1070 *
1069 1071 * Input:
1070 1072 * uid - POSIX UID
1071 1073 *
1072 1074 * Output:
1073 1075 * stat - status of the get request
1074 1076 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1075 1077 * rid - RID (if stat == IDMAP_SUCCESS)
1076 1078 *
1077 1079 * Note: The output parameters will be set by idmap_get_mappings()
1078 1080 */
1079 1081 idmap_stat
1080 1082 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid,
1081 1083 const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1082 1084 {
1083 1085 idmap_mapping *mapping;
1084 1086 idmap_get_res *result;
1085 1087
1086 1088 if (get_handle == NULL || sid_prefix == NULL ||
1087 1089 rid == NULL || stat == NULL)
1088 1090 return (IDMAP_ERR_ARG);
1089 1091
1090 1092 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache,
1091 1093 sid_prefix, rid, uid) == IDMAP_SUCCESS) {
1092 1094 *stat = IDMAP_SUCCESS;
1093 1095 return (IDMAP_SUCCESS);
1094 1096 }
1095 1097
1096 1098 if (get_handle->mapping_num >= get_handle->mapping_size)
1097 1099 kidmap_get_extend(get_handle);
1098 1100
1099 1101 mapping = &get_handle->mapping[get_handle->mapping_num];
1100 1102 mapping->flag = 0;
1101 1103 mapping->id1.idtype = IDMAP_UID;
1102 1104 mapping->id1.idmap_id_u.uid = uid;
1103 1105 mapping->id2.idtype = IDMAP_SID;
1104 1106
1105 1107 result = &get_handle->result[get_handle->mapping_num];
1106 1108 result->idtype = IDMAP_SID;
1107 1109 result->uid = NULL;
1108 1110 result->gid = NULL;
1109 1111 result->pid = NULL;
1110 1112 result->sid_prefix = sid_prefix;
1111 1113 result->rid = rid;
1112 1114 result->is_user = NULL;
1113 1115 result->stat = stat;
1114 1116
1115 1117 get_handle->mapping_num++;
1116 1118
1117 1119 return (IDMAP_SUCCESS);
1118 1120 }
1119 1121
1120 1122
1121 1123 /*
1122 1124 * Given GID, get SID and RID
1123 1125 *
1124 1126 * Input:
1125 1127 * gid - POSIX GID
1126 1128 *
1127 1129 * Output:
1128 1130 * stat - status of the get request
1129 1131 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1130 1132 * rid - RID (if stat == IDMAP_SUCCESS)
1131 1133 *
1132 1134 * Note: The output parameters will be set by idmap_get_mappings()
1133 1135 */
1134 1136 idmap_stat
1135 1137 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid,
1136 1138 const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1137 1139 {
1138 1140 idmap_mapping *mapping;
1139 1141 idmap_get_res *result;
1140 1142
1141 1143 if (get_handle == NULL || sid_prefix == NULL ||
1142 1144 rid == NULL || stat == NULL)
1143 1145 return (IDMAP_ERR_ARG);
1144 1146
1145 1147 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache,
1146 1148 sid_prefix, rid, gid) == IDMAP_SUCCESS) {
1147 1149 *stat = IDMAP_SUCCESS;
1148 1150 return (IDMAP_SUCCESS);
1149 1151 }
1150 1152
1151 1153 if (get_handle->mapping_num >= get_handle->mapping_size)
1152 1154 kidmap_get_extend(get_handle);
1153 1155
1154 1156 mapping = &get_handle->mapping[get_handle->mapping_num];
1155 1157 mapping->flag = 0;
1156 1158 mapping->id1.idtype = IDMAP_GID;
1157 1159 mapping->id1.idmap_id_u.gid = gid;
1158 1160 mapping->id2.idtype = IDMAP_SID;
1159 1161
1160 1162 result = &get_handle->result[get_handle->mapping_num];
1161 1163 result->idtype = IDMAP_SID;
1162 1164 result->uid = NULL;
1163 1165 result->gid = NULL;
1164 1166 result->pid = NULL;
1165 1167 result->sid_prefix = sid_prefix;
1166 1168 result->rid = rid;
1167 1169 result->is_user = NULL;
1168 1170 result->stat = stat;
1169 1171
1170 1172 get_handle->mapping_num++;
1171 1173
1172 1174 return (IDMAP_SUCCESS);
1173 1175 }
1174 1176
1175 1177
1176 1178 /*
1177 1179 * Process the batched "get mapping" requests. The results (i.e.
1178 1180 * status and identity) will be available in the data areas
1179 1181 * provided by individual requests.
1180 1182 *
1181 1183 * If the door call fails the status IDMAP_ERR_NOMAPPING is
1182 1184 * return and the UID or UID result is set to "nobody"
1183 1185 */
1184 1186
1185 1187 idmap_stat
1186 1188 kidmap_get_mappings(idmap_get_handle_t *get_handle)
1187 1189 {
1188 1190 idmap_mapping_batch rpc_args;
1189 1191 idmap_ids_res rpc_res;
1190 1192 uint32_t op = IDMAP_GET_MAPPED_IDS;
1191 1193 idmap_mapping *request;
1192 1194 idmap_get_res *result;
1193 1195 idmap_id *id;
1194 1196 int status;
1195 1197 int i;
1196 1198 const char *sid_prefix;
1197 1199 int is_user;
1198 1200 idmap_cache_t *cache;
1199 1201 int direction;
1200 1202
1201 1203 if (get_handle == NULL)
1202 1204 return (IDMAP_ERR_ARG);
1203 1205
1204 1206 if (get_handle->mapping_num == 0)
1205 1207 return (IDMAP_SUCCESS);
1206 1208 cache = &get_handle->zs->cache;
1207 1209
1208 1210 bzero(&rpc_res, sizeof (idmap_ids_res));
1209 1211
1210 1212 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num;
1211 1213 rpc_args.idmap_mapping_batch_val = get_handle->mapping;
1212 1214
1213 1215 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch,
1214 1216 (caddr_t)&rpc_args, xdr_idmap_ids_res,
1215 1217 (caddr_t)&rpc_res) != 0) {
1216 1218 /* Door call failed */
1217 1219 status = IDMAP_ERR_NOMAPPING;
1218 1220 goto error;
1219 1221 }
1220 1222
1221 1223 status = rpc_res.retcode;
1222 1224 if (status != IDMAP_SUCCESS) {
1223 1225 /* RPC returned idmap error code */
1224 1226 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1225 1227 goto error;
1226 1228 }
1227 1229
1228 1230 for (i = 0; i < get_handle->mapping_num; i++) {
1229 1231 request = &get_handle->mapping[i];
1230 1232 result = &get_handle->result[i];
1231 1233
1232 1234 if (i >= rpc_res.ids.ids_len) {
1233 1235 *result->stat = IDMAP_ERR_NOMAPPING;
1234 1236 if (result->uid)
1235 1237 *result->uid = UID_NOBODY;
1236 1238 if (result->gid)
1237 1239 *result->gid = GID_NOBODY;
1238 1240 if (result->pid)
1239 1241 *result->pid = UID_NOBODY;
1240 1242 if (result->is_user)
1241 1243 *result->is_user = 1;
1242 1244 if (result->sid_prefix)
1243 1245 *result->sid_prefix = NULL;
1244 1246 if (result->rid)
1245 1247 *result->rid = 0;
1246 1248 continue;
1247 1249 }
1248 1250
1249 1251 *result->stat = rpc_res.ids.ids_val[i].retcode;
1250 1252
1251 1253 id = &rpc_res.ids.ids_val[i].id;
1252 1254 direction = rpc_res.ids.ids_val[i].direction;
1253 1255
1254 1256 switch (id->idtype) {
1255 1257 case IDMAP_UID:
1256 1258 if (result->uid)
1257 1259 *result->uid = id->idmap_id_u.uid;
1258 1260 if (result->pid)
1259 1261 *result->pid = id->idmap_id_u.uid;
1260 1262 if (result->is_user)
1261 1263 *result->is_user = 1;
1262 1264 sid_prefix = kidmap_find_sid_prefix(
1263 1265 request->id1.idmap_id_u.sid.prefix);
1264 1266 if (*result->stat == IDMAP_SUCCESS && result->uid)
1265 1267 kidmap_cache_add_sid2uid(
1266 1268 cache, sid_prefix,
1267 1269 request->id1.idmap_id_u.sid.rid,
1268 1270 id->idmap_id_u.uid,
1269 1271 direction);
1270 1272 else if (*result->stat == IDMAP_SUCCESS && result->pid)
1271 1273 kidmap_cache_add_sid2pid(
1272 1274 cache, sid_prefix,
1273 1275 request->id1.idmap_id_u.sid.rid,
1274 1276 id->idmap_id_u.uid, 1,
1275 1277 direction);
1276 1278 break;
1277 1279
1278 1280 case IDMAP_GID:
1279 1281 if (result->gid)
1280 1282 *result->gid = id->idmap_id_u.gid;
1281 1283 if (result->pid)
1282 1284 *result->pid = id->idmap_id_u.gid;
1283 1285 if (result->is_user)
1284 1286 *result->is_user = 0;
1285 1287 sid_prefix = kidmap_find_sid_prefix(
1286 1288 request->id1.idmap_id_u.sid.prefix);
1287 1289 if (*result->stat == IDMAP_SUCCESS && result->gid)
1288 1290 kidmap_cache_add_sid2gid(
1289 1291 cache, sid_prefix,
1290 1292 request->id1.idmap_id_u.sid.rid,
1291 1293 id->idmap_id_u.gid,
1292 1294 direction);
1293 1295 else if (*result->stat == IDMAP_SUCCESS && result->pid)
1294 1296 kidmap_cache_add_sid2pid(
1295 1297 cache, sid_prefix,
1296 1298 request->id1.idmap_id_u.sid.rid,
1297 1299 id->idmap_id_u.gid, 0,
1298 1300 direction);
1299 1301 break;
|
↓ open down ↓ |
1265 lines elided |
↑ open up ↑ |
1300 1302
1301 1303 case IDMAP_SID:
1302 1304 case IDMAP_USID:
1303 1305 case IDMAP_GSID:
1304 1306 sid_prefix = kidmap_find_sid_prefix(
1305 1307 id->idmap_id_u.sid.prefix);
1306 1308 if (result->sid_prefix && result->rid) {
1307 1309 *result->sid_prefix = sid_prefix;
1308 1310 *result->rid = id->idmap_id_u.sid.rid;
1309 1311 }
1312 + if (*result->stat == IDMAP_ERR_NOTFOUND &&
1313 + sid_prefix != NULL) {
1314 + /* IDMAP generated a local SID. Use it. */
1315 + *result->stat = IDMAP_SUCCESS;
1316 + }
1317 +
1310 1318 if (*result->stat == IDMAP_SUCCESS &&
1311 1319 request->id1.idtype == IDMAP_UID)
1312 1320 kidmap_cache_add_sid2uid(
1313 1321 cache, sid_prefix,
1314 1322 id->idmap_id_u.sid.rid,
1315 1323 request->id1.idmap_id_u.uid,
1316 1324 direction);
1317 1325 else if (*result->stat == IDMAP_SUCCESS &&
1318 1326 request->id1.idtype == IDMAP_GID)
1319 1327 kidmap_cache_add_sid2gid(
1320 1328 cache, sid_prefix,
1321 1329 id->idmap_id_u.sid.rid,
1322 1330 request->id1.idmap_id_u.gid,
1323 1331 direction);
1324 1332 break;
1325 1333
1326 1334 default:
1327 1335 *result->stat = IDMAP_ERR_NORESULT;
1328 1336 if (result->uid)
1329 1337 *result->uid = UID_NOBODY;
1330 1338 if (result->gid)
1331 1339 *result->gid = GID_NOBODY;
1332 1340 if (result->pid)
1333 1341 *result->pid = UID_NOBODY;
1334 1342 if (result->is_user)
1335 1343 *result->is_user = 1;
1336 1344 if (result->sid_prefix)
1337 1345 *result->sid_prefix = NULL;
1338 1346 if (result->rid)
1339 1347 *result->rid = 0;
1340 1348 break;
1341 1349 }
1342 1350 }
1343 1351 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1344 1352
1345 1353 /* Reset get_handle for new resquests */
1346 1354 get_handle->mapping_num = 0;
1347 1355 return (status);
1348 1356
1349 1357 error:
1350 1358 for (i = 0; i < get_handle->mapping_num; i++) {
1351 1359 result = &get_handle->result[i];
1352 1360
1353 1361 *result->stat = status;
1354 1362 if (result->uid)
1355 1363 *result->uid = UID_NOBODY;
1356 1364 if (result->gid)
1357 1365 *result->gid = GID_NOBODY;
1358 1366 if (result->pid)
1359 1367 *result->pid = UID_NOBODY;
1360 1368 if (result->is_user)
1361 1369 *result->is_user = 1;
1362 1370 if (result->sid_prefix)
1363 1371 *result->sid_prefix = NULL;
1364 1372 if (result->rid)
1365 1373 *result->rid = 0;
1366 1374 }
1367 1375
1368 1376 /* Reset get_handle for new resquests */
1369 1377 get_handle->mapping_num = 0;
1370 1378 return (status);
1371 1379 }
1372 1380
1373 1381
1374 1382 /*
1375 1383 * Destroy the "get mapping" handle
1376 1384 */
1377 1385 void
1378 1386 kidmap_get_destroy(idmap_get_handle_t *get_handle)
1379 1387 {
1380 1388 if (get_handle == NULL)
1381 1389 return;
1382 1390
1383 1391 kmem_free(get_handle->mapping,
1384 1392 (sizeof (idmap_mapping)) * get_handle->mapping_size);
1385 1393 get_handle->mapping = NULL;
1386 1394
1387 1395 kmem_free(get_handle->result,
1388 1396 (sizeof (idmap_get_res)) * get_handle->mapping_size);
1389 1397 get_handle->result = NULL;
1390 1398
1391 1399 kmem_free(get_handle, sizeof (idmap_get_handle_t));
1392 1400 }
1393 1401
1394 1402
1395 1403 static int
1396 1404 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args,
1397 1405 caddr_t args, xdrproc_t xdr_res, caddr_t res)
1398 1406 {
1399 1407 XDR xdr_ctx;
1400 1408 struct rpc_msg reply_msg;
1401 1409 char *inbuf_ptr = NULL;
1402 1410 size_t inbuf_size = 4096;
1403 1411 char *outbuf_ptr = NULL;
1404 1412 size_t outbuf_size = 4096;
1405 1413 size_t size;
1406 1414 int status = 0;
1407 1415 door_arg_t params;
1408 1416 int retry = 0;
1409 1417 struct rpc_msg call_msg;
1410 1418
1411 1419 params.rbuf = NULL;
1412 1420 params.rsize = 0;
1413 1421
1414 1422 retry:
1415 1423 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP);
1416 1424 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP);
1417 1425
1418 1426 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE);
1419 1427
1420 1428 call_msg.rm_call.cb_prog = IDMAP_PROG;
1421 1429 call_msg.rm_call.cb_vers = IDMAP_V1;
1422 1430 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id);
1423 1431
1424 1432 if (!xdr_callhdr(&xdr_ctx, &call_msg)) {
1425 1433 #ifdef DEBUG
1426 1434 zcmn_err(zs->zone_id, CE_WARN,
1427 1435 "idmap: xdr encoding header error");
1428 1436 #endif /* DEBUG */
1429 1437 status = -1;
1430 1438 goto exit;
1431 1439 }
1432 1440
1433 1441 if (!xdr_uint32(&xdr_ctx, &op) ||
1434 1442 /* Auth none */
1435 1443 !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1436 1444 !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1437 1445 /* RPC args */
1438 1446 !xdr_args(&xdr_ctx, args)) {
1439 1447 #ifdef DEBUG
1440 1448 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error");
1441 1449 #endif /* DEBUG */
1442 1450 if (retry > 2) {
1443 1451 status = -1;
1444 1452 goto exit;
1445 1453 }
1446 1454 retry++;
1447 1455 if (inbuf_ptr) {
1448 1456 kmem_free(inbuf_ptr, inbuf_size);
1449 1457 inbuf_ptr = NULL;
1450 1458 }
1451 1459 if (outbuf_ptr) {
1452 1460 kmem_free(outbuf_ptr, outbuf_size);
1453 1461 outbuf_ptr = NULL;
1454 1462 }
1455 1463 if ((size = xdr_sizeof(xdr_args, args)) == 0) {
1456 1464 #ifdef DEBUG
1457 1465 zcmn_err(zs->zone_id, CE_WARN,
1458 1466 "idmap: xdr_sizeof error");
1459 1467 #endif /* DEBUG */
1460 1468 status = -1;
1461 1469 goto exit;
1462 1470 }
1463 1471 inbuf_size = size + 1024;
1464 1472 outbuf_size = size + 1024;
1465 1473 goto retry;
1466 1474 }
1467 1475
1468 1476 params.data_ptr = inbuf_ptr;
1469 1477 params.data_size = XDR_GETPOS(&xdr_ctx);
1470 1478 params.desc_ptr = NULL;
1471 1479 params.desc_num = 0;
1472 1480 params.rbuf = outbuf_ptr;
1473 1481 params.rsize = outbuf_size;
1474 1482
1475 1483 if (kidmap_call_door(zs, ¶ms) != 0) {
1476 1484 status = -1;
1477 1485 goto exit;
1478 1486 }
1479 1487
1480 1488 reply_msg.acpted_rply.ar_verf = _null_auth;
1481 1489 reply_msg.acpted_rply.ar_results.where = res;
1482 1490 reply_msg.acpted_rply.ar_results.proc = xdr_res;
1483 1491 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE);
1484 1492 if (xdr_replymsg(&xdr_ctx, &reply_msg)) {
1485 1493 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED ||
1486 1494 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
1487 1495 status = -1;
1488 1496 goto exit;
1489 1497 }
1490 1498 } else {
1491 1499 #ifdef DEBUG
1492 1500 zcmn_err(zs->zone_id, CE_WARN,
1493 1501 "idmap: xdr decoding reply message error");
1494 1502 #endif /* DEBUG */
1495 1503 status = -1;
1496 1504 }
1497 1505
1498 1506 exit:
1499 1507 if (outbuf_ptr != params.rbuf && params.rbuf != NULL)
1500 1508 kmem_free(params.rbuf, params.rsize);
1501 1509 if (inbuf_ptr)
1502 1510 kmem_free(inbuf_ptr, inbuf_size);
1503 1511 if (outbuf_ptr)
1504 1512 kmem_free(outbuf_ptr, outbuf_size);
1505 1513 return (status);
1506 1514 }
|
↓ open down ↓ |
187 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX