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