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