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 * Database related utility routines 30 */ 31 32 #include <atomic.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <errno.h> 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <rpc/rpc.h> 40 #include <sys/sid.h> 41 #include <time.h> 42 #include <pwd.h> 43 #include <grp.h> 44 #include <pthread.h> 45 #include <assert.h> 46 #include <sys/u8_textprep.h> 47 48 #include "idmapd.h" 49 #include "adutils.h" 50 #include "string.h" 51 #include "idmap_priv.h" 52 #include "schema.h" 53 54 55 static int degraded = 0; /* whether the FMRI has been marked degraded */ 56 57 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 58 sqlite_vm **, int *, int, const char ***); 59 static idmap_retcode lookup_wksids_name2sid(const char *, char **, char **, 60 idmap_rid_t *, int *); 61 62 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 63 64 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 65 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 66 67 #define AVOID_NAMESERVICE(req)\ 68 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 69 70 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 71 72 #define LOCALRID_MIN 1000 73 74 75 76 typedef enum init_db_option { 77 FAIL_IF_CORRUPT = 0, 78 REMOVE_IF_CORRUPT = 1 79 } init_db_option_t; 80 81 /* 82 * Thread specfic data to hold the database handles so that the 83 * databaes are not opened and closed for every request. It also 84 * contains the sqlite busy handler structure. 85 */ 86 87 struct idmap_busy { 88 const char *name; 89 const int *delays; 90 int delay_size; 91 int total; 92 int sec; 93 }; 94 95 96 typedef struct idmap_tsd { 97 sqlite *db_db; 98 sqlite *cache_db; 99 struct idmap_busy cache_busy; 100 struct idmap_busy db_busy; 101 } idmap_tsd_t; 102 103 104 105 static const int cache_delay_table[] = 106 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 107 50, 50, 60, 70, 80, 90, 100}; 108 109 static const int db_delay_table[] = 110 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 111 112 113 static pthread_key_t idmap_tsd_key; 114 115 void 116 idmap_tsd_destroy(void *key) 117 { 118 119 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 120 if (tsd) { 121 if (tsd->db_db) 122 (void) sqlite_close(tsd->db_db); 123 if (tsd->cache_db) 124 (void) sqlite_close(tsd->cache_db); 125 free(tsd); 126 } 127 } 128 129 int 130 idmap_init_tsd_key(void) 131 { 132 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 133 } 134 135 136 137 idmap_tsd_t * 138 idmap_get_tsd(void) 139 { 140 idmap_tsd_t *tsd; 141 142 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 143 /* No thread specific data so create it */ 144 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 145 /* Initialize thread specific data */ 146 (void) memset(tsd, 0, sizeof (*tsd)); 147 /* save the trhread specific data */ 148 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 149 /* Can't store key */ 150 free(tsd); 151 tsd = NULL; 152 } 153 } else { 154 tsd = NULL; 155 } 156 } 157 158 return (tsd); 159 } 160 161 static 162 const char * 163 get_fmri(void) 164 { 165 static char *fmri = NULL; 166 static char buf[60]; 167 char *s; 168 169 membar_consumer(); 170 s = fmri; 171 if (s != NULL && *s == '\0') 172 return (NULL); 173 else if (s != NULL) 174 return (s); 175 176 if ((s = getenv("SMF_FMRI")) == NULL || strlen(s) >= sizeof (buf)) 177 buf[0] = '\0'; 178 else 179 (void) strlcpy(buf, s, sizeof (buf)); 180 181 membar_producer(); 182 fmri = buf; 183 184 return (get_fmri()); 185 } 186 187 /* 188 * Wrappers for smf_degrade/restore_instance() 189 * 190 * smf_restore_instance() is too heavy duty to be calling every time we 191 * have a successful AD name<->SID lookup. 192 */ 193 void 194 degrade_svc(void) 195 { 196 const char *fmri; 197 198 if ((fmri = get_fmri()) == NULL) 199 return; 200 201 membar_consumer(); 202 if (degraded) 203 return; 204 205 (void) smf_degrade_instance(fmri, 0); 206 membar_producer(); 207 degraded = 1; 208 } 209 210 211 void 212 restore_svc(void) 213 { 214 const char *fmri; 215 216 if ((fmri = get_fmri()) == NULL) 217 return; 218 219 membar_consumer(); 220 if (!degraded) 221 return; 222 (void) smf_restore_instance(fmri); 223 membar_producer(); 224 degraded = 0; 225 } 226 227 /* 228 * A simple wrapper around u8_textprep_str() that returns the Unicode 229 * lower-case version of some string. The result must be freed. 230 */ 231 char * 232 tolower_u8(const char *s) 233 { 234 char *res = NULL; 235 char *outs; 236 size_t inlen, outlen, inbytesleft, outbytesleft; 237 int rc, err; 238 239 /* 240 * u8_textprep_str() does not allocate memory. The input and 241 * output buffers may differ in size (though that would be more 242 * likely when normalization is done). We have to loop over it... 243 * 244 * To improve the chances that we can avoid looping we add 10 245 * bytes of output buffer room the first go around. 246 */ 247 inlen = inbytesleft = strlen(s); 248 outlen = outbytesleft = inlen + 10; 249 if ((res = malloc(outlen)) == NULL) 250 return (NULL); 251 outs = res; 252 253 while ((rc = u8_textprep_str((char *)s, &inbytesleft, outs, 254 &outbytesleft, U8_TEXTPREP_TOLOWER, U8_UNICODE_LATEST, &err)) < 0 && 255 err == E2BIG) { 256 if ((res = realloc(res, outlen + inbytesleft)) == NULL) 257 return (NULL); 258 /* adjust input/output buffer pointers */ 259 s += (inlen - inbytesleft); 260 outs = res + outlen - outbytesleft; 261 /* adjust outbytesleft and outlen */ 262 outlen += inbytesleft; 263 outbytesleft += inbytesleft; 264 } 265 266 if (rc < 0) { 267 free(res); 268 res = NULL; 269 return (NULL); 270 } 271 272 res[outlen - outbytesleft] = '\0'; 273 274 return (res); 275 } 276 277 static int sql_exec_tran_no_cb(sqlite *db, char *sql, const char *dbname, 278 const char *while_doing); 279 280 281 /* 282 * Initialize 'dbname' using 'sql' 283 */ 284 static 285 int 286 init_db_instance(const char *dbname, int version, 287 const char *detect_version_sql, char * const *sql, 288 init_db_option_t opt, int *created, int *upgraded) 289 { 290 int rc, curr_version; 291 int tries = 1; 292 int prio = LOG_NOTICE; 293 sqlite *db = NULL; 294 char *errmsg = NULL; 295 296 *created = 0; 297 *upgraded = 0; 298 299 if (opt == REMOVE_IF_CORRUPT) 300 tries = 3; 301 302 rinse_repeat: 303 if (tries == 0) { 304 idmapdlog(LOG_ERR, "Failed to initialize db %s", dbname); 305 return (-1); 306 } 307 if (tries-- == 1) 308 /* Last try, log errors */ 309 prio = LOG_ERR; 310 311 db = sqlite_open(dbname, 0600, &errmsg); 312 if (db == NULL) { 313 idmapdlog(prio, "Error creating database %s (%s)", 314 dbname, CHECK_NULL(errmsg)); 315 sqlite_freemem(errmsg); 316 if (opt == REMOVE_IF_CORRUPT) 317 (void) unlink(dbname); 318 goto rinse_repeat; 319 } 320 321 sqlite_busy_timeout(db, 3000); 322 323 /* Detect current version of schema in the db, if any */ 324 curr_version = 0; 325 if (detect_version_sql != NULL) { 326 char *end, **results; 327 int nrow; 328 329 #ifdef IDMAPD_DEBUG 330 (void) fprintf(stderr, "Schema version detection SQL: %s\n", 331 detect_version_sql); 332 #endif /* IDMAPD_DEBUG */ 333 rc = sqlite_get_table(db, detect_version_sql, &results, 334 &nrow, NULL, &errmsg); 335 if (rc != SQLITE_OK) { 336 idmapdlog(prio, 337 "Error detecting schema version of db %s (%s)", 338 dbname, errmsg); 339 sqlite_freemem(errmsg); 340 sqlite_free_table(results); 341 sqlite_close(db); 342 return (-1); 343 } 344 if (nrow != 1) { 345 idmapdlog(prio, 346 "Error detecting schema version of db %s", dbname); 347 sqlite_close(db); 348 sqlite_free_table(results); 349 return (-1); 350 } 351 curr_version = strtol(results[1], &end, 10); 352 sqlite_free_table(results); 353 } 354 355 if (curr_version < 0) { 356 if (opt == REMOVE_IF_CORRUPT) 357 (void) unlink(dbname); 358 goto rinse_repeat; 359 } 360 361 if (curr_version == version) 362 goto done; 363 364 /* Install or upgrade schema */ 365 #ifdef IDMAPD_DEBUG 366 (void) fprintf(stderr, "Schema init/upgrade SQL: %s\n", 367 sql[curr_version]); 368 #endif /* IDMAPD_DEBUG */ 369 rc = sql_exec_tran_no_cb(db, sql[curr_version], dbname, 370 (curr_version == 0) ? "installing schema" : "upgrading schema"); 371 if (rc != 0) { 372 idmapdlog(prio, "Error %s schema for db %s", dbname, 373 (curr_version == 0) ? "installing schema" : 374 "upgrading schema"); 375 if (opt == REMOVE_IF_CORRUPT) 376 (void) unlink(dbname); 377 goto rinse_repeat; 378 } 379 380 *upgraded = (curr_version > 0); 381 *created = (curr_version == 0); 382 383 done: 384 (void) sqlite_close(db); 385 return (0); 386 } 387 388 389 /* 390 * This is the SQLite database busy handler that retries the SQL 391 * operation until it is successful. 392 */ 393 int 394 /* LINTED E_FUNC_ARG_UNUSED */ 395 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 396 { 397 struct idmap_busy *busy = arg; 398 int delay; 399 struct timespec rqtp; 400 401 if (count == 1) { 402 busy->total = 0; 403 busy->sec = 2; 404 } 405 if (busy->total > 1000 * busy->sec) { 406 idmapdlog(LOG_ERR, 407 "Thread %d waited %d sec for the %s database", 408 pthread_self(), busy->sec, busy->name); 409 busy->sec++; 410 } 411 412 if (count <= busy->delay_size) { 413 delay = busy->delays[count-1]; 414 } else { 415 delay = busy->delays[busy->delay_size - 1]; 416 } 417 busy->total += delay; 418 rqtp.tv_sec = 0; 419 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 420 (void) nanosleep(&rqtp, NULL); 421 return (1); 422 } 423 424 425 /* 426 * Get the database handle 427 */ 428 idmap_retcode 429 get_db_handle(sqlite **db) 430 { 431 char *errmsg; 432 idmap_tsd_t *tsd; 433 434 /* 435 * Retrieve the db handle from thread-specific storage 436 * If none exists, open and store in thread-specific storage. 437 */ 438 if ((tsd = idmap_get_tsd()) == NULL) { 439 idmapdlog(LOG_ERR, 440 "Error getting thread specific data for %s", IDMAP_DBNAME); 441 return (IDMAP_ERR_MEMORY); 442 } 443 444 if (tsd->db_db == NULL) { 445 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 446 if (tsd->db_db == NULL) { 447 idmapdlog(LOG_ERR, "Error opening database %s (%s)", 448 IDMAP_DBNAME, CHECK_NULL(errmsg)); 449 sqlite_freemem(errmsg); 450 return (IDMAP_ERR_DB); 451 } 452 453 tsd->db_busy.name = IDMAP_DBNAME; 454 tsd->db_busy.delays = db_delay_table; 455 tsd->db_busy.delay_size = sizeof (db_delay_table) / 456 sizeof (int); 457 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 458 &tsd->db_busy); 459 } 460 *db = tsd->db_db; 461 return (IDMAP_SUCCESS); 462 } 463 464 /* 465 * Get the cache handle 466 */ 467 idmap_retcode 468 get_cache_handle(sqlite **cache) 469 { 470 char *errmsg; 471 idmap_tsd_t *tsd; 472 473 /* 474 * Retrieve the db handle from thread-specific storage 475 * If none exists, open and store in thread-specific storage. 476 */ 477 if ((tsd = idmap_get_tsd()) == NULL) { 478 idmapdlog(LOG_ERR, "Error getting thread specific data for %s", 479 IDMAP_DBNAME); 480 return (IDMAP_ERR_MEMORY); 481 } 482 483 if (tsd->cache_db == NULL) { 484 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 485 if (tsd->cache_db == NULL) { 486 idmapdlog(LOG_ERR, "Error opening database %s (%s)", 487 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 488 sqlite_freemem(errmsg); 489 return (IDMAP_ERR_DB); 490 } 491 492 tsd->cache_busy.name = IDMAP_CACHENAME; 493 tsd->cache_busy.delays = cache_delay_table; 494 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 495 sizeof (int); 496 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 497 &tsd->cache_busy); 498 } 499 *cache = tsd->cache_db; 500 return (IDMAP_SUCCESS); 501 } 502 503 /* 504 * Initialize cache and db 505 */ 506 int 507 init_dbs() 508 { 509 char *sql[2]; 510 int created, upgraded; 511 512 /* name-based mappings; probably OK to blow away in a pinch(?) */ 513 sql[0] = DB_INSTALL_SQL; 514 sql[1] = DB_UPGRADE_FROM_v1_SQL; 515 516 if (init_db_instance(IDMAP_DBNAME, DB_VERSION, DB_VERSION_SQL, sql, 517 FAIL_IF_CORRUPT, &created, &upgraded) < 0) 518 return (-1); 519 520 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 521 sql[0] = CACHE_INSTALL_SQL; 522 sql[1] = CACHE_UPGRADE_FROM_v1_SQL; 523 if (init_db_instance(IDMAP_CACHENAME, CACHE_VERSION, CACHE_VERSION_SQL, 524 sql, REMOVE_IF_CORRUPT, &created, &upgraded) < 0) 525 return (-1); 526 527 _idmapdstate.new_eph_db = (created || upgraded) ? 1 : 0; 528 529 return (0); 530 } 531 532 /* 533 * Finalize databases 534 */ 535 void 536 fini_dbs() 537 { 538 } 539 540 /* 541 * This table is a listing of status codes that will returned to the 542 * client when a SQL command fails with the corresponding error message. 543 */ 544 static msg_table_t sqlmsgtable[] = { 545 {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 546 "columns unixname, is_user, u2w_order are not unique"}, 547 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 548 "columns winname, windomain, is_user, is_wuser, w2u_order are not" 549 " unique"}, 550 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, "Conflicting w2u namerules"}, 551 {-1, NULL} 552 }; 553 554 /* 555 * idmapd's version of string2stat to map SQLite messages to 556 * status codes 557 */ 558 idmap_retcode 559 idmapd_string2stat(const char *msg) 560 { 561 int i; 562 for (i = 0; sqlmsgtable[i].msg; i++) { 563 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 564 return (sqlmsgtable[i].retcode); 565 } 566 return (IDMAP_ERR_OTHER); 567 } 568 569 /* 570 * Executes some SQL in a transaction. 571 * 572 * Returns 0 on success, -1 if it failed but the rollback succeeded, -2 573 * if the rollback failed. 574 */ 575 static 576 int 577 sql_exec_tran_no_cb(sqlite *db, char *sql, const char *dbname, 578 const char *while_doing) 579 { 580 char *errmsg = NULL; 581 int rc; 582 583 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg); 584 if (rc != SQLITE_OK) { 585 idmapdlog(LOG_ERR, "Begin transaction failed (%s) " 586 "while %s (%s)", errmsg, while_doing, dbname); 587 sqlite_freemem(errmsg); 588 return (-1); 589 } 590 591 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 592 if (rc != SQLITE_OK) { 593 idmapdlog(LOG_ERR, "Database error (%s) while %s (%s)", errmsg, 594 while_doing, dbname); 595 sqlite_freemem(errmsg); 596 errmsg = NULL; 597 goto rollback; 598 } 599 600 rc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, &errmsg); 601 if (rc == SQLITE_OK) { 602 sqlite_freemem(errmsg); 603 return (0); 604 } 605 606 idmapdlog(LOG_ERR, "Database commit error (%s) while s (%s)", 607 errmsg, while_doing, dbname); 608 sqlite_freemem(errmsg); 609 errmsg = NULL; 610 611 rollback: 612 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, &errmsg); 613 if (rc != SQLITE_OK) { 614 idmapdlog(LOG_ERR, "Rollback failed (%s) while %s (%s)", 615 errmsg, while_doing, dbname); 616 sqlite_freemem(errmsg); 617 return (-2); 618 } 619 sqlite_freemem(errmsg); 620 621 return (-1); 622 } 623 624 /* 625 * Execute the given SQL statment without using any callbacks 626 */ 627 idmap_retcode 628 sql_exec_no_cb(sqlite *db, char *sql) 629 { 630 char *errmsg = NULL; 631 int r; 632 idmap_retcode retcode; 633 634 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 635 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 636 637 if (r != SQLITE_OK) { 638 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 639 CHECK_NULL(errmsg)); 640 retcode = idmapd_string2stat(errmsg); 641 if (errmsg != NULL) 642 sqlite_freemem(errmsg); 643 return (retcode); 644 } 645 646 return (IDMAP_SUCCESS); 647 } 648 649 /* 650 * Generate expression that can be used in WHERE statements. 651 * Examples: 652 * <prefix> <col> <op> <value> <suffix> 653 * "" "unixuser" "=" "foo" "AND" 654 */ 655 idmap_retcode 656 gen_sql_expr_from_rule(idmap_namerule *rule, char **out) 657 { 658 char *s_windomain = NULL, *s_winname = NULL; 659 char *s_unixname = NULL; 660 char *lower_winname; 661 int retcode = IDMAP_SUCCESS; 662 663 if (out == NULL) 664 return (IDMAP_ERR_ARG); 665 666 667 if (!EMPTY_STRING(rule->windomain)) { 668 s_windomain = sqlite_mprintf("AND windomain = %Q ", 669 rule->windomain); 670 if (s_windomain == NULL) { 671 retcode = IDMAP_ERR_MEMORY; 672 goto out; 673 } 674 } 675 676 if (!EMPTY_STRING(rule->winname)) { 677 if ((lower_winname = tolower_u8(rule->winname)) == NULL) 678 lower_winname = rule->winname; 679 s_winname = sqlite_mprintf( 680 "AND winname = %Q AND is_wuser = %d ", 681 lower_winname, rule->is_wuser ? 1 : 0); 682 if (lower_winname != rule->winname) 683 free(lower_winname); 684 if (s_winname == NULL) { 685 retcode = IDMAP_ERR_MEMORY; 686 goto out; 687 } 688 } 689 690 if (!EMPTY_STRING(rule->unixname)) { 691 s_unixname = sqlite_mprintf( 692 "AND unixname = %Q AND is_user = %d ", 693 rule->unixname, rule->is_user ? 1 : 0); 694 if (s_unixname == NULL) { 695 retcode = IDMAP_ERR_MEMORY; 696 goto out; 697 } 698 } 699 700 *out = sqlite_mprintf("%s %s %s", 701 s_windomain ? s_windomain : "", 702 s_winname ? s_winname : "", 703 s_unixname ? s_unixname : ""); 704 705 if (*out == NULL) { 706 retcode = IDMAP_ERR_MEMORY; 707 idmapdlog(LOG_ERR, "Out of memory"); 708 goto out; 709 } 710 711 out: 712 if (s_windomain != NULL) 713 sqlite_freemem(s_windomain); 714 if (s_winname != NULL) 715 sqlite_freemem(s_winname); 716 if (s_unixname != NULL) 717 sqlite_freemem(s_unixname); 718 719 return (retcode); 720 } 721 722 723 724 /* 725 * Generate and execute SQL statement for LIST RPC calls 726 */ 727 idmap_retcode 728 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 729 list_svc_cb cb, void *result) 730 { 731 list_cb_data_t cb_data; 732 char *errmsg = NULL; 733 int r; 734 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 735 736 (void) memset(&cb_data, 0, sizeof (cb_data)); 737 cb_data.result = result; 738 cb_data.limit = limit; 739 740 741 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 742 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 743 switch (r) { 744 case SQLITE_OK: 745 retcode = IDMAP_SUCCESS; 746 break; 747 748 default: 749 retcode = IDMAP_ERR_INTERNAL; 750 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 751 CHECK_NULL(errmsg)); 752 break; 753 } 754 if (errmsg != NULL) 755 sqlite_freemem(errmsg); 756 return (retcode); 757 } 758 759 /* 760 * This routine is called by callbacks that process the results of 761 * LIST RPC calls to validate data and to allocate memory for 762 * the result array. 763 */ 764 idmap_retcode 765 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 766 int ncol, uchar_t **list, size_t valsize) 767 { 768 size_t nsize; 769 void *tmplist; 770 771 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 772 return (IDMAP_NEXT); 773 774 if (argc < ncol || argv == NULL) { 775 idmapdlog(LOG_ERR, "Invalid data"); 776 return (IDMAP_ERR_INTERNAL); 777 } 778 779 /* alloc in bulk to reduce number of reallocs */ 780 if (cb_data->next >= cb_data->len) { 781 nsize = (cb_data->len + SIZE_INCR) * valsize; 782 tmplist = realloc(*list, nsize); 783 if (tmplist == NULL) { 784 idmapdlog(LOG_ERR, "Out of memory"); 785 return (IDMAP_ERR_MEMORY); 786 } 787 *list = tmplist; 788 (void) memset(*list + (cb_data->len * valsize), 0, 789 SIZE_INCR * valsize); 790 cb_data->len += SIZE_INCR; 791 } 792 return (IDMAP_SUCCESS); 793 } 794 795 static 796 idmap_retcode 797 get_namerule_order(char *winname, char *windomain, char *unixname, 798 int direction, int is_diagonal, int *w2u_order, int *u2w_order) 799 { 800 *w2u_order = 0; 801 *u2w_order = 0; 802 803 /* 804 * Windows to UNIX lookup order: 805 * 1. winname@domain (or winname) to "" 806 * 2. winname@domain (or winname) to unixname 807 * 3. winname@* to "" 808 * 4. winname@* to unixname 809 * 5. *@domain (or *) to * 810 * 6. *@domain (or *) to "" 811 * 7. *@domain (or *) to unixname 812 * 8. *@* to * 813 * 9. *@* to "" 814 * 10. *@* to unixname 815 * 816 * winname is a special case of winname@domain when domain is the 817 * default domain. Similarly * is a special case of *@domain when 818 * domain is the default domain. 819 * 820 * Note that "" has priority over specific names because "" inhibits 821 * mappings and traditionally deny rules always had higher priority. 822 */ 823 if (direction != IDMAP_DIRECTION_U2W) { 824 /* bi-directional or from windows to unix */ 825 if (winname == NULL) 826 return (IDMAP_ERR_W2U_NAMERULE); 827 else if (unixname == NULL) 828 return (IDMAP_ERR_W2U_NAMERULE); 829 else if (EMPTY_NAME(winname)) 830 return (IDMAP_ERR_W2U_NAMERULE); 831 else if (*winname == '*' && windomain && *windomain == '*') { 832 if (*unixname == '*') 833 *w2u_order = 8; 834 else if (EMPTY_NAME(unixname)) 835 *w2u_order = 9; 836 else /* unixname == name */ 837 *w2u_order = 10; 838 } else if (*winname == '*') { 839 if (*unixname == '*') 840 *w2u_order = 5; 841 else if (EMPTY_NAME(unixname)) 842 *w2u_order = 6; 843 else /* name */ 844 *w2u_order = 7; 845 } else if (windomain != NULL && *windomain == '*') { 846 /* winname == name */ 847 if (*unixname == '*') 848 return (IDMAP_ERR_W2U_NAMERULE); 849 else if (EMPTY_NAME(unixname)) 850 *w2u_order = 3; 851 else /* name */ 852 *w2u_order = 4; 853 } else { 854 /* winname == name && windomain == null or name */ 855 if (*unixname == '*') 856 return (IDMAP_ERR_W2U_NAMERULE); 857 else if (EMPTY_NAME(unixname)) 858 *w2u_order = 1; 859 else /* name */ 860 *w2u_order = 2; 861 } 862 863 } 864 865 /* 866 * 1. unixname to "", non-diagonal 867 * 2. unixname to winname@domain (or winname), non-diagonal 868 * 3. unixname to "", diagonal 869 * 4. unixname to winname@domain (or winname), diagonal 870 * 5. * to *@domain (or *), non-diagonal 871 * 5. * to *@domain (or *), diagonal 872 * 7. * to "" 873 * 8. * to winname@domain (or winname) 874 * 9. * to "", non-diagonal 875 * 10. * to winname@domain (or winname), diagonal 876 */ 877 if (direction != IDMAP_DIRECTION_W2U) { 878 int diagonal = is_diagonal ? 1 : 0; 879 880 /* bi-directional or from unix to windows */ 881 if (unixname == NULL || EMPTY_NAME(unixname)) 882 return (IDMAP_ERR_U2W_NAMERULE); 883 else if (winname == NULL) 884 return (IDMAP_ERR_U2W_NAMERULE); 885 else if (windomain != NULL && *windomain == '*') 886 return (IDMAP_ERR_U2W_NAMERULE); 887 else if (*unixname == '*') { 888 if (*winname == '*') 889 *u2w_order = 5 + diagonal; 890 else if (EMPTY_NAME(winname)) 891 *u2w_order = 7 + 2 * diagonal; 892 else 893 *u2w_order = 8 + 2 * diagonal; 894 } else { 895 if (*winname == '*') 896 return (IDMAP_ERR_U2W_NAMERULE); 897 else if (EMPTY_NAME(winname)) 898 *u2w_order = 1 + 2 * diagonal; 899 else 900 *u2w_order = 2 + 2 * diagonal; 901 } 902 } 903 return (IDMAP_SUCCESS); 904 } 905 906 /* 907 * Generate and execute SQL statement to add name-based mapping rule 908 */ 909 idmap_retcode 910 add_namerule(sqlite *db, idmap_namerule *rule) 911 { 912 char *sql = NULL; 913 idmap_stat retcode; 914 char *dom = NULL; 915 int w2u_order, u2w_order; 916 char w2ubuf[11], u2wbuf[11]; 917 918 retcode = get_namerule_order(rule->winname, rule->windomain, 919 rule->unixname, rule->direction, 920 rule->is_user == rule->is_wuser ? 0 : 1, &w2u_order, &u2w_order); 921 if (retcode != IDMAP_SUCCESS) 922 goto out; 923 924 if (w2u_order) 925 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 926 if (u2w_order) 927 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 928 929 /* 930 * For the triggers on namerules table to work correctly: 931 * 1) Use NULL instead of 0 for w2u_order and u2w_order 932 * 2) Use "" instead of NULL for "no domain" 933 */ 934 935 if (rule->windomain != NULL) 936 dom = rule->windomain; 937 else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL, NULL) 938 == IDMAP_SUCCESS) { 939 /* well-known SIDs don't need domain */ 940 dom = ""; 941 } 942 943 RDLOCK_CONFIG(); 944 if (dom == NULL) { 945 if (_idmapdstate.cfg->pgcfg.default_domain) 946 dom = _idmapdstate.cfg->pgcfg.default_domain; 947 else 948 dom = ""; 949 } 950 sql = sqlite_mprintf("INSERT into namerules " 951 "(is_user, is_wuser, windomain, winname_display, is_nt4, " 952 "unixname, w2u_order, u2w_order) " 953 "VALUES(%d, %d, %Q, %Q, %d, %Q, %q, %q);", 954 rule->is_user ? 1 : 0, rule->is_wuser ? 1 : 0, dom, 955 rule->winname, rule->is_nt4 ? 1 : 0, rule->unixname, 956 w2u_order ? w2ubuf : NULL, u2w_order ? u2wbuf : NULL); 957 UNLOCK_CONFIG(); 958 959 if (sql == NULL) { 960 retcode = IDMAP_ERR_INTERNAL; 961 idmapdlog(LOG_ERR, "Out of memory"); 962 goto out; 963 } 964 965 retcode = sql_exec_no_cb(db, sql); 966 967 if (retcode == IDMAP_ERR_OTHER) 968 retcode = IDMAP_ERR_CFG; 969 970 out: 971 if (sql != NULL) 972 sqlite_freemem(sql); 973 return (retcode); 974 } 975 976 /* 977 * Flush name-based mapping rules 978 */ 979 idmap_retcode 980 flush_namerules(sqlite *db) 981 { 982 idmap_stat retcode; 983 984 retcode = sql_exec_no_cb(db, "DELETE FROM namerules;"); 985 986 return (retcode); 987 } 988 989 /* 990 * Generate and execute SQL statement to remove a name-based mapping rule 991 */ 992 idmap_retcode 993 rm_namerule(sqlite *db, idmap_namerule *rule) 994 { 995 char *sql = NULL; 996 idmap_stat retcode; 997 char buf[80]; 998 char *expr = NULL; 999 1000 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 1001 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 1002 return (IDMAP_SUCCESS); 1003 1004 buf[0] = 0; 1005 1006 if (rule->direction == IDMAP_DIRECTION_BI) 1007 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 1008 " AND u2w_order > 0"); 1009 else if (rule->direction == IDMAP_DIRECTION_W2U) 1010 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 1011 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 1012 else if (rule->direction == IDMAP_DIRECTION_U2W) 1013 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 1014 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 1015 1016 retcode = gen_sql_expr_from_rule(rule, &expr); 1017 if (retcode != IDMAP_SUCCESS) 1018 goto out; 1019 1020 sql = sqlite_mprintf("DELETE FROM namerules WHERE 1 %s %s;", expr, 1021 buf); 1022 1023 if (sql == NULL) { 1024 retcode = IDMAP_ERR_INTERNAL; 1025 idmapdlog(LOG_ERR, "Out of memory"); 1026 goto out; 1027 } 1028 1029 1030 retcode = sql_exec_no_cb(db, sql); 1031 1032 out: 1033 if (expr != NULL) 1034 sqlite_freemem(expr); 1035 if (sql != NULL) 1036 sqlite_freemem(sql); 1037 return (retcode); 1038 } 1039 1040 /* 1041 * Compile the given SQL query and step just once. 1042 * 1043 * Input: 1044 * db - db handle 1045 * sql - SQL statement 1046 * 1047 * Output: 1048 * vm - virtual SQL machine 1049 * ncol - number of columns in the result 1050 * values - column values 1051 * 1052 * Return values: 1053 * IDMAP_SUCCESS 1054 * IDMAP_ERR_NOTFOUND 1055 * IDMAP_ERR_INTERNAL 1056 */ 1057 1058 static 1059 idmap_retcode 1060 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 1061 int reqcol, const char ***values) 1062 { 1063 char *errmsg = NULL; 1064 int r; 1065 1066 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 1067 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 1068 CHECK_NULL(errmsg)); 1069 sqlite_freemem(errmsg); 1070 return (IDMAP_ERR_INTERNAL); 1071 } 1072 1073 r = sqlite_step(*vm, ncol, values, NULL); 1074 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 1075 1076 if (r == SQLITE_ROW) { 1077 if (ncol != NULL && *ncol < reqcol) { 1078 (void) sqlite_finalize(*vm, NULL); 1079 *vm = NULL; 1080 return (IDMAP_ERR_INTERNAL); 1081 } 1082 /* Caller will call finalize after using the results */ 1083 return (IDMAP_SUCCESS); 1084 } else if (r == SQLITE_DONE) { 1085 (void) sqlite_finalize(*vm, NULL); 1086 *vm = NULL; 1087 return (IDMAP_ERR_NOTFOUND); 1088 } 1089 1090 (void) sqlite_finalize(*vm, &errmsg); 1091 *vm = NULL; 1092 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 1093 CHECK_NULL(errmsg)); 1094 sqlite_freemem(errmsg); 1095 return (IDMAP_ERR_INTERNAL); 1096 } 1097 1098 /* 1099 * Table for well-known SIDs. 1100 * 1101 * Background: 1102 * 1103 * Some of the well-known principals are stored under: 1104 * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 1105 * They belong to objectClass "foreignSecurityPrincipal". They don't have 1106 * "samAccountName" nor "userPrincipalName" attributes. Their names are 1107 * available in "cn" and "name" attributes. Some of these principals have a 1108 * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 1109 * these duplicate entries have the stringified SID in the "name" and "cn" 1110 * attributes instead of the actual name. 1111 * 1112 * Those of the form S-1-5-32-X are Builtin groups and are stored in the 1113 * cn=builtin container (except, Power Users which is not stored in AD) 1114 * 1115 * These principals are and will remain constant. Therefore doing AD lookups 1116 * provides no benefit. Also, using hard-coded table (and thus avoiding AD 1117 * lookup) improves performance and avoids additional complexity in the 1118 * adutils.c code. Moreover these SIDs can be used when no Active Directory 1119 * is available (such as the CIFS server's "workgroup" mode). 1120 * 1121 * Notes: 1122 * 1. Currently we don't support localization of well-known SID names, 1123 * unlike Windows. 1124 * 1125 * 2. Other well-known SIDs i.e. S-1-5-<domain>-<w-k RID> are not stored 1126 * here. AD does have normal user/group objects for these objects and 1127 * can be looked up using the existing AD lookup code. 1128 */ 1129 static wksids_table_t wksids[] = { 1130 {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 1131 {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 1132 {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 1133 {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 1134 {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 1135 {"S-1-3", 4, "Owner Rights", 0, SENTINEL_PID, -1}, 1136 {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 1137 {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 1138 {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 1139 {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 1140 {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 1141 {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 1142 {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 1143 {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 1144 {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 1145 {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 1146 {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 1147 {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 1148 {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 1149 {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 1150 {"S-1-5", 17, "IUSR", 0, SENTINEL_PID, -1}, 1151 {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 1152 {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 1153 {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 1154 {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 1155 {"S-1-5-32", 544, "Administrators", 0, SENTINEL_PID, -1}, 1156 {"S-1-5-32", 545, "Users", 0, SENTINEL_PID, -1}, 1157 {"S-1-5-32", 546, "Guests", 0, SENTINEL_PID, -1}, 1158 {"S-1-5-32", 547, "Power Users", 0, SENTINEL_PID, -1}, 1159 {"S-1-5-32", 548, "Account Operators", 0, SENTINEL_PID, -1}, 1160 {"S-1-5-32", 549, "Server Operators", 0, SENTINEL_PID, -1}, 1161 {"S-1-5-32", 550, "Print Operators", 0, SENTINEL_PID, -1}, 1162 {"S-1-5-32", 551, "Backup Operators", 0, SENTINEL_PID, -1}, 1163 {"S-1-5-32", 552, "Replicator", 0, SENTINEL_PID, -1}, 1164 {"S-1-5-32", 554, "Pre-Windows 2000 Compatible Access", 0, 1165 SENTINEL_PID, -1}, 1166 {"S-1-5-32", 555, "Remote Desktop Users", 0, SENTINEL_PID, -1}, 1167 {"S-1-5-32", 556, "Network Configuration Operators", 0, 1168 SENTINEL_PID, -1}, 1169 {"S-1-5-32", 557, "Incoming Forest Trust Builders", 0, 1170 SENTINEL_PID, -1}, 1171 {"S-1-5-32", 558, "Performance Monitor Users", 0, SENTINEL_PID, -1}, 1172 {"S-1-5-32", 559, "Performance Log Users", 0, SENTINEL_PID, -1}, 1173 {"S-1-5-32", 560, "Windows Authorization Access Group", 0, 1174 SENTINEL_PID, -1}, 1175 {"S-1-5-32", 561, "Terminal Server License Servers", 0, 1176 SENTINEL_PID, -1}, 1177 {"S-1-5-32", 561, "Distributed COM Users", 0, SENTINEL_PID, -1}, 1178 {"S-1-5-32", 568, "IIS_IUSRS", 0, SENTINEL_PID, -1}, 1179 {"S-1-5-32", 569, "Cryptograhic Operators", 0, SENTINEL_PID, -1}, 1180 {"S-1-5-32", 573, "Event Log Readers", 0, SENTINEL_PID, -1}, 1181 {"S-1-5-32", 574, "Certificate Service DCOM Access", 0, 1182 SENTINEL_PID, -1}, 1183 {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 1184 {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 1185 {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 1186 {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 1187 }; 1188 1189 static 1190 idmap_retcode 1191 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) 1192 { 1193 int i; 1194 for (i = 0; wksids[i].sidprefix != NULL; i++) { 1195 if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 1196 (strcasecmp(wksids[i].sidprefix, 1197 req->id1.idmap_id_u.sid.prefix) == 0)) { 1198 1199 if (wksids[i].pid == SENTINEL_PID) 1200 /* Not mapped, break */ 1201 break; 1202 else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 1203 continue; 1204 1205 switch (req->id2.idtype) { 1206 case IDMAP_UID: 1207 if (wksids[i].is_user == 0) 1208 continue; 1209 res->id.idmap_id_u.uid = wksids[i].pid; 1210 res->direction = wksids[i].direction; 1211 return (IDMAP_SUCCESS); 1212 case IDMAP_GID: 1213 if (wksids[i].is_user == 1) 1214 continue; 1215 res->id.idmap_id_u.gid = wksids[i].pid; 1216 res->direction = wksids[i].direction; 1217 return (IDMAP_SUCCESS); 1218 case IDMAP_POSIXID: 1219 res->id.idmap_id_u.uid = wksids[i].pid; 1220 res->id.idtype = (!wksids[i].is_user) ? 1221 IDMAP_GID : IDMAP_UID; 1222 res->direction = wksids[i].direction; 1223 return (IDMAP_SUCCESS); 1224 default: 1225 return (IDMAP_ERR_NOTSUPPORTED); 1226 } 1227 } 1228 } 1229 return (IDMAP_ERR_NOTFOUND); 1230 } 1231 1232 1233 static 1234 idmap_retcode 1235 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) 1236 { 1237 int i; 1238 if (!IS_REQUEST_SID(*req, 2)) 1239 return (IDMAP_ERR_NOTSUPPORTED); 1240 for (i = 0; wksids[i].sidprefix != NULL; i++) { 1241 if (wksids[i].pid == req->id1.idmap_id_u.uid && 1242 wksids[i].is_user == is_user && 1243 wksids[i].direction != IDMAP_DIRECTION_W2U) { 1244 res->id.idmap_id_u.sid.rid = wksids[i].rid; 1245 res->id.idmap_id_u.sid.prefix = 1246 strdup(wksids[i].sidprefix); 1247 if (res->id.idmap_id_u.sid.prefix == NULL) { 1248 idmapdlog(LOG_ERR, "Out of memory"); 1249 return (IDMAP_ERR_MEMORY); 1250 } 1251 res->direction = wksids[i].direction; 1252 return (IDMAP_SUCCESS); 1253 } 1254 } 1255 return (IDMAP_ERR_NOTFOUND); 1256 } 1257 1258 static 1259 idmap_retcode 1260 lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 1261 int *type) 1262 { 1263 int i; 1264 for (i = 0; wksids[i].sidprefix != NULL; i++) { 1265 if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 1266 wksids[i].rid == rid) { 1267 if ((*name = strdup(wksids[i].winname)) == NULL) { 1268 idmapdlog(LOG_ERR, "Out of memory"); 1269 return (IDMAP_ERR_MEMORY); 1270 } 1271 *type = (wksids[i].is_user)? 1272 _IDMAP_T_USER:_IDMAP_T_GROUP; 1273 return (IDMAP_SUCCESS); 1274 } 1275 } 1276 return (IDMAP_ERR_NOTFOUND); 1277 } 1278 1279 static 1280 idmap_retcode 1281 lookup_wksids_name2sid(const char *name, char **canonname, char **sidprefix, 1282 idmap_rid_t *rid, int *type) 1283 { 1284 int i; 1285 1286 for (i = 0; wksids[i].sidprefix != NULL; i++) { 1287 if (strcasecmp(wksids[i].winname, name) == 0) { 1288 if (sidprefix != NULL && (*sidprefix = 1289 strdup(wksids[i].sidprefix)) == NULL) { 1290 idmapdlog(LOG_ERR, "Out of memory"); 1291 return (IDMAP_ERR_MEMORY); 1292 } 1293 if (canonname != NULL && 1294 (*canonname = strdup(wksids[i].winname)) == NULL) { 1295 idmapdlog(LOG_ERR, "Out of memory"); 1296 return (IDMAP_ERR_MEMORY); 1297 } 1298 if (type != NULL) 1299 *type = (wksids[i].is_user)? 1300 _IDMAP_T_USER:_IDMAP_T_GROUP; 1301 if (rid != NULL) 1302 *rid = wksids[i].rid; 1303 return (IDMAP_SUCCESS); 1304 } 1305 } 1306 return (IDMAP_ERR_NOTFOUND); 1307 } 1308 1309 static 1310 idmap_retcode 1311 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) 1312 { 1313 char *end; 1314 char *sql = NULL; 1315 const char **values; 1316 sqlite_vm *vm = NULL; 1317 int ncol, is_user; 1318 uid_t pid; 1319 time_t curtime, exp; 1320 idmap_retcode retcode; 1321 char *is_user_string; 1322 1323 /* Current time */ 1324 errno = 0; 1325 if ((curtime = time(NULL)) == (time_t)-1) { 1326 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 1327 strerror(errno)); 1328 retcode = IDMAP_ERR_INTERNAL; 1329 goto out; 1330 } 1331 1332 switch (req->id2.idtype) { 1333 case IDMAP_UID: 1334 is_user_string = "1"; 1335 break; 1336 case IDMAP_GID: 1337 is_user_string = "0"; 1338 break; 1339 case IDMAP_POSIXID: 1340 /* the non-diagonal mapping */ 1341 is_user_string = "is_wuser"; 1342 break; 1343 default: 1344 retcode = IDMAP_ERR_NOTSUPPORTED; 1345 goto out; 1346 } 1347 1348 /* SQL to lookup the cache */ 1349 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 1350 "FROM idmap_cache WHERE is_user = %s AND " 1351 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 1352 "(pid >= 2147483648 OR " 1353 "(expiration = 0 OR expiration ISNULL OR " 1354 "expiration > %d));", 1355 is_user_string, 1356 req->id1.idmap_id_u.sid.prefix, 1357 req->id1.idmap_id_u.sid.rid, 1358 curtime); 1359 if (sql == NULL) { 1360 idmapdlog(LOG_ERR, "Out of memory"); 1361 retcode = IDMAP_ERR_MEMORY; 1362 goto out; 1363 } 1364 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 1365 sqlite_freemem(sql); 1366 1367 if (retcode == IDMAP_ERR_NOTFOUND) { 1368 goto out; 1369 } else if (retcode == IDMAP_SUCCESS) { 1370 /* sanity checks */ 1371 if (values[0] == NULL || values[1] == NULL) { 1372 retcode = IDMAP_ERR_CACHE; 1373 goto out; 1374 } 1375 1376 pid = strtoul(values[0], &end, 10); 1377 is_user = strncmp(values[1], "0", 2)?1:0; 1378 1379 if (is_user) { 1380 res->id.idtype = IDMAP_UID; 1381 res->id.idmap_id_u.uid = pid; 1382 } else { 1383 res->id.idtype = IDMAP_GID; 1384 res->id.idmap_id_u.gid = pid; 1385 } 1386 1387 /* 1388 * We may have an expired ephemeral mapping. Consider 1389 * the expired entry as valid if we are not going to 1390 * perform name-based mapping. But do not renew the 1391 * expiration. 1392 * If we will be doing name-based mapping then store the 1393 * ephemeral pid in the result so that we can use it 1394 * if we end up doing dynamic mapping again. 1395 */ 1396 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 1397 !AVOID_NAMESERVICE(req) && 1398 IS_EPHEMERAL(pid) && values[2] != NULL) { 1399 exp = strtoll(values[2], &end, 10); 1400 if (exp && exp <= curtime) { 1401 /* Store the ephemeral pid */ 1402 res->direction = IDMAP_DIRECTION_BI; 1403 req->direction |= is_user 1404 ? _IDMAP_F_EXP_EPH_UID 1405 : _IDMAP_F_EXP_EPH_GID; 1406 retcode = IDMAP_ERR_NOTFOUND; 1407 } 1408 } 1409 } 1410 1411 out: 1412 if (retcode == IDMAP_SUCCESS) { 1413 if (values[4] != NULL) 1414 res->direction = 1415 (strtol(values[4], &end, 10) == 0)? 1416 IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 1417 else 1418 res->direction = IDMAP_DIRECTION_W2U; 1419 1420 if (values[3] != NULL) { 1421 req->id2name = strdup(values[3]); 1422 if (req->id2name == NULL) { 1423 idmapdlog(LOG_ERR, "Out of memory"); 1424 retcode = IDMAP_ERR_MEMORY; 1425 } 1426 } 1427 } 1428 if (vm != NULL) 1429 (void) sqlite_finalize(vm, NULL); 1430 return (retcode); 1431 } 1432 1433 static 1434 idmap_retcode 1435 lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 1436 char **name, char **domain, int *type) 1437 { 1438 char *end; 1439 char *sql = NULL; 1440 const char **values; 1441 sqlite_vm *vm = NULL; 1442 int ncol; 1443 time_t curtime; 1444 idmap_retcode retcode = IDMAP_SUCCESS; 1445 1446 /* Get current time */ 1447 errno = 0; 1448 if ((curtime = time(NULL)) == (time_t)-1) { 1449 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 1450 strerror(errno)); 1451 retcode = IDMAP_ERR_INTERNAL; 1452 goto out; 1453 } 1454 1455 /* SQL to lookup the cache */ 1456 sql = sqlite_mprintf("SELECT canon_name, domain, type " 1457 "FROM name_cache WHERE " 1458 "sidprefix = %Q AND rid = %u AND " 1459 "(expiration = 0 OR expiration ISNULL OR " 1460 "expiration > %d);", 1461 sidprefix, rid, curtime); 1462 if (sql == NULL) { 1463 idmapdlog(LOG_ERR, "Out of memory"); 1464 retcode = IDMAP_ERR_MEMORY; 1465 goto out; 1466 } 1467 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 1468 sqlite_freemem(sql); 1469 1470 if (retcode == IDMAP_SUCCESS) { 1471 if (type != NULL) { 1472 if (values[2] == NULL) { 1473 retcode = IDMAP_ERR_CACHE; 1474 goto out; 1475 } 1476 *type = strtol(values[2], &end, 10); 1477 } 1478 1479 if (name != NULL && values[0] != NULL) { 1480 if ((*name = strdup(values[0])) == NULL) { 1481 idmapdlog(LOG_ERR, "Out of memory"); 1482 retcode = IDMAP_ERR_MEMORY; 1483 goto out; 1484 } 1485 } 1486 1487 if (domain != NULL && values[1] != NULL) { 1488 if ((*domain = strdup(values[1])) == NULL) { 1489 if (name != NULL && *name) { 1490 free(*name); 1491 *name = NULL; 1492 } 1493 idmapdlog(LOG_ERR, "Out of memory"); 1494 retcode = IDMAP_ERR_MEMORY; 1495 goto out; 1496 } 1497 } 1498 } 1499 1500 out: 1501 if (vm != NULL) 1502 (void) sqlite_finalize(vm, NULL); 1503 return (retcode); 1504 } 1505 1506 /* 1507 * Lookup sid to name locally 1508 */ 1509 static 1510 idmap_retcode 1511 lookup_local_sid2name(sqlite *cache, idmap_mapping *req) 1512 { 1513 int type = -1; 1514 idmap_retcode retcode; 1515 char *sidprefix; 1516 idmap_rid_t rid; 1517 char *name = NULL, *domain = NULL; 1518 1519 sidprefix = req->id1.idmap_id_u.sid.prefix; 1520 rid = req->id1.idmap_id_u.sid.rid; 1521 1522 /* Lookup sids to name in well-known sids table */ 1523 retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 1524 if (retcode != IDMAP_ERR_NOTFOUND) 1525 goto out; 1526 1527 /* Lookup sid to name in cache */ 1528 retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 1529 &domain, &type); 1530 if (retcode != IDMAP_SUCCESS) 1531 goto out; 1532 1533 out: 1534 if (retcode == IDMAP_SUCCESS) { 1535 req->id1.idtype = type == _IDMAP_T_USER 1536 ? IDMAP_USID : IDMAP_GSID; 1537 1538 /* update state in 'req' */ 1539 if (name != NULL) 1540 req->id1name = name; 1541 if (domain != NULL) 1542 req->id1domain = domain; 1543 } else { 1544 if (name != NULL) 1545 free(name); 1546 if (domain != NULL) 1547 free(domain); 1548 } 1549 return (retcode); 1550 } 1551 1552 idmap_retcode 1553 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 1554 idmap_ids_res *result) 1555 { 1556 idmap_retcode retcode; 1557 int ret, i; 1558 int retries = 0; 1559 idmap_mapping *req; 1560 idmap_id_res *res; 1561 1562 if (state->ad_nqueries == 0) 1563 return (IDMAP_SUCCESS); 1564 1565 retry: 1566 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 1567 &state->ad_lookup); 1568 if (ret != 0) { 1569 degrade_svc(); 1570 idmapdlog(LOG_ERR, 1571 "Failed to create sid2name batch for AD lookup"); 1572 return (IDMAP_ERR_INTERNAL); 1573 } 1574 1575 restore_svc(); 1576 1577 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 1578 req = &batch->idmap_mapping_batch_val[i]; 1579 res = &result->ids.ids_val[i]; 1580 1581 if (IS_REQUEST_SID(*req, 1) && 1582 req->direction & _IDMAP_F_S2N_AD) { 1583 if (retries == 0) 1584 res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 1585 else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 1586 continue; 1587 retcode = idmap_sid2name_batch_add1( 1588 state->ad_lookup, req->id1.idmap_id_u.sid.prefix, 1589 &req->id1.idmap_id_u.sid.rid, &req->id1name, 1590 &req->id1domain, (int *)&res->id.idtype, 1591 &res->retcode); 1592 1593 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1594 break; 1595 if (retcode != IDMAP_SUCCESS) 1596 goto out; 1597 } 1598 } 1599 1600 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1601 idmap_lookup_release_batch(&state->ad_lookup); 1602 else 1603 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 1604 1605 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 1606 req = &batch->idmap_mapping_batch_val[i]; 1607 res = &result->ids.ids_val[i]; 1608 if (res->retcode != IDMAP_SUCCESS) 1609 continue; 1610 1611 if (!(IS_REQUEST_SID(*req, 1))) 1612 continue; 1613 if (!(req->direction & _IDMAP_F_S2N_AD)) 1614 continue; 1615 /* 1616 * Map from type values known to adutils to type values 1617 * understood everywhere else in idmapd/libidmap/idmap. 1618 */ 1619 if (res->id.idtype == _IDMAP_T_USER) { 1620 req->id1.idtype = IDMAP_USID; 1621 res->id.idtype = IDMAP_UID; 1622 } else if (res->id.idtype == _IDMAP_T_GROUP) { 1623 req->id1.idtype = IDMAP_GSID; 1624 res->id.idtype = IDMAP_GID; 1625 } else { 1626 res->retcode = IDMAP_ERR_SID; 1627 } 1628 1629 if (res->retcode == IDMAP_SUCCESS && 1630 req->id2.idtype == IDMAP_POSIXID) 1631 req->id2.idtype = res->id.idtype; 1632 } 1633 1634 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 1635 goto retry; 1636 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1637 degrade_svc(); 1638 1639 return (retcode); 1640 1641 out: 1642 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 1643 idmap_lookup_release_batch(&state->ad_lookup); 1644 return (retcode); 1645 } 1646 1647 /* 1648 * Convention when processing win2unix requests: 1649 * 1650 * Windows identity: 1651 * req->id1name = 1652 * winname if given otherwise winname found will be placed 1653 * here. 1654 * req->id1domain = 1655 * windomain if given otherwise windomain found will be 1656 * placed here. 1657 * req->id1.idtype = 1658 * Either IDMAP_SID/USID/GSID. If this is IDMAP_SID then it'll 1659 * be set to IDMAP_USID/GSID depending upon whether the 1660 * given SID is user or group respectively. The user/group-ness 1661 * is determined either when looking up well-known SIDs table OR 1662 * if the SID is found in namecache OR by ad_lookup() OR by 1663 * ad_lookup_batch(). 1664 * req->id1..sid.[prefix, rid] = 1665 * SID if given otherwise SID found will be placed here. 1666 * 1667 * Unix identity: 1668 * req->id2name = 1669 * unixname found will be placed here. 1670 * req->id2domain = 1671 * NOT USED 1672 * res->id.idtype = 1673 * Target type initialized from req->id2.idtype. If 1674 * it is IDMAP_POSIXID then actual type (IDMAP_UID/GID) found 1675 * will be placed here. 1676 * res->id..[uid or gid] = 1677 * UID/GID found will be placed here. 1678 * 1679 * Others: 1680 * res->retcode = 1681 * Return status for this request will be placed here. 1682 * res->direction = 1683 * Direction found will be placed here. Direction 1684 * meaning whether the resultant mapping is valid 1685 * only from win2unix or bi-directional. 1686 * req->direction = 1687 * INTERNAL USE. Used by idmapd to set various 1688 * flags (_IDMAP_F_xxxx) to aid in processing 1689 * of the request. 1690 * req->id2.idtype = 1691 * INTERNAL USE. Initially this is the requested target 1692 * type and is used to initialize res->id.idtype. 1693 * ad_lookup_batch() uses this field temporarily to store 1694 * sid_type obtained by the batched AD lookups and after 1695 * use resets it to IDMAP_NONE to prevent xdr from 1696 * mis-interpreting the contents of req->id2. 1697 * req->id2..[uid or gid or sid] = 1698 * NOT USED 1699 */ 1700 1701 /* 1702 * This function does the following: 1703 * 1. Lookup well-known SIDs table. 1704 * 2. Check if the given SID is a local-SID and if so extract UID/GID from it. 1705 * 3. Lookup cache. 1706 * 4. Check if the client does not want new mapping to be allocated 1707 * in which case this pass is the final pass. 1708 * 5. Set AD lookup flag if it determines that the next stage needs 1709 * to do AD lookup. 1710 */ 1711 idmap_retcode 1712 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 1713 idmap_id_res *res) 1714 { 1715 idmap_retcode retcode; 1716 1717 /* 1718 * The req->direction field is used to maintain state of the 1719 * sid2pid request. 1720 */ 1721 req->direction = _IDMAP_F_DONE; 1722 1723 if (EMPTY_STRING(req->id1.idmap_id_u.sid.prefix)) { 1724 retcode = IDMAP_ERR_SID; 1725 goto out; 1726 } 1727 res->id.idtype = req->id2.idtype; 1728 res->id.idmap_id_u.uid = UID_NOBODY; 1729 1730 /* Lookup well-known sid to pid mapping */ 1731 retcode = lookup_wksids_sid2pid(req, res); 1732 if (retcode != IDMAP_ERR_NOTFOUND) 1733 goto out; 1734 1735 /* Lookup sid to pid in cache */ 1736 retcode = lookup_cache_sid2pid(cache, req, res); 1737 if (retcode != IDMAP_ERR_NOTFOUND) 1738 goto out; 1739 1740 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 1741 res->id.idmap_id_u.uid = SENTINEL_PID; 1742 goto out; 1743 } 1744 1745 /* 1746 * Failed to find non-expired entry in cache. Tell the caller 1747 * that we are not done yet. 1748 */ 1749 state->sid2pid_done = FALSE; 1750 1751 /* 1752 * Our next step is name-based mapping. To lookup name-based 1753 * mapping rules, we need the windows name and domain-name 1754 * associated with the SID. 1755 */ 1756 1757 /* 1758 * Check if we already have the name (i.e name2pid lookups) 1759 */ 1760 if (!EMPTY_STRING(req->id1name) && 1761 !EMPTY_STRING(req->id1domain)) { 1762 retcode = IDMAP_SUCCESS; 1763 req->direction |= _IDMAP_F_S2N_CACHE; 1764 goto out; 1765 } 1766 1767 /* Lookup sid to winname@domain locally first */ 1768 retcode = lookup_local_sid2name(cache, req); 1769 if (retcode == IDMAP_SUCCESS) { 1770 req->direction |= _IDMAP_F_S2N_CACHE; 1771 } else if (retcode == IDMAP_ERR_NOTFOUND) { 1772 /* Batch sid to name AD lookup request */ 1773 retcode = IDMAP_SUCCESS; 1774 req->direction |= _IDMAP_F_S2N_AD; 1775 state->ad_nqueries++; 1776 goto out; 1777 } 1778 1779 1780 out: 1781 res->retcode = idmap_stat4prot(retcode); 1782 return (retcode); 1783 } 1784 1785 /* 1786 * Generate SID using the following convention 1787 * <machine-sid-prefix>-<1000 + uid> 1788 * <machine-sid-prefix>-<2^31 + gid> 1789 */ 1790 static 1791 idmap_retcode 1792 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) 1793 { 1794 if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 1795 /* Skip 1000 UIDs */ 1796 if (is_user && req->id1.idmap_id_u.uid > 1797 (INT32_MAX - LOCALRID_MIN)) 1798 return (IDMAP_ERR_NOMAPPING); 1799 1800 RDLOCK_CONFIG(); 1801 res->id.idmap_id_u.sid.prefix = 1802 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 1803 if (res->id.idmap_id_u.sid.prefix == NULL) { 1804 UNLOCK_CONFIG(); 1805 idmapdlog(LOG_ERR, "Out of memory"); 1806 return (IDMAP_ERR_MEMORY); 1807 } 1808 UNLOCK_CONFIG(); 1809 res->id.idmap_id_u.sid.rid = 1810 (is_user) ? req->id1.idmap_id_u.uid + LOCALRID_MIN : 1811 req->id1.idmap_id_u.gid + INT32_MAX + 1; 1812 res->direction = IDMAP_DIRECTION_BI; 1813 1814 /* 1815 * Don't update name_cache because local sids don't have 1816 * valid windows names. 1817 * We mark the entry as being found in the namecache so that 1818 * the cache update routine doesn't update namecache. 1819 */ 1820 req->direction = _IDMAP_F_S2N_CACHE; 1821 return (IDMAP_SUCCESS); 1822 } 1823 1824 return (IDMAP_ERR_NOMAPPING); 1825 } 1826 1827 static 1828 idmap_retcode 1829 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) 1830 { 1831 char *sidprefix; 1832 uint32_t rid; 1833 int s; 1834 1835 /* 1836 * If the sidprefix == localsid then UID = last RID - 1000 or 1837 * GID = last RID - 2^31. 1838 */ 1839 sidprefix = req->id1.idmap_id_u.sid.prefix; 1840 rid = req->id1.idmap_id_u.sid.rid; 1841 1842 RDLOCK_CONFIG(); 1843 s = (_idmapdstate.cfg->pgcfg.machine_sid) ? 1844 strcasecmp(sidprefix, _idmapdstate.cfg->pgcfg.machine_sid) : 1; 1845 UNLOCK_CONFIG(); 1846 1847 if (s == 0) { 1848 switch (req->id2.idtype) { 1849 case IDMAP_UID: 1850 if (rid > INT32_MAX) { 1851 return (IDMAP_ERR_NOTFOUND); 1852 } else if (rid < LOCALRID_MIN) { 1853 return (IDMAP_ERR_NOTFOUND); 1854 } 1855 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1856 res->id.idtype = IDMAP_UID; 1857 break; 1858 case IDMAP_GID: 1859 if (rid <= INT32_MAX) { 1860 return (IDMAP_ERR_NOTFOUND); 1861 } 1862 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 1863 res->id.idtype = IDMAP_GID; 1864 break; 1865 case IDMAP_POSIXID: 1866 if (rid > INT32_MAX) { 1867 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 1868 res->id.idtype = IDMAP_GID; 1869 } else if (rid < LOCALRID_MIN) { 1870 return (IDMAP_ERR_NOTFOUND); 1871 } else { 1872 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1873 res->id.idtype = IDMAP_UID; 1874 } 1875 break; 1876 default: 1877 return (IDMAP_ERR_NOTSUPPORTED); 1878 } 1879 return (IDMAP_SUCCESS); 1880 } 1881 1882 return (IDMAP_ERR_NOTFOUND); 1883 } 1884 1885 static 1886 idmap_retcode 1887 ns_lookup_byname(int is_user, const char *name, const char *lower_name, 1888 idmap_id_res *res) 1889 { 1890 struct passwd pwd, *pwdp; 1891 struct group grp, *grpp; 1892 char buf[1024]; 1893 int errnum; 1894 const char *me = "ns_lookup_byname"; 1895 1896 if (is_user) { 1897 pwdp = getpwnam_r(name, &pwd, buf, sizeof (buf)); 1898 if (pwdp == NULL && lower_name != NULL && 1899 name != lower_name && strcmp(name, lower_name) != 0) 1900 pwdp = getpwnam_r(lower_name, &pwd, buf, sizeof (buf)); 1901 1902 if (pwdp == NULL) { 1903 errnum = errno; 1904 idmapdlog(LOG_WARNING, 1905 "%s: getpwnam_r(%s) failed (%s).", 1906 me, name, errnum ? strerror(errnum) : "not found"); 1907 if (errnum == 0) 1908 return (IDMAP_ERR_NOTFOUND); 1909 else 1910 return (IDMAP_ERR_INTERNAL); 1911 } 1912 res->id.idmap_id_u.uid = pwd.pw_uid; 1913 res->id.idtype = IDMAP_UID; 1914 } else { 1915 grpp = getgrnam_r(name, &grp, buf, sizeof (buf)); 1916 if (grpp == NULL && lower_name != NULL && 1917 name != lower_name && strcmp(name, lower_name) != 0) 1918 grpp = getgrnam_r(lower_name, &grp, buf, sizeof (buf)); 1919 if (grpp == NULL) { 1920 errnum = errno; 1921 idmapdlog(LOG_WARNING, 1922 "%s: getgrnam_r(%s) failed (%s).", 1923 me, name, errnum ? strerror(errnum) : "not found"); 1924 if (errnum == 0) 1925 return (IDMAP_ERR_NOTFOUND); 1926 else 1927 return (IDMAP_ERR_INTERNAL); 1928 } 1929 res->id.idmap_id_u.gid = grp.gr_gid; 1930 res->id.idtype = IDMAP_GID; 1931 } 1932 return (IDMAP_SUCCESS); 1933 } 1934 1935 /* 1936 * Name-based mapping 1937 * 1938 * Case 1: If no rule matches do ephemeral 1939 * 1940 * Case 2: If rule matches and unixname is "" then return no mapping. 1941 * 1942 * Case 3: If rule matches and unixname is specified then lookup name 1943 * service using the unixname. If unixname not found then return no mapping. 1944 * 1945 * Case 4: If rule matches and unixname is * then lookup name service 1946 * using winname as the unixname. If unixname not found then process 1947 * other rules using the lookup order. If no other rule matches then do 1948 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 1949 * This allows us to specify a fallback unixname per _domain_ or no mapping 1950 * instead of the default behaviour of doing ephemeral mapping. 1951 * 1952 * Example 1: 1953 * *@sfbay == * 1954 * If looking up windows users foo@sfbay and foo does not exists in 1955 * the name service then foo@sfbay will be mapped to an ephemeral id. 1956 * 1957 * Example 2: 1958 * *@sfbay == * 1959 * *@sfbay => guest 1960 * If looking up windows users foo@sfbay and foo does not exists in 1961 * the name service then foo@sfbay will be mapped to guest. 1962 * 1963 * Example 3: 1964 * *@sfbay == * 1965 * *@sfbay => "" 1966 * If looking up windows users foo@sfbay and foo does not exists in 1967 * the name service then we will return no mapping for foo@sfbay. 1968 * 1969 */ 1970 static 1971 idmap_retcode 1972 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) 1973 { 1974 const char *unixname, *windomain; 1975 char *sql = NULL, *errmsg = NULL, *lower_winname = NULL; 1976 idmap_retcode retcode; 1977 char *end, *lower_unixname, *winname; 1978 const char **values; 1979 sqlite_vm *vm = NULL; 1980 int ncol, r, i, is_user, is_wuser; 1981 const char *me = "name_based_mapping_sid2pid"; 1982 1983 winname = req->id1name; 1984 windomain = req->id1domain; 1985 1986 switch (req->id1.idtype) { 1987 case IDMAP_USID: 1988 is_wuser = 1; 1989 break; 1990 case IDMAP_GSID: 1991 is_wuser = 0; 1992 break; 1993 default: 1994 idmapdlog(LOG_ERR, "Idmapd internal error: userness of the " 1995 "winname undetermined."); 1996 return (IDMAP_ERR_INTERNAL); 1997 break; 1998 } 1999 2000 switch (req->id2.idtype) { 2001 case IDMAP_UID: 2002 is_user = 1; 2003 break; 2004 case IDMAP_GID: 2005 is_user = 0; 2006 break; 2007 case IDMAP_POSIXID: 2008 is_user = is_wuser; 2009 res->id.idtype = is_user ? IDMAP_UID : IDMAP_GID; 2010 break; 2011 } 2012 2013 i = 0; 2014 if (windomain == NULL) { 2015 windomain = ""; 2016 } else { 2017 RDLOCK_CONFIG(); 2018 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2019 if (strcasecmp(_idmapdstate.cfg->pgcfg.default_domain, 2020 windomain) == 0) 2021 i = 1; 2022 } 2023 UNLOCK_CONFIG(); 2024 } 2025 2026 if ((lower_winname = tolower_u8(winname)) == NULL) 2027 lower_winname = winname; /* hope for the best */ 2028 sql = sqlite_mprintf( 2029 "SELECT unixname, u2w_order FROM namerules WHERE " 2030 "w2u_order > 0 AND is_user = %d AND is_wuser = %d AND " 2031 "(winname = %Q OR winname = '*') AND " 2032 "(windomain = %Q OR windomain = '*' %s) " 2033 "ORDER BY w2u_order ASC;", 2034 is_user, is_wuser, lower_winname, windomain, 2035 i ? "OR windomain ISNULL OR windomain = ''" : ""); 2036 if (sql == NULL) { 2037 idmapdlog(LOG_ERR, "Out of memory"); 2038 retcode = IDMAP_ERR_MEMORY; 2039 goto out; 2040 } 2041 2042 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 2043 retcode = IDMAP_ERR_INTERNAL; 2044 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2045 CHECK_NULL(errmsg)); 2046 sqlite_freemem(errmsg); 2047 goto out; 2048 } 2049 2050 for (; ; ) { 2051 r = sqlite_step(vm, &ncol, &values, NULL); 2052 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 2053 2054 if (r == SQLITE_ROW) { 2055 if (ncol < 2) { 2056 retcode = IDMAP_ERR_INTERNAL; 2057 goto out; 2058 } 2059 if (values[0] == NULL) { 2060 retcode = IDMAP_ERR_INTERNAL; 2061 goto out; 2062 } 2063 2064 if (EMPTY_NAME(values[0])) { 2065 retcode = IDMAP_ERR_NOMAPPING; 2066 goto out; 2067 } 2068 unixname = (values[0][0] == '*') ? winname : values[0]; 2069 lower_unixname = (values[0][0] == '*') ? 2070 lower_winname : NULL; 2071 retcode = ns_lookup_byname(is_user, unixname, 2072 lower_unixname, res); 2073 if (retcode == IDMAP_ERR_NOTFOUND) { 2074 if (unixname == winname) 2075 /* Case 4 */ 2076 continue; 2077 else 2078 /* Case 3 */ 2079 retcode = IDMAP_ERR_NOMAPPING; 2080 } 2081 goto out; 2082 } else if (r == SQLITE_DONE) { 2083 retcode = IDMAP_ERR_NOTFOUND; 2084 goto out; 2085 } else { 2086 (void) sqlite_finalize(vm, &errmsg); 2087 vm = NULL; 2088 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2089 CHECK_NULL(errmsg)); 2090 sqlite_freemem(errmsg); 2091 retcode = IDMAP_ERR_INTERNAL; 2092 goto out; 2093 } 2094 } 2095 2096 out: 2097 sqlite_freemem(sql); 2098 if (retcode == IDMAP_SUCCESS) { 2099 if (values[1] != NULL) 2100 res->direction = 2101 (strtol(values[1], &end, 10) == 0)? 2102 IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 2103 else 2104 res->direction = IDMAP_DIRECTION_W2U; 2105 req->id2name = strdup(unixname); 2106 } 2107 if (lower_winname != NULL && lower_winname != winname) 2108 free(lower_winname); 2109 if (vm != NULL) 2110 (void) sqlite_finalize(vm, NULL); 2111 return (retcode); 2112 } 2113 2114 static 2115 int 2116 get_next_eph_uid(uid_t *next_uid) 2117 { 2118 uid_t uid; 2119 gid_t gid; 2120 int err; 2121 2122 *next_uid = (uid_t)-1; 2123 uid = _idmapdstate.next_uid++; 2124 if (uid >= _idmapdstate.limit_uid) { 2125 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 2126 return (err); 2127 2128 _idmapdstate.limit_uid = uid + 8192; 2129 _idmapdstate.next_uid = uid; 2130 } 2131 *next_uid = uid; 2132 2133 return (0); 2134 } 2135 2136 static 2137 int 2138 get_next_eph_gid(gid_t *next_gid) 2139 { 2140 uid_t uid; 2141 gid_t gid; 2142 int err; 2143 2144 *next_gid = (uid_t)-1; 2145 gid = _idmapdstate.next_gid++; 2146 if (gid >= _idmapdstate.limit_gid) { 2147 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 2148 return (err); 2149 2150 _idmapdstate.limit_gid = gid + 8192; 2151 _idmapdstate.next_gid = gid; 2152 } 2153 *next_gid = gid; 2154 2155 return (0); 2156 } 2157 2158 static 2159 int 2160 gethash(const char *str, uint32_t num, uint_t htsize) 2161 { 2162 uint_t hval, i, len; 2163 2164 if (str == NULL) 2165 return (0); 2166 for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 2167 hval += str[i]; 2168 hval += (hval << 10); 2169 hval ^= (hval >> 6); 2170 } 2171 for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 2172 hval += str[i]; 2173 hval += (hval << 10); 2174 hval ^= (hval >> 6); 2175 } 2176 hval += (hval << 3); 2177 hval ^= (hval >> 11); 2178 hval += (hval << 15); 2179 return (hval % htsize); 2180 } 2181 2182 static 2183 int 2184 get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 2185 uid_t *pid) 2186 { 2187 uint_t next, key; 2188 uint_t htsize = state->sid_history_size; 2189 idmap_sid *sid; 2190 2191 next = gethash(prefix, rid, htsize); 2192 while (next != htsize) { 2193 key = state->sid_history[next].key; 2194 if (key == htsize) 2195 return (0); 2196 sid = &state->batch->idmap_mapping_batch_val[key].id1. 2197 idmap_id_u.sid; 2198 if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 2199 *pid = state->result->ids.ids_val[key].id. 2200 idmap_id_u.uid; 2201 return (1); 2202 } 2203 next = state->sid_history[next].next; 2204 } 2205 return (0); 2206 } 2207 2208 static 2209 void 2210 add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) 2211 { 2212 uint_t hash, next; 2213 uint_t htsize = state->sid_history_size; 2214 2215 hash = next = gethash(prefix, rid, htsize); 2216 while (state->sid_history[next].key != htsize) { 2217 next++; 2218 next %= htsize; 2219 } 2220 state->sid_history[next].key = state->curpos; 2221 if (hash == next) 2222 return; 2223 state->sid_history[next].next = state->sid_history[hash].next; 2224 state->sid_history[hash].next = next; 2225 } 2226 2227 /* ARGSUSED */ 2228 static 2229 idmap_retcode 2230 dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 2231 idmap_mapping *req, idmap_id_res *res) 2232 { 2233 2234 uid_t next_pid; 2235 2236 res->direction = IDMAP_DIRECTION_BI; 2237 2238 if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 2239 return (IDMAP_SUCCESS); 2240 2241 if (state->sid_history != NULL && 2242 get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 2243 req->id1.idmap_id_u.sid.rid, &next_pid)) { 2244 res->id.idmap_id_u.uid = next_pid; 2245 return (IDMAP_SUCCESS); 2246 } 2247 2248 if (res->id.idtype == IDMAP_UID) { 2249 if (get_next_eph_uid(&next_pid) != 0) 2250 return (IDMAP_ERR_INTERNAL); 2251 res->id.idmap_id_u.uid = next_pid; 2252 } else { 2253 if (get_next_eph_gid(&next_pid) != 0) 2254 return (IDMAP_ERR_INTERNAL); 2255 res->id.idmap_id_u.gid = next_pid; 2256 } 2257 2258 if (state->sid_history != NULL) 2259 add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 2260 req->id1.idmap_id_u.sid.rid); 2261 2262 return (IDMAP_SUCCESS); 2263 } 2264 2265 idmap_retcode 2266 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 2267 idmap_mapping *req, idmap_id_res *res) 2268 { 2269 idmap_retcode retcode; 2270 2271 /* 2272 * The req->direction field is used to maintain state of the 2273 * sid2pid request. 2274 */ 2275 2276 /* Check if second pass is needed */ 2277 if (req->direction == _IDMAP_F_DONE) 2278 return (res->retcode); 2279 2280 /* Get status from previous pass */ 2281 retcode = (res->retcode == IDMAP_NEXT) ? IDMAP_SUCCESS : res->retcode; 2282 2283 if (retcode != IDMAP_SUCCESS) { 2284 /* Reset return type */ 2285 res->id.idtype = req->id2.idtype; 2286 res->id.idmap_id_u.uid = UID_NOBODY; 2287 2288 /* Check if this is a localsid */ 2289 if (retcode == IDMAP_ERR_NOTFOUND && 2290 _idmapdstate.cfg->pgcfg.machine_sid) { 2291 retcode = lookup_localsid2pid(req, res); 2292 if (retcode == IDMAP_SUCCESS) { 2293 state->sid2pid_done = FALSE; 2294 req->direction = _IDMAP_F_S2N_CACHE; 2295 } 2296 } 2297 goto out; 2298 } 2299 2300 /* Name-based mapping */ 2301 retcode = name_based_mapping_sid2pid(db, req, res); 2302 if (retcode == IDMAP_ERR_NOTFOUND) 2303 /* If not found, do ephemeral mapping */ 2304 goto ephemeral; 2305 else if (retcode != IDMAP_SUCCESS) 2306 goto out; 2307 2308 state->sid2pid_done = FALSE; 2309 goto out; 2310 2311 2312 ephemeral: 2313 retcode = dynamic_ephemeral_mapping(state, cache, req, res); 2314 if (retcode == IDMAP_SUCCESS) 2315 state->sid2pid_done = FALSE; 2316 2317 out: 2318 res->retcode = idmap_stat4prot(retcode); 2319 return (retcode); 2320 } 2321 2322 idmap_retcode 2323 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 2324 idmap_mapping *req, idmap_id_res *res) 2325 { 2326 char *sql = NULL; 2327 idmap_retcode retcode; 2328 2329 /* Check if we need to cache anything */ 2330 if (req->direction == _IDMAP_F_DONE) 2331 return (IDMAP_SUCCESS); 2332 2333 /* We don't cache negative entries */ 2334 if (res->retcode != IDMAP_SUCCESS) 2335 return (IDMAP_SUCCESS); 2336 2337 /* 2338 * Using NULL for u2w instead of 0 so that our trigger allows 2339 * the same pid to be the destination in multiple entries 2340 */ 2341 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2342 "(sidprefix, rid, windomain, canon_winname, pid, unixname, " 2343 "is_user, is_wuser, expiration, w2u, u2w) " 2344 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " 2345 "strftime('%%s','now') + 600, %q, 1); ", 2346 res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, 2347 req->id2domain, req->id2name, req->id1.idmap_id_u.uid, 2348 req->id1name, (req->id1.idtype == IDMAP_UID) ? 1 : 0, 2349 (req->id2.idtype == IDMAP_USID) ? 1 : 0, 2350 (res->direction == 0) ? "1" : NULL); 2351 2352 if (sql == NULL) { 2353 retcode = IDMAP_ERR_INTERNAL; 2354 idmapdlog(LOG_ERR, "Out of memory"); 2355 goto out; 2356 } 2357 2358 retcode = sql_exec_no_cb(cache, sql); 2359 if (retcode != IDMAP_SUCCESS) 2360 goto out; 2361 2362 state->pid2sid_done = FALSE; 2363 sqlite_freemem(sql); 2364 sql = NULL; 2365 2366 /* If sid2name was found in the cache, no need to update namecache */ 2367 if (req->direction & _IDMAP_F_S2N_CACHE) 2368 goto out; 2369 2370 if (req->id2name == NULL) 2371 goto out; 2372 2373 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2374 "(sidprefix, rid, canon_name, domain, type, expiration) " 2375 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2376 res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, 2377 req->id2name, req->id2domain, 2378 (req->id2.idtype == IDMAP_UID) ? _IDMAP_T_USER : _IDMAP_T_GROUP); 2379 2380 if (sql == NULL) { 2381 retcode = IDMAP_ERR_INTERNAL; 2382 idmapdlog(LOG_ERR, "Out of memory"); 2383 goto out; 2384 } 2385 2386 retcode = sql_exec_no_cb(cache, sql); 2387 2388 out: 2389 if (sql != NULL) 2390 sqlite_freemem(sql); 2391 return (retcode); 2392 } 2393 2394 idmap_retcode 2395 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 2396 idmap_mapping *req, idmap_id_res *res) 2397 { 2398 char *sql = NULL; 2399 idmap_retcode retcode; 2400 int is_eph_user; 2401 2402 /* Check if we need to cache anything */ 2403 if (req->direction == _IDMAP_F_DONE) 2404 return (IDMAP_SUCCESS); 2405 2406 /* We don't cache negative entries */ 2407 if (res->retcode != IDMAP_SUCCESS) 2408 return (IDMAP_SUCCESS); 2409 2410 if (req->direction & _IDMAP_F_EXP_EPH_UID) 2411 is_eph_user = 1; 2412 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 2413 is_eph_user = 0; 2414 else 2415 is_eph_user = -1; 2416 2417 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 2418 sql = sqlite_mprintf("UPDATE idmap_cache " 2419 "SET w2u = 0 WHERE " 2420 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 2421 "pid >= 2147483648 AND is_user = %d;", 2422 req->id1.idmap_id_u.sid.prefix, 2423 req->id1.idmap_id_u.sid.rid, 2424 is_eph_user); 2425 if (sql == NULL) { 2426 retcode = IDMAP_ERR_INTERNAL; 2427 idmapdlog(LOG_ERR, "Out of memory"); 2428 goto out; 2429 } 2430 2431 retcode = sql_exec_no_cb(cache, sql); 2432 if (retcode != IDMAP_SUCCESS) 2433 goto out; 2434 2435 sqlite_freemem(sql); 2436 sql = NULL; 2437 } 2438 2439 2440 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2441 "(sidprefix, rid, windomain, canon_winname, pid, unixname, " 2442 "is_user, is_wuser, expiration, w2u, u2w) " 2443 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " 2444 "strftime('%%s','now') + 600, 1, %q); ", 2445 req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, 2446 req->id1domain, req->id1name, res->id.idmap_id_u.uid, 2447 req->id2name, (res->id.idtype == IDMAP_UID) ? 1 : 0, 2448 (req->id1.idtype == IDMAP_USID) ? 1 : 0, 2449 (res->direction == 0) ? "1" : NULL); 2450 2451 if (sql == NULL) { 2452 retcode = IDMAP_ERR_INTERNAL; 2453 idmapdlog(LOG_ERR, "Out of memory"); 2454 goto out; 2455 } 2456 2457 retcode = sql_exec_no_cb(cache, sql); 2458 if (retcode != IDMAP_SUCCESS) 2459 goto out; 2460 2461 state->sid2pid_done = FALSE; 2462 sqlite_freemem(sql); 2463 sql = NULL; 2464 2465 /* If name2sid was found in the cache, no need to update namecache */ 2466 if (req->direction & _IDMAP_F_S2N_CACHE) 2467 goto out; 2468 2469 if (EMPTY_STRING(req->id1name)) 2470 goto out; 2471 2472 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2473 "(sidprefix, rid, canon_name, domain, type, expiration) " 2474 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2475 req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, 2476 req->id1name, req->id1domain, 2477 (req->id1.idtype == IDMAP_USID) ? _IDMAP_T_USER : _IDMAP_T_GROUP); 2478 2479 if (sql == NULL) { 2480 retcode = IDMAP_ERR_INTERNAL; 2481 idmapdlog(LOG_ERR, "Out of memory"); 2482 goto out; 2483 } 2484 2485 retcode = sql_exec_no_cb(cache, sql); 2486 2487 out: 2488 if (sql != NULL) 2489 sqlite_freemem(sql); 2490 return (retcode); 2491 } 2492 2493 static 2494 idmap_retcode 2495 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 2496 int is_user, int getname) 2497 { 2498 char *end; 2499 char *sql = NULL; 2500 const char **values; 2501 sqlite_vm *vm = NULL; 2502 int ncol; 2503 idmap_retcode retcode = IDMAP_SUCCESS; 2504 time_t curtime; 2505 2506 /* Current time */ 2507 errno = 0; 2508 if ((curtime = time(NULL)) == (time_t)-1) { 2509 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 2510 strerror(errno)); 2511 retcode = IDMAP_ERR_INTERNAL; 2512 goto out; 2513 } 2514 2515 /* SQL to lookup the cache */ 2516 sql = sqlite_mprintf("SELECT sidprefix, rid, canon_winname, windomain, " 2517 "w2u, is_wuser " 2518 "FROM idmap_cache WHERE " 2519 "pid = %u AND u2w = 1 AND is_user = %d AND " 2520 "(pid >= 2147483648 OR " 2521 "(expiration = 0 OR expiration ISNULL OR " 2522 "expiration > %d));", 2523 req->id1.idmap_id_u.uid, is_user, curtime); 2524 if (sql == NULL) { 2525 idmapdlog(LOG_ERR, "Out of memory"); 2526 retcode = IDMAP_ERR_MEMORY; 2527 goto out; 2528 } 2529 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 2530 sqlite_freemem(sql); 2531 2532 if (retcode == IDMAP_ERR_NOTFOUND) 2533 goto out; 2534 else if (retcode == IDMAP_SUCCESS) { 2535 /* sanity checks */ 2536 if (values[0] == NULL || values[1] == NULL) { 2537 retcode = IDMAP_ERR_CACHE; 2538 goto out; 2539 } 2540 2541 switch (req->id2.idtype) { 2542 case IDMAP_SID: 2543 case IDMAP_USID: 2544 case IDMAP_GSID: 2545 res->id.idtype = 2546 strtol(values[5], &end, 10) == 1 2547 ? IDMAP_USID : IDMAP_GSID; 2548 2549 if (req->id2.idtype == IDMAP_USID && 2550 res->id.idtype == IDMAP_GSID) { 2551 retcode = IDMAP_ERR_NOTUSER; 2552 goto out; 2553 } else if (req->id2.idtype == IDMAP_GSID && 2554 res->id.idtype == IDMAP_USID) { 2555 retcode = IDMAP_ERR_NOTGROUP; 2556 goto out; 2557 } 2558 2559 res->id.idmap_id_u.sid.rid = 2560 strtoul(values[1], &end, 10); 2561 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 2562 if (res->id.idmap_id_u.sid.prefix == NULL) { 2563 idmapdlog(LOG_ERR, "Out of memory"); 2564 retcode = IDMAP_ERR_MEMORY; 2565 goto out; 2566 } 2567 2568 if (values[4] != NULL) 2569 res->direction = 2570 (strtol(values[4], &end, 10) == 0)? 2571 IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2572 else 2573 res->direction = IDMAP_DIRECTION_U2W; 2574 2575 if (getname == 0 || values[2] == NULL) 2576 break; 2577 req->id2name = strdup(values[2]); 2578 if (req->id2name == NULL) { 2579 idmapdlog(LOG_ERR, "Out of memory"); 2580 retcode = IDMAP_ERR_MEMORY; 2581 goto out; 2582 } 2583 2584 if (values[3] == NULL) 2585 break; 2586 req->id2domain = strdup(values[3]); 2587 if (req->id2domain == NULL) { 2588 idmapdlog(LOG_ERR, "Out of memory"); 2589 retcode = IDMAP_ERR_MEMORY; 2590 goto out; 2591 } 2592 2593 req->id2.idtype = res->id.idtype; 2594 2595 break; 2596 default: 2597 retcode = IDMAP_ERR_NOTSUPPORTED; 2598 break; 2599 } 2600 } 2601 2602 out: 2603 if (vm != NULL) 2604 (void) sqlite_finalize(vm, NULL); 2605 return (retcode); 2606 } 2607 2608 static 2609 idmap_retcode 2610 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 2611 char **canonname, char **sidprefix, idmap_rid_t *rid, int *type) 2612 { 2613 char *end, *lower_name; 2614 char *sql = NULL; 2615 const char **values; 2616 sqlite_vm *vm = NULL; 2617 int ncol; 2618 time_t curtime; 2619 idmap_retcode retcode = IDMAP_SUCCESS; 2620 2621 /* Get current time */ 2622 errno = 0; 2623 if ((curtime = time(NULL)) == (time_t)-1) { 2624 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 2625 strerror(errno)); 2626 retcode = IDMAP_ERR_INTERNAL; 2627 goto out; 2628 } 2629 2630 /* SQL to lookup the cache */ 2631 if ((lower_name = tolower_u8(name)) == NULL) 2632 lower_name = (char *)name; 2633 sql = sqlite_mprintf("SELECT sidprefix, rid, type, canon_name " 2634 "FROM name_cache WHERE name = %Q AND domain = %Q AND " 2635 "(expiration = 0 OR expiration ISNULL OR " 2636 "expiration > %d);", lower_name, domain, curtime); 2637 if (lower_name != name) 2638 free(lower_name); 2639 if (sql == NULL) { 2640 idmapdlog(LOG_ERR, "Out of memory"); 2641 retcode = IDMAP_ERR_MEMORY; 2642 goto out; 2643 } 2644 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 4, &values); 2645 sqlite_freemem(sql); 2646 2647 if (retcode == IDMAP_SUCCESS) { 2648 if (type != NULL) { 2649 if (values[2] == NULL) { 2650 retcode = IDMAP_ERR_CACHE; 2651 goto out; 2652 } 2653 *type = strtol(values[2], &end, 10); 2654 } 2655 2656 if (canonname != NULL) { 2657 assert(values[3] != NULL); 2658 if ((*canonname = strdup(values[3])) == NULL) { 2659 idmapdlog(LOG_ERR, "Out of memory"); 2660 retcode = IDMAP_ERR_MEMORY; 2661 goto out; 2662 } 2663 } 2664 2665 if (values[0] == NULL || values[1] == NULL) { 2666 retcode = IDMAP_ERR_CACHE; 2667 goto out; 2668 } 2669 if ((*sidprefix = strdup(values[0])) == NULL) { 2670 idmapdlog(LOG_ERR, "Out of memory"); 2671 retcode = IDMAP_ERR_MEMORY; 2672 goto out; 2673 } 2674 *rid = strtoul(values[1], &end, 10); 2675 } 2676 2677 out: 2678 if (vm != NULL) 2679 (void) sqlite_finalize(vm, NULL); 2680 return (retcode); 2681 } 2682 2683 static 2684 idmap_retcode 2685 lookup_win_name2sid(const char *name, const char *domain, 2686 char **canonname, char **sidprefix, idmap_rid_t *rid, 2687 int *type) 2688 { 2689 int ret; 2690 int retries = 0; 2691 idmap_query_state_t *qs = NULL; 2692 idmap_retcode rc, retcode; 2693 2694 retcode = IDMAP_ERR_NOTFOUND; 2695 2696 retry: 2697 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 2698 if (ret != 0) { 2699 degrade_svc(); 2700 idmapdlog(LOG_ERR, 2701 "Failed to create name2sid batch for AD lookup"); 2702 return (IDMAP_ERR_INTERNAL); 2703 } 2704 2705 restore_svc(); 2706 2707 retcode = idmap_name2sid_batch_add1(qs, name, domain, canonname, 2708 sidprefix, rid, type, &rc); 2709 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2710 goto out; 2711 2712 if (retcode != IDMAP_SUCCESS) { 2713 idmapdlog(LOG_ERR, "Failed to batch name2sid for AD lookup"); 2714 idmap_lookup_release_batch(&qs); 2715 return (IDMAP_ERR_INTERNAL); 2716 } 2717 2718 out: 2719 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2720 idmap_lookup_release_batch(&qs); 2721 else 2722 retcode = idmap_lookup_batch_end(&qs, NULL); 2723 2724 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 2725 goto retry; 2726 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2727 degrade_svc(); 2728 2729 if (retcode != IDMAP_SUCCESS) { 2730 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 2731 "failed"); 2732 return (retcode); 2733 } else 2734 return (rc); 2735 /* NOTREACHED */ 2736 } 2737 2738 static 2739 idmap_retcode 2740 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 2741 int *is_wuser, char **canonname, char **sidprefix, 2742 idmap_rid_t *rid, idmap_mapping *req) 2743 { 2744 int type; 2745 idmap_retcode retcode; 2746 2747 *sidprefix = NULL; 2748 *canonname = NULL; 2749 2750 /* Lookup name@domain to sid in the well-known sids table */ 2751 retcode = lookup_wksids_name2sid(name, canonname, sidprefix, rid, 2752 &type); 2753 if (retcode == IDMAP_SUCCESS) { 2754 req->direction |= _IDMAP_F_S2N_CACHE; 2755 goto out; 2756 } else if (retcode != IDMAP_ERR_NOTFOUND) { 2757 return (retcode); 2758 } 2759 2760 /* Lookup name@domain to sid in cache */ 2761 retcode = lookup_cache_name2sid(cache, name, domain, canonname, 2762 sidprefix, rid, &type); 2763 if (retcode == IDMAP_ERR_NOTFOUND) { 2764 /* Lookup Windows NT/AD to map name@domain to sid */ 2765 retcode = lookup_win_name2sid(name, domain, canonname, 2766 sidprefix, rid, &type); 2767 if (retcode != IDMAP_SUCCESS) 2768 return (retcode); 2769 req->direction |= _IDMAP_F_S2N_AD; 2770 } else if (retcode != IDMAP_SUCCESS) { 2771 return (retcode); 2772 } else { 2773 /* Set flag */ 2774 req->direction |= _IDMAP_F_S2N_CACHE; 2775 } 2776 2777 out: 2778 /* 2779 * Entry found (cache or Windows lookup) 2780 * is_wuser is both input as well as output parameter 2781 */ 2782 if (*is_wuser == 1) { 2783 if (type != _IDMAP_T_USER) { 2784 if (*sidprefix != NULL) { 2785 free(*sidprefix); 2786 *sidprefix = NULL; 2787 } 2788 if (*canonname != NULL) { 2789 free(*canonname); 2790 *canonname = NULL; 2791 } 2792 return (IDMAP_ERR_NOTUSER); 2793 } 2794 } else if (*is_wuser == 0) { 2795 if (type != _IDMAP_T_GROUP) { 2796 if (*sidprefix != NULL) { 2797 free(*sidprefix); 2798 *sidprefix = NULL; 2799 } 2800 if (*canonname != NULL) { 2801 free(*canonname); 2802 *canonname = NULL; 2803 } 2804 return (IDMAP_ERR_NOTGROUP); 2805 } 2806 } else if (*is_wuser == -1) { 2807 /* Caller wants to know if its user or group */ 2808 if (type == _IDMAP_T_USER) 2809 *is_wuser = 1; 2810 else if (type == _IDMAP_T_GROUP) 2811 *is_wuser = 0; 2812 else { 2813 if (*sidprefix != NULL) { 2814 free(*sidprefix); 2815 *sidprefix = NULL; 2816 } 2817 if (*canonname != NULL) { 2818 free(*canonname); 2819 *canonname = NULL; 2820 } 2821 return (IDMAP_ERR_SID); 2822 } 2823 } 2824 2825 return (retcode); 2826 } 2827 2828 static 2829 idmap_retcode 2830 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 2831 int is_user, idmap_mapping *req, idmap_id_res *res) 2832 { 2833 const char *winname, *windomain; 2834 char *canonname; 2835 char *default_domain = NULL; 2836 char *sql = NULL, *errmsg = NULL; 2837 idmap_retcode retcode; 2838 char *end; 2839 const char **values; 2840 sqlite_vm *vm = NULL; 2841 int ncol, r, nrow; 2842 const char *me = "name_based_mapping_pid2sid"; 2843 int is_wuser; 2844 2845 RDLOCK_CONFIG(); 2846 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2847 default_domain = 2848 strdup(_idmapdstate.cfg->pgcfg.default_domain); 2849 if (default_domain == NULL) { 2850 UNLOCK_CONFIG(); 2851 idmapdlog(LOG_ERR, "Out of memory"); 2852 retcode = IDMAP_ERR_MEMORY; 2853 goto out; 2854 } 2855 } 2856 UNLOCK_CONFIG(); 2857 2858 sql = sqlite_mprintf( 2859 "SELECT winname_display, windomain, w2u_order FROM namerules WHERE " 2860 "u2w_order > 0 AND is_user = %d AND " 2861 "(unixname = %Q OR unixname = '*') " 2862 "ORDER BY u2w_order ASC;", is_user, unixname); 2863 if (sql == NULL) { 2864 idmapdlog(LOG_ERR, "Out of memory"); 2865 retcode = IDMAP_ERR_MEMORY; 2866 goto out; 2867 } 2868 2869 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 2870 retcode = IDMAP_ERR_INTERNAL; 2871 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2872 CHECK_NULL(errmsg)); 2873 sqlite_freemem(errmsg); 2874 goto out; 2875 } 2876 2877 for (nrow = 0; ; ) { 2878 r = sqlite_step(vm, &ncol, &values, NULL); 2879 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 2880 if (r == SQLITE_ROW) { 2881 nrow++; 2882 if (ncol < 3) { 2883 retcode = IDMAP_ERR_INTERNAL; 2884 goto out; 2885 } 2886 if (values[0] == NULL) { 2887 /* values [1] and [2] can be null */ 2888 retcode = IDMAP_ERR_INTERNAL; 2889 goto out; 2890 } 2891 if (EMPTY_NAME(values[0])) { 2892 retcode = IDMAP_ERR_NOMAPPING; 2893 goto out; 2894 } 2895 2896 if (values[0][0] == '*') { 2897 if (nrow > 1) { 2898 /* 2899 * There were non-wildcard rules where 2900 * windows identity doesn't exist 2901 */ 2902 retcode = IDMAP_ERR_NOMAPPING; 2903 goto out; 2904 } 2905 winname = unixname; 2906 } else { 2907 winname = values[0]; 2908 } 2909 2910 if (values[1] != NULL) 2911 windomain = values[1]; 2912 else if (default_domain != NULL) 2913 windomain = default_domain; 2914 else { 2915 idmapdlog(LOG_ERR, "%s: no domain", me); 2916 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 2917 goto out; 2918 } 2919 /* Lookup winname@domain to sid */ 2920 2921 is_wuser = res->id.idtype == IDMAP_USID ? 1 2922 : res->id.idtype == IDMAP_GSID ? 0 2923 : -1; 2924 2925 retcode = lookup_name2sid(cache, winname, windomain, 2926 &is_wuser, &canonname, 2927 &res->id.idmap_id_u.sid.prefix, 2928 &res->id.idmap_id_u.sid.rid, req); 2929 if (retcode == IDMAP_ERR_NOTFOUND) { 2930 continue; 2931 } 2932 2933 goto out; 2934 } else if (r == SQLITE_DONE) { 2935 retcode = IDMAP_ERR_NOTFOUND; 2936 goto out; 2937 } else { 2938 (void) sqlite_finalize(vm, &errmsg); 2939 vm = NULL; 2940 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2941 CHECK_NULL(errmsg)); 2942 sqlite_freemem(errmsg); 2943 retcode = IDMAP_ERR_INTERNAL; 2944 goto out; 2945 } 2946 } 2947 2948 out: 2949 if (sql != NULL) 2950 sqlite_freemem(sql); 2951 if (retcode == IDMAP_SUCCESS) { 2952 res->id.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID; 2953 2954 if (values[2] != NULL) 2955 res->direction = 2956 (strtol(values[2], &end, 10) == 0)? 2957 IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2958 else 2959 res->direction = IDMAP_DIRECTION_U2W; 2960 2961 req->id2.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID; 2962 req->id2name = canonname; 2963 if (req->id2name != NULL) { 2964 if (windomain == default_domain) { 2965 req->id2domain = (char *)windomain; 2966 default_domain = NULL; 2967 } else { 2968 req->id2domain = strdup(windomain); 2969 } 2970 } 2971 } 2972 if (vm != NULL) 2973 (void) sqlite_finalize(vm, NULL); 2974 if (default_domain != NULL) 2975 free(default_domain); 2976 return (retcode); 2977 } 2978 2979 /* 2980 * Convention when processing unix2win requests: 2981 * 2982 * Unix identity: 2983 * req->id1name = 2984 * unixname if given otherwise unixname found will be placed 2985 * here. 2986 * req->id1domain = 2987 * NOT USED 2988 * req->id1.idtype = 2989 * Given type (IDMAP_UID or IDMAP_GID) 2990 * req->id1..[uid or gid] = 2991 * UID/GID if given otherwise UID/GID found will be placed here. 2992 * 2993 * Windows identity: 2994 * req->id2name = 2995 * winname found will be placed here. 2996 * req->id2domain = 2997 * windomain found will be placed here. 2998 * res->id.idtype = 2999 * Target type initialized from req->id2.idtype. If 3000 * it is IDMAP_SID then actual type (IDMAP_USID/GSID) found 3001 * will be placed here. 3002 * req->id..sid.[prefix, rid] = 3003 * SID found will be placed here. 3004 * 3005 * Others: 3006 * res->retcode = 3007 * Return status for this request will be placed here. 3008 * res->direction = 3009 * Direction found will be placed here. Direction 3010 * meaning whether the resultant mapping is valid 3011 * only from unix2win or bi-directional. 3012 * req->direction = 3013 * INTERNAL USE. Used by idmapd to set various 3014 * flags (_IDMAP_F_xxxx) to aid in processing 3015 * of the request. 3016 * req->id2.idtype = 3017 * INTERNAL USE. Initially this is the requested target 3018 * type and is used to initialize res->id.idtype. 3019 * ad_lookup_batch() uses this field temporarily to store 3020 * sid_type obtained by the batched AD lookups and after 3021 * use resets it to IDMAP_NONE to prevent xdr from 3022 * mis-interpreting the contents of req->id2. 3023 * req->id2..[uid or gid or sid] = 3024 * NOT USED 3025 */ 3026 3027 /* 3028 * This function does the following: 3029 * 1. Lookup well-known SIDs table. 3030 * 2. Lookup cache. 3031 * 3. Check if the client does not want new mapping to be allocated 3032 * in which case this pass is the final pass. 3033 * 4. Set AD lookup flags if it determines that the next stage needs 3034 * to do AD lookup. 3035 */ 3036 idmap_retcode 3037 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 3038 idmap_mapping *req, idmap_id_res *res, int is_user, 3039 int getname) 3040 { 3041 char *unixname = NULL; 3042 struct passwd pwd; 3043 struct group grp; 3044 char buf[1024]; 3045 int errnum; 3046 idmap_retcode retcode = IDMAP_SUCCESS; 3047 const char *me = "pid2sid"; 3048 3049 req->direction = _IDMAP_F_DONE; 3050 res->id.idtype = req->id2.idtype; 3051 3052 /* Lookup well-known SIDs */ 3053 retcode = lookup_wksids_pid2sid(req, res, is_user); 3054 if (retcode != IDMAP_ERR_NOTFOUND) 3055 goto out; 3056 3057 /* Lookup pid to sid in cache */ 3058 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 3059 if (retcode != IDMAP_ERR_NOTFOUND) 3060 goto out; 3061 3062 /* Ephemeral ids cannot be allocated during pid2sid */ 3063 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 3064 retcode = IDMAP_ERR_NOMAPPING; 3065 goto out; 3066 } 3067 3068 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 3069 retcode = IDMAP_ERR_NOMAPPING; 3070 goto out; 3071 } 3072 3073 /* uid/gid to name */ 3074 if (!EMPTY_STRING(req->id1name)) { 3075 unixname = req->id1name; 3076 } else if (is_user) { 3077 errno = 0; 3078 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 3079 sizeof (buf)) == NULL) { 3080 errnum = errno; 3081 idmapdlog(LOG_WARNING, 3082 "%s: getpwuid_r(%u) failed (%s).", 3083 me, req->id1.idmap_id_u.uid, 3084 errnum ? strerror(errnum) : "not found"); 3085 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3086 IDMAP_ERR_INTERNAL; 3087 goto fallback_localsid; 3088 } 3089 unixname = pwd.pw_name; 3090 } else { 3091 errno = 0; 3092 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 3093 sizeof (buf)) == NULL) { 3094 errnum = errno; 3095 idmapdlog(LOG_WARNING, 3096 "%s: getgrgid_r(%u) failed (%s).", 3097 me, req->id1.idmap_id_u.gid, 3098 errnum ? strerror(errnum) : "not found"); 3099 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3100 IDMAP_ERR_INTERNAL; 3101 goto fallback_localsid; 3102 } 3103 unixname = grp.gr_name; 3104 } 3105 3106 /* Name-based mapping */ 3107 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 3108 req, res); 3109 if (retcode == IDMAP_ERR_NOTFOUND) { 3110 retcode = generate_localsid(req, res, is_user); 3111 goto out; 3112 } else if (retcode == IDMAP_SUCCESS) 3113 goto out; 3114 3115 fallback_localsid: 3116 /* 3117 * Here we generate localsid as fallback id on errors. Our 3118 * return status is the error that's been previously assigned. 3119 */ 3120 (void) generate_localsid(req, res, is_user); 3121 3122 out: 3123 if (retcode == IDMAP_SUCCESS && EMPTY_STRING(req->id1name) && 3124 unixname != NULL) { 3125 if (req->id1name != NULL) 3126 free(req->id1name); 3127 req->id1name = strdup(unixname); 3128 if (req->id1name == NULL) 3129 retcode = IDMAP_ERR_MEMORY; 3130 } 3131 if (req->direction != _IDMAP_F_DONE) 3132 state->pid2sid_done = FALSE; 3133 res->retcode = idmap_stat4prot(retcode); 3134 return (retcode); 3135 } 3136 3137 static 3138 idmap_retcode 3139 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 3140 char **domain, int *type) 3141 { 3142 int ret; 3143 idmap_query_state_t *qs = NULL; 3144 idmap_retcode rc, retcode; 3145 3146 retcode = IDMAP_ERR_NOTFOUND; 3147 3148 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 3149 if (ret != 0) { 3150 degrade_svc(); 3151 idmapdlog(LOG_ERR, 3152 "Failed to create sid2name batch for AD lookup"); 3153 retcode = IDMAP_ERR_INTERNAL; 3154 goto out; 3155 } 3156 3157 restore_svc(); 3158 3159 ret = idmap_sid2name_batch_add1(qs, sidprefix, &rid, name, domain, 3160 type, &rc); 3161 if (ret != 0) { 3162 idmapdlog(LOG_ERR, "Failed to batch sid2name for AD lookup"); 3163 retcode = IDMAP_ERR_INTERNAL; 3164 goto out; 3165 } 3166 3167 out: 3168 if (qs != NULL) { 3169 ret = idmap_lookup_batch_end(&qs, NULL); 3170 if (ret == IDMAP_ERR_RETRIABLE_NET_ERR) 3171 degrade_svc(); 3172 if (ret != 0) { 3173 idmapdlog(LOG_ERR, 3174 "Failed to execute sid2name AD lookup"); 3175 retcode = IDMAP_ERR_INTERNAL; 3176 } else 3177 retcode = rc; 3178 } 3179 3180 return (retcode); 3181 } 3182 3183 static 3184 int 3185 copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 3186 { 3187 (void) memset(mapping, 0, sizeof (*mapping)); 3188 3189 mapping->flag = request->flag; 3190 mapping->direction = request->direction; 3191 mapping->id2.idtype = request->id2.idtype; 3192 3193 mapping->id1.idtype = request->id1.idtype; 3194 if (IS_REQUEST_SID(*request, 1)) { 3195 mapping->id1.idmap_id_u.sid.rid = 3196 request->id1.idmap_id_u.sid.rid; 3197 if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 3198 mapping->id1.idmap_id_u.sid.prefix = 3199 strdup(request->id1.idmap_id_u.sid.prefix); 3200 if (mapping->id1.idmap_id_u.sid.prefix == NULL) 3201 goto errout; 3202 } 3203 } else { 3204 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 3205 } 3206 3207 mapping->id1domain = strdup(request->id1domain); 3208 if (mapping->id1domain == NULL) 3209 goto errout; 3210 3211 mapping->id1name = strdup(request->id1name); 3212 if (mapping->id1name == NULL) 3213 goto errout; 3214 3215 /* We don't need the rest of the request i.e request->id2 */ 3216 return (0); 3217 3218 errout: 3219 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 3220 free(mapping->id1.idmap_id_u.sid.prefix); 3221 if (mapping->id1domain != NULL) 3222 free(mapping->id1domain); 3223 if (mapping->id1name != NULL) 3224 free(mapping->id1name); 3225 3226 (void) memset(mapping, 0, sizeof (*mapping)); 3227 return (-1); 3228 } 3229 3230 3231 idmap_retcode 3232 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 3233 idmap_mapping *mapping) 3234 { 3235 idmap_id_res idres; 3236 lookup_state_t state; 3237 char *cp; 3238 int is_wuser; 3239 idmap_retcode retcode; 3240 const char *winname, *windomain; 3241 char *canonname; 3242 3243 (void) memset(&idres, 0, sizeof (idres)); 3244 (void) memset(&state, 0, sizeof (state)); 3245 3246 if (request->id1.idtype == IDMAP_USID) 3247 is_wuser = 1; 3248 else if (request->id1.idtype == IDMAP_GSID) 3249 is_wuser = 0; 3250 else if (request->id1.idtype == IDMAP_SID) 3251 is_wuser = -1; 3252 else { 3253 retcode = IDMAP_ERR_IDTYPE; 3254 goto out; 3255 } 3256 3257 /* Copy data from request to result */ 3258 if (copy_mapping_request(mapping, request) < 0) { 3259 retcode = IDMAP_ERR_MEMORY; 3260 goto out; 3261 } 3262 3263 winname = mapping->id1name; 3264 windomain = mapping->id1domain; 3265 3266 if (EMPTY_STRING(winname) && !EMPTY_STRING(windomain)) { 3267 retcode = IDMAP_ERR_ARG; 3268 goto out; 3269 } 3270 3271 if (!EMPTY_STRING(winname) && EMPTY_STRING(windomain)) { 3272 retcode = IDMAP_SUCCESS; 3273 if ((cp = strchr(winname, '@')) != NULL) { 3274 /* 3275 * if winname is qualified with a domain, use it. 3276 */ 3277 *cp = '\0'; 3278 mapping->id1domain = strdup(cp + 1); 3279 if (mapping->id1domain == NULL) 3280 retcode = IDMAP_ERR_MEMORY; 3281 } else { 3282 RDLOCK_CONFIG(); 3283 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 3284 /* 3285 * otherwise use the mapping domain 3286 */ 3287 mapping->id1domain = 3288 strdup(_idmapdstate.cfg-> 3289 pgcfg.default_domain); 3290 if (mapping->id1domain == NULL) 3291 retcode = IDMAP_ERR_MEMORY; 3292 } 3293 UNLOCK_CONFIG(); 3294 } 3295 3296 if (retcode != IDMAP_SUCCESS) { 3297 idmapdlog(LOG_ERR, "Out of memory"); 3298 goto out; 3299 } 3300 windomain = mapping->id1domain; 3301 } 3302 3303 if (!EMPTY_STRING(winname) && 3304 EMPTY_STRING(mapping->id1.idmap_id_u.sid.prefix)) { 3305 retcode = lookup_name2sid(cache, winname, windomain, 3306 &is_wuser, &canonname, &mapping->id1.idmap_id_u.sid.prefix, 3307 &mapping->id1.idmap_id_u.sid.rid, mapping); 3308 if (retcode != IDMAP_SUCCESS) 3309 goto out; 3310 free(mapping->id1name); 3311 mapping->id1name = canonname; 3312 if (mapping->id1.idtype == IDMAP_SID) 3313 mapping->id1.idtype = is_wuser ? 3314 IDMAP_USID : IDMAP_GSID; 3315 } 3316 3317 state.sid2pid_done = TRUE; 3318 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 3319 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 3320 goto out; 3321 3322 if (state.ad_nqueries) { 3323 /* sid2name AD lookup */ 3324 retcode = lookup_win_sid2name( 3325 mapping->id1.idmap_id_u.sid.prefix, 3326 mapping->id1.idmap_id_u.sid.rid, 3327 &mapping->id1name, 3328 &mapping->id1domain, 3329 (int *)&idres.id.idtype); 3330 3331 idres.retcode = retcode; 3332 } 3333 3334 state.sid2pid_done = TRUE; 3335 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 3336 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 3337 goto out; 3338 3339 /* Update cache */ 3340 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 3341 3342 out: 3343 if (retcode == IDMAP_SUCCESS) { 3344 mapping->direction = idres.direction; 3345 mapping->id2 = idres.id; 3346 (void) memset(&idres, 0, sizeof (idres)); 3347 } else { 3348 mapping->id2.idmap_id_u.uid = UID_NOBODY; 3349 } 3350 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 3351 return (retcode); 3352 } 3353 3354 idmap_retcode 3355 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 3356 idmap_mapping *mapping, int is_user) 3357 { 3358 idmap_id_res idres; 3359 lookup_state_t state; 3360 struct passwd pwd; 3361 struct group grp; 3362 char buf[1024]; 3363 int errnum; 3364 idmap_retcode retcode; 3365 const char *unixname; 3366 const char *me = "get_u2w_mapping"; 3367 3368 /* 3369 * In order to re-use the pid2sid code, we convert 3370 * our input data into structs that are expected by 3371 * pid2sid_first_pass. 3372 */ 3373 3374 (void) memset(&idres, 0, sizeof (idres)); 3375 (void) memset(&state, 0, sizeof (state)); 3376 3377 /* Copy data from request to result */ 3378 if (copy_mapping_request(mapping, request) < 0) { 3379 retcode = IDMAP_ERR_MEMORY; 3380 goto out; 3381 } 3382 3383 unixname = mapping->id1name; 3384 3385 if (EMPTY_STRING(unixname) && 3386 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 3387 retcode = IDMAP_ERR_ARG; 3388 goto out; 3389 } 3390 3391 if (!EMPTY_STRING(unixname) && 3392 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 3393 /* Get uid/gid by name */ 3394 if (is_user) { 3395 errno = 0; 3396 if (getpwnam_r(unixname, &pwd, buf, 3397 sizeof (buf)) == NULL) { 3398 errnum = errno; 3399 idmapdlog(LOG_WARNING, 3400 "%s: getpwnam_r(%s) failed (%s).", 3401 me, unixname, 3402 errnum ? strerror(errnum) : "not found"); 3403 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3404 IDMAP_ERR_INTERNAL; 3405 goto out; 3406 } 3407 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 3408 } else { 3409 errno = 0; 3410 if (getgrnam_r(unixname, &grp, buf, 3411 sizeof (buf)) == NULL) { 3412 errnum = errno; 3413 idmapdlog(LOG_WARNING, 3414 "%s: getgrnam_r(%s) failed (%s).", 3415 me, unixname, 3416 errnum ? strerror(errnum) : "not found"); 3417 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3418 IDMAP_ERR_INTERNAL; 3419 goto out; 3420 } 3421 mapping->id1.idmap_id_u.gid = grp.gr_gid; 3422 } 3423 } 3424 3425 state.pid2sid_done = TRUE; 3426 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 3427 is_user, 1); 3428 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 3429 goto out; 3430 3431 /* Update cache */ 3432 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 3433 3434 out: 3435 mapping->direction = idres.direction; 3436 mapping->id2 = idres.id; 3437 (void) memset(&idres, 0, sizeof (idres)); 3438 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 3439 return (retcode); 3440 } 3441