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