1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Service routines 30 */ 31 32 #include "idmapd.h" 33 #include "idmap_priv.h" 34 #include <signal.h> 35 #include <thread.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <errno.h> 39 #include <assert.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <ucred.h> 43 #include <pwd.h> 44 #include <auth_attr.h> 45 #include <secdb.h> 46 47 #define _VALIDATE_LIST_CB_DATA(col, val, siz)\ 48 retcode = validate_list_cb_data(cb_data, argc, argv, col,\ 49 (uchar_t **)val, siz);\ 50 if (retcode == IDMAP_NEXT) {\ 51 result->retcode = IDMAP_NEXT;\ 52 return (0);\ 53 } else if (retcode < 0) {\ 54 result->retcode = retcode;\ 55 return (1);\ 56 } 57 58 #define PROCESS_LIST_SVC_SQL(rcode, db, sql, limit, cb, res, len)\ 59 rcode = process_list_svc_sql(db, sql, limit, cb, res);\ 60 if (rcode == IDMAP_ERR_BUSY)\ 61 res->retcode = IDMAP_ERR_BUSY;\ 62 else if (rcode == IDMAP_SUCCESS && len == 0)\ 63 res->retcode = IDMAP_ERR_NOTFOUND; 64 65 66 #define STRDUP_OR_FAIL(to, from) \ 67 if ((from) == NULL) \ 68 to = NULL; \ 69 else { \ 70 if ((to = strdup(from)) == NULL) \ 71 return (1); \ 72 } 73 74 /* ARGSUSED */ 75 bool_t 76 idmap_null_1_svc(void *result, struct svc_req *rqstp) 77 { 78 return (TRUE); 79 } 80 81 /* 82 * RPC layer allocates empty strings to replace NULL char *. 83 * This utility function frees these empty strings. 84 */ 85 static void 86 sanitize_mapping_request(idmap_mapping *req) 87 { 88 free(req->id1name); 89 req->id1name = NULL; 90 free(req->id1domain); 91 req->id1domain = NULL; 92 free(req->id2name); 93 req->id2name = NULL; 94 free(req->id2domain); 95 req->id2domain = NULL; 96 } 97 98 /* ARGSUSED */ 99 bool_t 100 idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch, 101 idmap_ids_res *result, struct svc_req *rqstp) 102 { 103 sqlite *cache = NULL, *db = NULL; 104 lookup_state_t state; 105 idmap_retcode retcode, winrc; 106 uint_t i; 107 108 /* Init */ 109 (void) memset(result, 0, sizeof (*result)); 110 (void) memset(&state, 0, sizeof (state)); 111 112 /* Return success if nothing was requested */ 113 if (batch.idmap_mapping_batch_len < 1) 114 goto out; 115 116 /* Get cache handle */ 117 result->retcode = get_cache_handle(&cache); 118 if (result->retcode != IDMAP_SUCCESS) 119 goto out; 120 121 /* Get db handle */ 122 result->retcode = get_db_handle(&db); 123 if (result->retcode != IDMAP_SUCCESS) 124 goto out; 125 126 /* Allocate result array */ 127 result->ids.ids_val = calloc(batch.idmap_mapping_batch_len, 128 sizeof (idmap_id_res)); 129 if (result->ids.ids_val == NULL) { 130 idmapdlog(LOG_ERR, "Out of memory"); 131 result->retcode = IDMAP_ERR_MEMORY; 132 goto out; 133 } 134 result->ids.ids_len = batch.idmap_mapping_batch_len; 135 136 /* Allocate hash table to check for duplicate sids */ 137 state.sid_history = calloc(batch.idmap_mapping_batch_len, 138 sizeof (*state.sid_history)); 139 if (state.sid_history == NULL) { 140 idmapdlog(LOG_ERR, "Out of memory"); 141 result->retcode = IDMAP_ERR_MEMORY; 142 goto out; 143 } 144 state.sid_history_size = batch.idmap_mapping_batch_len; 145 for (i = 0; i < state.sid_history_size; i++) { 146 state.sid_history[i].key = state.sid_history_size; 147 state.sid_history[i].next = state.sid_history_size; 148 } 149 state.batch = &batch; 150 state.result = result; 151 152 /* Init our 'done' flags */ 153 state.sid2pid_done = state.pid2sid_done = TRUE; 154 155 /* First stage */ 156 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 157 state.curpos = i; 158 (void) sanitize_mapping_request( 159 &batch.idmap_mapping_batch_val[i]); 160 if (IS_BATCH_SID(batch, i)) { 161 retcode = sid2pid_first_pass( 162 &state, 163 cache, 164 &batch.idmap_mapping_batch_val[i], 165 &result->ids.ids_val[i]); 166 } else if (IS_BATCH_UID(batch, i)) { 167 retcode = pid2sid_first_pass( 168 &state, 169 cache, 170 db, 171 &batch.idmap_mapping_batch_val[i], 172 &result->ids.ids_val[i], 1, 0); 173 } else if (IS_BATCH_GID(batch, i)) { 174 retcode = pid2sid_first_pass( 175 &state, 176 cache, 177 db, 178 &batch.idmap_mapping_batch_val[i], 179 &result->ids.ids_val[i], 0, 0); 180 } else { 181 result->ids.ids_val[i].retcode = IDMAP_ERR_IDTYPE; 182 continue; 183 } 184 if (IDMAP_FATAL_ERROR(retcode)) { 185 result->retcode = retcode; 186 goto out; 187 } 188 } 189 190 /* Check if we are done */ 191 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE) 192 goto out; 193 194 /* Process Windows server lookups for sid2name */ 195 if (state.ad_nqueries) { 196 winrc = lookup_win_batch_sid2name(&state, &batch, 197 result); 198 if (IDMAP_FATAL_ERROR(winrc)) { 199 result->retcode = winrc; 200 goto out; 201 } 202 } else 203 winrc = IDMAP_SUCCESS; 204 205 /* Reset sid2pid 'done' flag */ 206 state.sid2pid_done = TRUE; 207 208 /* Second stage */ 209 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 210 state.curpos = i; 211 /* Process sid to pid ONLY */ 212 if (IS_BATCH_SID(batch, i)) { 213 if (IDMAP_ERROR(winrc)) 214 result->ids.ids_val[i].retcode = winrc; 215 retcode = sid2pid_second_pass( 216 &state, 217 cache, 218 db, 219 &batch.idmap_mapping_batch_val[i], 220 &result->ids.ids_val[i]); 221 if (IDMAP_FATAL_ERROR(retcode)) { 222 result->retcode = retcode; 223 goto out; 224 } 225 } 226 } 227 228 /* Check if we are done */ 229 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE) 230 goto out; 231 232 /* Reset our 'done' flags */ 233 state.sid2pid_done = state.pid2sid_done = TRUE; 234 235 /* Update cache in a single transaction */ 236 if (sql_exec_no_cb(cache, "BEGIN TRANSACTION;") != IDMAP_SUCCESS) 237 goto out; 238 239 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 240 state.curpos = i; 241 if (IS_BATCH_SID(batch, i)) { 242 (void) update_cache_sid2pid( 243 &state, 244 cache, 245 &batch.idmap_mapping_batch_val[i], 246 &result->ids.ids_val[i]); 247 } else if ((IS_BATCH_UID(batch, i)) || 248 (IS_BATCH_GID(batch, i))) { 249 (void) update_cache_pid2sid( 250 &state, 251 cache, 252 &batch.idmap_mapping_batch_val[i], 253 &result->ids.ids_val[i]); 254 } 255 } 256 257 /* Commit if we have at least one successful update */ 258 if (state.sid2pid_done == FALSE || state.pid2sid_done == FALSE) 259 (void) sql_exec_no_cb(cache, "COMMIT TRANSACTION;"); 260 else 261 (void) sql_exec_no_cb(cache, "END TRANSACTION;"); 262 263 out: 264 if (state.sid_history) 265 free(state.sid_history); 266 if (IDMAP_ERROR(result->retcode)) { 267 xdr_free(xdr_idmap_ids_res, (caddr_t)result); 268 result->ids.ids_len = 0; 269 result->ids.ids_val = NULL; 270 } 271 result->retcode = idmap_stat4prot(result->retcode); 272 return (TRUE); 273 } 274 275 276 /* ARGSUSED */ 277 static 278 int 279 list_mappings_cb(void *parg, int argc, char **argv, char **colnames) 280 { 281 list_cb_data_t *cb_data; 282 char *str; 283 idmap_mappings_res *result; 284 idmap_retcode retcode; 285 int w2u, u2w; 286 char *end; 287 static int validated_column_names = 0; 288 289 if (!validated_column_names) { 290 assert(strcmp(colnames[0], "rowid") == 0); 291 assert(strcmp(colnames[1], "sidprefix") == 0); 292 assert(strcmp(colnames[2], "rid") == 0); 293 assert(strcmp(colnames[3], "pid") == 0); 294 assert(strcmp(colnames[4], "w2u") == 0); 295 assert(strcmp(colnames[5], "u2w") == 0); 296 assert(strcmp(colnames[6], "windomain") == 0); 297 assert(strcmp(colnames[7], "canon_winname") == 0); 298 assert(strcmp(colnames[8], "unixname") == 0); 299 assert(strcmp(colnames[9], "is_user") == 0); 300 assert(strcmp(colnames[10], "is_wuser") == 0); 301 validated_column_names = 1; 302 } 303 304 305 cb_data = (list_cb_data_t *)parg; 306 result = (idmap_mappings_res *)cb_data->result; 307 308 _VALIDATE_LIST_CB_DATA(11, &result->mappings.mappings_val, 309 sizeof (idmap_mapping)); 310 311 result->mappings.mappings_len++; 312 313 if ((str = strdup(argv[1])) == NULL) 314 return (1); 315 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.prefix = 316 str; 317 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.rid = 318 strtoul(argv[2], &end, 10); 319 result->mappings.mappings_val[cb_data->next].id1.idtype = 320 strtol(argv[10], &end, 10) ? IDMAP_USID : IDMAP_GSID; 321 322 result->mappings.mappings_val[cb_data->next].id2.idmap_id_u.uid = 323 strtoul(argv[3], &end, 10); 324 result->mappings.mappings_val[cb_data->next].id2.idtype = 325 strtol(argv[9], &end, 10) ? IDMAP_UID : IDMAP_GID; 326 327 w2u = argv[4] ? strtol(argv[4], &end, 10) : 0; 328 u2w = argv[5] ? strtol(argv[5], &end, 10) : 0; 329 330 if (w2u > 0 && u2w == 0) 331 result->mappings.mappings_val[cb_data->next].direction = 332 IDMAP_DIRECTION_W2U; 333 else if (w2u == 0 && u2w > 0) 334 result->mappings.mappings_val[cb_data->next].direction = 335 IDMAP_DIRECTION_U2W; 336 else 337 result->mappings.mappings_val[cb_data->next].direction = 338 IDMAP_DIRECTION_BI; 339 340 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1domain, 341 argv[6]); 342 343 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1name, 344 argv[7]); 345 346 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id2name, 347 argv[8]); 348 349 350 result->lastrowid = strtoll(argv[0], &end, 10); 351 cb_data->next++; 352 result->retcode = IDMAP_SUCCESS; 353 return (0); 354 } 355 356 357 /* ARGSUSED */ 358 bool_t 359 idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, 360 idmap_mappings_res *result, struct svc_req *rqstp) 361 { 362 sqlite *cache = NULL; 363 char lbuf[30], rbuf[30]; 364 uint64_t maxlimit; 365 idmap_retcode retcode; 366 char *sql = NULL; 367 368 (void) memset(result, 0, sizeof (*result)); 369 lbuf[0] = rbuf[0] = 0; 370 371 RDLOCK_CONFIG(); 372 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; 373 UNLOCK_CONFIG(); 374 375 /* Get cache handle */ 376 result->retcode = get_cache_handle(&cache); 377 if (result->retcode != IDMAP_SUCCESS) 378 goto out; 379 380 result->retcode = IDMAP_ERR_INTERNAL; 381 382 /* Create LIMIT expression. */ 383 if (limit == 0 || (maxlimit > 0 && maxlimit < limit)) 384 limit = maxlimit; 385 if (limit > 0) 386 (void) snprintf(lbuf, sizeof (lbuf), 387 "LIMIT %" PRIu64, limit + 1ULL); 388 389 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid); 390 391 /* 392 * Combine all the above into a giant SELECT statement that 393 * will return the requested mappings 394 */ 395 sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, u2w, " 396 "windomain, canon_winname, unixname, is_user, is_wuser " 397 " FROM idmap_cache WHERE " 398 " %s %s;", 399 rbuf, lbuf); 400 if (sql == NULL) { 401 idmapdlog(LOG_ERR, "Out of memory"); 402 goto out; 403 } 404 405 /* Execute the SQL statement and update the return buffer */ 406 PROCESS_LIST_SVC_SQL(retcode, cache, sql, limit, list_mappings_cb, 407 result, result->mappings.mappings_len); 408 409 out: 410 if (sql) 411 sqlite_freemem(sql); 412 if (IDMAP_ERROR(result->retcode)) 413 (void) xdr_free(xdr_idmap_mappings_res, (caddr_t)result); 414 result->retcode = idmap_stat4prot(result->retcode); 415 return (TRUE); 416 } 417 418 419 /* ARGSUSED */ 420 static 421 int 422 list_namerules_cb(void *parg, int argc, char **argv, char **colnames) 423 { 424 list_cb_data_t *cb_data; 425 idmap_namerules_res *result; 426 idmap_retcode retcode; 427 int w2u_order, u2w_order; 428 char *end; 429 static int validated_column_names = 0; 430 431 if (!validated_column_names) { 432 assert(strcmp(colnames[0], "rowid") == 0); 433 assert(strcmp(colnames[1], "is_user") == 0); 434 assert(strcmp(colnames[2], "is_wuser") == 0); 435 assert(strcmp(colnames[3], "windomain") == 0); 436 assert(strcmp(colnames[4], "winname_display") == 0); 437 assert(strcmp(colnames[5], "is_nt4") == 0); 438 assert(strcmp(colnames[6], "unixname") == 0); 439 assert(strcmp(colnames[7], "w2u_order") == 0); 440 assert(strcmp(colnames[8], "u2w_order") == 0); 441 validated_column_names = 1; 442 } 443 444 cb_data = (list_cb_data_t *)parg; 445 result = (idmap_namerules_res *)cb_data->result; 446 447 _VALIDATE_LIST_CB_DATA(9, &result->rules.rules_val, 448 sizeof (idmap_namerule)); 449 450 result->rules.rules_len++; 451 452 result->rules.rules_val[cb_data->next].is_user = 453 strtol(argv[1], &end, 10); 454 455 result->rules.rules_val[cb_data->next].is_wuser = 456 strtol(argv[2], &end, 10); 457 458 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].windomain, 459 argv[3]); 460 461 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].winname, 462 argv[4]); 463 464 result->rules.rules_val[cb_data->next].is_nt4 = 465 strtol(argv[5], &end, 10); 466 467 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].unixname, 468 argv[6]); 469 470 w2u_order = argv[7] ? strtol(argv[7], &end, 10) : 0; 471 u2w_order = argv[8] ? strtol(argv[8], &end, 10) : 0; 472 473 if (w2u_order > 0 && u2w_order == 0) 474 result->rules.rules_val[cb_data->next].direction = 475 IDMAP_DIRECTION_W2U; 476 else if (w2u_order == 0 && u2w_order > 0) 477 result->rules.rules_val[cb_data->next].direction = 478 IDMAP_DIRECTION_U2W; 479 else 480 result->rules.rules_val[cb_data->next].direction = 481 IDMAP_DIRECTION_BI; 482 483 result->lastrowid = strtoll(argv[0], &end, 10); 484 cb_data->next++; 485 result->retcode = IDMAP_SUCCESS; 486 return (0); 487 } 488 489 490 /* ARGSUSED */ 491 bool_t 492 idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid, 493 uint64_t limit, idmap_namerules_res *result, 494 struct svc_req *rqstp) 495 { 496 497 sqlite *db = NULL; 498 char w2ubuf[15], u2wbuf[15]; 499 char lbuf[30], rbuf[30]; 500 char *sql = NULL; 501 char *expr = NULL; 502 uint64_t maxlimit; 503 idmap_retcode retcode; 504 505 (void) memset(result, 0, sizeof (*result)); 506 lbuf[0] = rbuf[0] = 0; 507 508 RDLOCK_CONFIG(); 509 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; 510 UNLOCK_CONFIG(); 511 512 /* Get db handle */ 513 result->retcode = get_db_handle(&db); 514 if (result->retcode != IDMAP_SUCCESS) 515 goto out; 516 517 result->retcode = IDMAP_ERR_INTERNAL; 518 519 w2ubuf[0] = u2wbuf[0] = 0; 520 if (rule.direction == IDMAP_DIRECTION_BI) { 521 (void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0"); 522 (void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0"); 523 } else if (rule.direction == IDMAP_DIRECTION_W2U) { 524 (void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0"); 525 (void) snprintf(u2wbuf, sizeof (u2wbuf), 526 "AND (u2w_order = 0 OR u2w_order ISNULL)"); 527 } else if (rule.direction == IDMAP_DIRECTION_U2W) { 528 (void) snprintf(w2ubuf, sizeof (w2ubuf), 529 "AND (w2u_order = 0 OR w2u_order ISNULL)"); 530 (void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0"); 531 } 532 533 retcode = gen_sql_expr_from_rule(&rule, &expr); 534 if (retcode != IDMAP_SUCCESS) 535 goto out; 536 537 /* Create LIMIT expression. */ 538 if (limit == 0 || (maxlimit > 0 && maxlimit < limit)) 539 limit = maxlimit; 540 if (limit > 0) 541 (void) snprintf(lbuf, sizeof (lbuf), 542 "LIMIT %" PRIu64, limit + 1ULL); 543 544 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid); 545 546 /* 547 * Combine all the above into a giant SELECT statement that 548 * will return the requested rules 549 */ 550 sql = sqlite_mprintf("SELECT rowid, is_user, is_wuser, windomain, " 551 "winname_display, is_nt4, unixname, w2u_order, u2w_order " 552 "FROM namerules WHERE " 553 " %s %s %s %s %s;", 554 rbuf, expr, w2ubuf, u2wbuf, lbuf); 555 556 if (sql == NULL) { 557 idmapdlog(LOG_ERR, "Out of memory"); 558 goto out; 559 } 560 561 /* Execute the SQL statement and update the return buffer */ 562 PROCESS_LIST_SVC_SQL(retcode, db, sql, limit, list_namerules_cb, 563 result, result->rules.rules_len); 564 565 out: 566 if (expr) 567 sqlite_freemem(expr); 568 if (sql) 569 sqlite_freemem(sql); 570 if (IDMAP_ERROR(result->retcode)) 571 (void) xdr_free(xdr_idmap_namerules_res, (caddr_t)result); 572 result->retcode = idmap_stat4prot(result->retcode); 573 return (TRUE); 574 } 575 576 #define IDMAP_RULES_AUTH "solaris.admin.idmap.rules" 577 static int 578 verify_rules_auth(struct svc_req *rqstp) 579 { 580 ucred_t *uc = NULL; 581 uid_t uid; 582 char buf[1024]; 583 struct passwd pwd; 584 const char *me = "verify_rules_auth"; 585 586 if (svc_getcallerucred(rqstp->rq_xprt, &uc) != 0) { 587 idmapdlog(LOG_ERR, 588 "%s: svc_getcallerucred failed (errno=%d)", 589 me, errno); 590 return (-1); 591 } 592 593 uid = ucred_geteuid(uc); 594 if (uid == (uid_t)-1) { 595 idmapdlog(LOG_ERR, 596 "%s: ucred_geteuid failed (errno=%d)", 597 me, errno); 598 ucred_free(uc); 599 return (-1); 600 } 601 602 if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) { 603 idmapdlog(LOG_ERR, 604 "%s: getpwuid_r(%u) failed (errno=%d)", 605 me, uid, errno); 606 ucred_free(uc); 607 return (-1); 608 } 609 610 if (chkauthattr(IDMAP_RULES_AUTH, pwd.pw_name) != 1) { 611 idmapdlog(LOG_INFO, 612 "%s: %s does not have authorization.", 613 me, pwd.pw_name); 614 ucred_free(uc); 615 return (-1); 616 } 617 618 ucred_free(uc); 619 return (1); 620 } 621 622 /* 623 * Meaning of the return values is the following: For retcode == 624 * IDMAP_SUCCESS, everything went OK and error_index is 625 * undefined. Otherwise, error_index >=0 shows the failed batch 626 * element. errro_index == -1 indicates failure at the beginning, 627 * error_index == -2 at the end. 628 */ 629 630 /* ARGSUSED */ 631 bool_t 632 idmap_update_1_svc(idmap_update_batch batch, idmap_update_res *res, 633 struct svc_req *rqstp) 634 { 635 sqlite *db = NULL; 636 idmap_update_op *up; 637 int i; 638 int trans = FALSE; 639 640 res->error_index = -1; 641 (void) memset(&res->error_rule, 0, sizeof (res->error_rule)); 642 (void) memset(&res->conflict_rule, 0, sizeof (res->conflict_rule)); 643 644 if (verify_rules_auth(rqstp) < 0) { 645 res->retcode = IDMAP_ERR_PERMISSION_DENIED; 646 goto out; 647 } 648 649 if (batch.idmap_update_batch_len == 0 || 650 batch.idmap_update_batch_val == NULL) { 651 res->retcode = IDMAP_SUCCESS; 652 goto out; 653 } 654 655 /* Get db handle */ 656 res->retcode = get_db_handle(&db); 657 if (res->retcode != IDMAP_SUCCESS) 658 goto out; 659 660 res->retcode = sql_exec_no_cb(db, "BEGIN TRANSACTION;"); 661 if (res->retcode != IDMAP_SUCCESS) 662 goto out; 663 trans = TRUE; 664 665 for (i = 0; i < batch.idmap_update_batch_len; i++) { 666 up = &batch.idmap_update_batch_val[i]; 667 switch (up->opnum) { 668 case OP_NONE: 669 res->retcode = IDMAP_SUCCESS; 670 break; 671 case OP_ADD_NAMERULE: 672 res->retcode = add_namerule(db, 673 &up->idmap_update_op_u.rule); 674 break; 675 case OP_RM_NAMERULE: 676 res->retcode = rm_namerule(db, 677 &up->idmap_update_op_u.rule); 678 break; 679 case OP_FLUSH_NAMERULES: 680 res->retcode = flush_namerules(db); 681 break; 682 default: 683 res->retcode = IDMAP_ERR_NOTSUPPORTED; 684 break; 685 }; 686 687 if (res->retcode != IDMAP_SUCCESS) { 688 res->error_index = i; 689 if (up->opnum == OP_ADD_NAMERULE || 690 up->opnum == OP_RM_NAMERULE) { 691 idmap_stat r2 = 692 idmap_namerule_cpy(&res->error_rule, 693 &up->idmap_update_op_u.rule); 694 if (r2 != IDMAP_SUCCESS) 695 res->retcode = r2; 696 } 697 goto out; 698 } 699 } 700 701 out: 702 if (trans) { 703 if (res->retcode == IDMAP_SUCCESS) { 704 res->retcode = 705 sql_exec_no_cb(db, "COMMIT TRANSACTION;"); 706 if (res->retcode != IDMAP_SUCCESS) 707 res->error_index = -2; 708 } 709 else 710 (void) sql_exec_no_cb(db, "ROLLBACK TRANSACTION;"); 711 } 712 713 res->retcode = idmap_stat4prot(res->retcode); 714 715 return (TRUE); 716 } 717 718 719 /* ARGSUSED */ 720 bool_t 721 idmap_get_mapped_id_by_name_1_svc(idmap_mapping request, 722 idmap_mappings_res *result, struct svc_req *rqstp) 723 { 724 sqlite *cache = NULL, *db = NULL; 725 726 /* Init */ 727 (void) memset(result, 0, sizeof (*result)); 728 729 /* Get cache handle */ 730 result->retcode = get_cache_handle(&cache); 731 if (result->retcode != IDMAP_SUCCESS) 732 goto out; 733 734 /* Get db handle */ 735 result->retcode = get_db_handle(&db); 736 if (result->retcode != IDMAP_SUCCESS) 737 goto out; 738 739 /* Allocate result */ 740 result->mappings.mappings_val = calloc(1, sizeof (idmap_mapping)); 741 if (result->mappings.mappings_val == NULL) { 742 idmapdlog(LOG_ERR, "Out of memory"); 743 result->retcode = IDMAP_ERR_MEMORY; 744 goto out; 745 } 746 result->mappings.mappings_len = 1; 747 748 749 if (IS_REQUEST_SID(request, 1)) { 750 result->retcode = get_w2u_mapping( 751 cache, 752 db, 753 &request, 754 result->mappings.mappings_val); 755 } else if (IS_REQUEST_UID(request)) { 756 result->retcode = get_u2w_mapping( 757 cache, 758 db, 759 &request, 760 result->mappings.mappings_val, 761 1); 762 } else if (IS_REQUEST_GID(request)) { 763 result->retcode = get_u2w_mapping( 764 cache, 765 db, 766 &request, 767 result->mappings.mappings_val, 768 0); 769 } else { 770 result->retcode = IDMAP_ERR_IDTYPE; 771 } 772 773 out: 774 if (IDMAP_FATAL_ERROR(result->retcode)) { 775 xdr_free(xdr_idmap_mappings_res, (caddr_t)result); 776 result->mappings.mappings_len = 0; 777 result->mappings.mappings_val = NULL; 778 } 779 result->retcode = idmap_stat4prot(result->retcode); 780 return (TRUE); 781 } 782 783 784 /* ARGSUSED */ 785 int 786 idmap_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, 787 caddr_t result) 788 { 789 (void) xdr_free(xdr_result, result); 790 return (TRUE); 791 } 792