14520Snw141292 /* 24520Snw141292 * CDDL HEADER START 34520Snw141292 * 44520Snw141292 * The contents of this file are subject to the terms of the 54520Snw141292 * Common Development and Distribution License (the "License"). 64520Snw141292 * You may not use this file except in compliance with the License. 74520Snw141292 * 84520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94520Snw141292 * or http://www.opensolaris.org/os/licensing. 104520Snw141292 * See the License for the specific language governing permissions 114520Snw141292 * and limitations under the License. 124520Snw141292 * 134520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 144520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 164520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 174520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 184520Snw141292 * 194520Snw141292 * CDDL HEADER END 204520Snw141292 */ 214520Snw141292 /* 224520Snw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 234520Snw141292 * Use is subject to license terms. 244520Snw141292 */ 254520Snw141292 264520Snw141292 #pragma ident "%Z%%M% %I% %E% SMI" 274520Snw141292 284520Snw141292 /* 294520Snw141292 * Database related utility routines 304520Snw141292 */ 314520Snw141292 324520Snw141292 #include <stdio.h> 334520Snw141292 #include <stdlib.h> 344520Snw141292 #include <string.h> 354520Snw141292 #include <errno.h> 364520Snw141292 #include <sys/types.h> 374520Snw141292 #include <sys/stat.h> 384520Snw141292 #include <rpc/rpc.h> 394520Snw141292 #include <sys/sid.h> 404520Snw141292 #include <time.h> 414520Snw141292 #include <pwd.h> 424520Snw141292 #include <grp.h> 434884Sjp151216 #include <pthread.h> 444884Sjp151216 #include <assert.h> 454520Snw141292 464520Snw141292 #include "idmapd.h" 474520Snw141292 #include "adutils.h" 484520Snw141292 #include "string.h" 494520Snw141292 #include "idmap_priv.h" 504520Snw141292 514884Sjp151216 524520Snw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 534520Snw141292 sqlite_vm **, int *, int, const char ***); 544864Sbaban static idmap_retcode lookup_wksids_name2sid(const char *, char **, 554864Sbaban idmap_rid_t *, int *); 564520Snw141292 574520Snw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 584520Snw141292 594520Snw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 604520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 614520Snw141292 624520Snw141292 #define AVOID_NAMESERVICE(req)\ 634520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 644520Snw141292 654520Snw141292 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 664520Snw141292 674520Snw141292 #define LOCALRID_MIN 1000 684520Snw141292 694520Snw141292 704520Snw141292 714520Snw141292 typedef enum init_db_option { 724520Snw141292 FAIL_IF_CORRUPT = 0, 734520Snw141292 REMOVE_IF_CORRUPT = 1 744520Snw141292 } init_db_option_t; 754520Snw141292 764884Sjp151216 /* 774884Sjp151216 * Thread specfic data to hold the database handles so that the 784884Sjp151216 * databaes are not opened and closed for every request. It also 794884Sjp151216 * contains the sqlite busy handler structure. 804884Sjp151216 */ 814884Sjp151216 824884Sjp151216 struct idmap_busy { 834884Sjp151216 const char *name; 844884Sjp151216 const int *delays; 854884Sjp151216 int delay_size; 864884Sjp151216 int total; 874884Sjp151216 int sec; 884884Sjp151216 }; 894884Sjp151216 904884Sjp151216 914884Sjp151216 typedef struct idmap_tsd { 924884Sjp151216 sqlite *db_db; 934884Sjp151216 sqlite *cache_db; 944884Sjp151216 struct idmap_busy cache_busy; 954884Sjp151216 struct idmap_busy db_busy; 964884Sjp151216 } idmap_tsd_t; 974884Sjp151216 984884Sjp151216 994884Sjp151216 1004884Sjp151216 static const int cache_delay_table[] = 1014884Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 1024884Sjp151216 50, 50, 60, 70, 80, 90, 100}; 1034884Sjp151216 1044884Sjp151216 static const int db_delay_table[] = 1054884Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 1064884Sjp151216 1074884Sjp151216 1084884Sjp151216 static pthread_key_t idmap_tsd_key; 1094884Sjp151216 1104884Sjp151216 void 1114884Sjp151216 idmap_tsd_destroy(void *key) 1124884Sjp151216 { 1134884Sjp151216 1144884Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 1154884Sjp151216 if (tsd) { 1164884Sjp151216 if (tsd->db_db) 1174884Sjp151216 (void) sqlite_close(tsd->db_db); 1184884Sjp151216 if (tsd->cache_db) 1194884Sjp151216 (void) sqlite_close(tsd->cache_db); 1204884Sjp151216 free(tsd); 1214884Sjp151216 } 1224884Sjp151216 } 1234884Sjp151216 1244884Sjp151216 int 1254884Sjp151216 idmap_init_tsd_key(void) { 1264884Sjp151216 1274884Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 1284884Sjp151216 } 1294884Sjp151216 1304884Sjp151216 1314884Sjp151216 1324884Sjp151216 idmap_tsd_t * 1334884Sjp151216 idmap_get_tsd(void) 1344884Sjp151216 { 1354884Sjp151216 idmap_tsd_t *tsd; 1364884Sjp151216 1374884Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 1384884Sjp151216 /* No thread specific data so create it */ 1394884Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 1404884Sjp151216 /* Initialize thread specific data */ 1414884Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 1424884Sjp151216 /* save the trhread specific data */ 1434884Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 1444884Sjp151216 /* Can't store key */ 1454884Sjp151216 free(tsd); 1464884Sjp151216 tsd = NULL; 1474884Sjp151216 } 1484884Sjp151216 } else { 1494884Sjp151216 tsd = NULL; 1504884Sjp151216 } 1514884Sjp151216 } 1524884Sjp151216 1534884Sjp151216 return (tsd); 1544884Sjp151216 } 1554884Sjp151216 1564884Sjp151216 1574520Snw141292 1584520Snw141292 /* 1594520Snw141292 * Initialize 'dbname' using 'sql' 1604520Snw141292 */ 1614520Snw141292 static int 1624520Snw141292 init_db_instance(const char *dbname, const char *sql, init_db_option_t opt, 1634520Snw141292 int *new_db_created) 1644520Snw141292 { 1654520Snw141292 int rc = 0; 1664520Snw141292 int tries = 0; 1674520Snw141292 sqlite *db = NULL; 1684520Snw141292 char *str = NULL; 1694520Snw141292 1704520Snw141292 if (new_db_created != NULL) 1714520Snw141292 *new_db_created = 0; 1724520Snw141292 1734520Snw141292 db = sqlite_open(dbname, 0600, &str); 1744520Snw141292 while (db == NULL) { 1754520Snw141292 idmapdlog(LOG_ERR, 1764520Snw141292 "Error creating database %s (%s)", 1774520Snw141292 dbname, CHECK_NULL(str)); 1784520Snw141292 sqlite_freemem(str); 1794520Snw141292 if (opt == FAIL_IF_CORRUPT || opt != REMOVE_IF_CORRUPT || 1804520Snw141292 tries > 0) 1814520Snw141292 return (-1); 1824520Snw141292 1834520Snw141292 tries++; 1844520Snw141292 (void) unlink(dbname); 1854520Snw141292 db = sqlite_open(dbname, 0600, &str); 1864520Snw141292 } 1874520Snw141292 1884520Snw141292 sqlite_busy_timeout(db, 3000); 1894520Snw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &str); 1904520Snw141292 if (SQLITE_OK != rc) { 1914520Snw141292 idmapdlog(LOG_ERR, "Cannot begin database transaction (%s)", 1924520Snw141292 str); 1934520Snw141292 sqlite_freemem(str); 1944520Snw141292 sqlite_close(db); 1954520Snw141292 return (1); 1964520Snw141292 } 1974520Snw141292 1984520Snw141292 switch (sqlite_exec(db, sql, NULL, NULL, &str)) { 1994520Snw141292 case SQLITE_ERROR: 2004520Snw141292 /* 2014520Snw141292 * This is the normal situation: CREATE probably failed because tables 2024520Snw141292 * already exist. It may indicate an error in SQL as well, but we cannot 2034520Snw141292 * tell. 2044520Snw141292 */ 2054520Snw141292 sqlite_freemem(str); 2064520Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 2074520Snw141292 NULL, NULL, &str); 2084520Snw141292 break; 2094520Snw141292 case SQLITE_OK: 2104520Snw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", 2114520Snw141292 NULL, NULL, &str); 2124520Snw141292 idmapdlog(LOG_INFO, 2134520Snw141292 "Database created at %s", dbname); 2144520Snw141292 2154520Snw141292 if (new_db_created != NULL) 2164520Snw141292 *new_db_created = 1; 2174520Snw141292 break; 2184520Snw141292 default: 2194520Snw141292 idmapdlog(LOG_ERR, 2204520Snw141292 "Error initializing database %s (%s)", 2214520Snw141292 dbname, str); 2224520Snw141292 sqlite_freemem(str); 2234520Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 2244520Snw141292 NULL, NULL, &str); 2254520Snw141292 break; 2264520Snw141292 } 2274520Snw141292 2284520Snw141292 if (SQLITE_OK != rc) { 2294520Snw141292 /* this is bad - database may be left in a locked state */ 2304520Snw141292 idmapdlog(LOG_ERR, 2314520Snw141292 "Error closing transaction (%s)", str); 2324520Snw141292 sqlite_freemem(str); 2334520Snw141292 } 2344520Snw141292 2354520Snw141292 (void) sqlite_close(db); 2364520Snw141292 return (rc); 2374520Snw141292 } 2384520Snw141292 2394884Sjp151216 2404884Sjp151216 /* 2414884Sjp151216 * This is the SQLite database busy handler that retries the SQL 2424884Sjp151216 * operation until it is successful. 2434884Sjp151216 */ 2444884Sjp151216 int 2454884Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 2464884Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 2474884Sjp151216 { 2484884Sjp151216 struct idmap_busy *busy = arg; 2494884Sjp151216 int delay; 2504884Sjp151216 struct timespec rqtp; 2514884Sjp151216 2524884Sjp151216 if (count == 1) { 2534884Sjp151216 busy->total = 0; 2544884Sjp151216 busy->sec = 2; 2554884Sjp151216 } 2564884Sjp151216 if (busy->total > 1000 * busy->sec) { 2574884Sjp151216 idmapdlog(LOG_ERR, 2584884Sjp151216 "Thread %d waited %d sec for the %s database", 2594884Sjp151216 pthread_self(), busy->sec, busy->name); 2604884Sjp151216 busy->sec++; 2614884Sjp151216 } 2624884Sjp151216 2634884Sjp151216 if (count <= busy->delay_size) { 2644884Sjp151216 delay = busy->delays[count-1]; 2654884Sjp151216 } else { 2664884Sjp151216 delay = busy->delays[busy->delay_size - 1]; 2674884Sjp151216 } 2684884Sjp151216 busy->total += delay; 2694884Sjp151216 rqtp.tv_sec = 0; 2704884Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 2714884Sjp151216 (void) nanosleep(&rqtp, NULL); 2724884Sjp151216 return (1); 2734884Sjp151216 } 2744884Sjp151216 2754884Sjp151216 2764520Snw141292 /* 2774520Snw141292 * Get the database handle 2784520Snw141292 */ 2794520Snw141292 idmap_retcode 2804520Snw141292 get_db_handle(sqlite **db) { 2814520Snw141292 char *errmsg; 2824884Sjp151216 idmap_tsd_t *tsd; 2834520Snw141292 2844520Snw141292 /* 2854884Sjp151216 * Retrieve the db handle from thread-specific storage 2864520Snw141292 * If none exists, open and store in thread-specific storage. 2874520Snw141292 */ 2884884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 2894520Snw141292 idmapdlog(LOG_ERR, 2904884Sjp151216 "Error getting thread specific data for %s", 2914884Sjp151216 IDMAP_DBNAME); 2924884Sjp151216 return (IDMAP_ERR_MEMORY); 2934520Snw141292 } 2944884Sjp151216 2954884Sjp151216 if (tsd->db_db == NULL) { 2964884Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 2974884Sjp151216 if (tsd->db_db == NULL) { 2984884Sjp151216 idmapdlog(LOG_ERR, 2994884Sjp151216 "Error opening database %s (%s)", 3004884Sjp151216 IDMAP_DBNAME, CHECK_NULL(errmsg)); 3014884Sjp151216 sqlite_freemem(errmsg); 3024884Sjp151216 return (IDMAP_ERR_INTERNAL); 3034884Sjp151216 } 3044884Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 3054884Sjp151216 tsd->db_busy.delays = db_delay_table; 3064884Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 3074884Sjp151216 sizeof (int); 3084884Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 3094884Sjp151216 &tsd->db_busy); 3104884Sjp151216 } 3114884Sjp151216 *db = tsd->db_db; 3124520Snw141292 return (IDMAP_SUCCESS); 3134520Snw141292 } 3144520Snw141292 3154520Snw141292 /* 3164520Snw141292 * Get the cache handle 3174520Snw141292 */ 3184520Snw141292 idmap_retcode 3194884Sjp151216 get_cache_handle(sqlite **cache) { 3204520Snw141292 char *errmsg; 3214884Sjp151216 idmap_tsd_t *tsd; 3224520Snw141292 3234520Snw141292 /* 3244884Sjp151216 * Retrieve the db handle from thread-specific storage 3254520Snw141292 * If none exists, open and store in thread-specific storage. 3264520Snw141292 */ 3274884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 3284520Snw141292 idmapdlog(LOG_ERR, 3294884Sjp151216 "Error getting thread specific data for %s", 3304884Sjp151216 IDMAP_DBNAME); 3314884Sjp151216 return (IDMAP_ERR_MEMORY); 3324520Snw141292 } 3334884Sjp151216 3344884Sjp151216 if (tsd->cache_db == NULL) { 3354884Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 3364884Sjp151216 if (tsd->cache_db == NULL) { 3374884Sjp151216 idmapdlog(LOG_ERR, 3384884Sjp151216 "Error opening database %s (%s)", 3394884Sjp151216 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 3404884Sjp151216 sqlite_freemem(errmsg); 3414884Sjp151216 return (IDMAP_ERR_INTERNAL); 3424884Sjp151216 } 3434884Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 3444884Sjp151216 tsd->cache_busy.delays = cache_delay_table; 3454884Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 3464884Sjp151216 sizeof (int); 3474884Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 3484884Sjp151216 &tsd->cache_busy); 3494884Sjp151216 } 3504884Sjp151216 *cache = tsd->cache_db; 3514520Snw141292 return (IDMAP_SUCCESS); 3524520Snw141292 } 3534520Snw141292 3544520Snw141292 #define CACHE_SQL\ 3554520Snw141292 "CREATE TABLE idmap_cache ("\ 3564520Snw141292 " sidprefix TEXT,"\ 3574520Snw141292 " rid INTEGER,"\ 3584520Snw141292 " windomain TEXT,"\ 3594520Snw141292 " winname TEXT,"\ 3604520Snw141292 " pid INTEGER,"\ 3614520Snw141292 " unixname TEXT,"\ 3624520Snw141292 " is_user INTEGER,"\ 3634520Snw141292 " w2u INTEGER,"\ 3644520Snw141292 " u2w INTEGER,"\ 3654520Snw141292 " expiration INTEGER"\ 3664520Snw141292 ");"\ 3674520Snw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache"\ 3684520Snw141292 " (sidprefix, rid, w2u);"\ 3694520Snw141292 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache"\ 3704520Snw141292 " (pid, is_user, u2w);"\ 3714520Snw141292 "CREATE TABLE name_cache ("\ 3724520Snw141292 " sidprefix TEXT,"\ 3734520Snw141292 " rid INTEGER,"\ 3744520Snw141292 " name TEXT,"\ 3754520Snw141292 " domain TEXT,"\ 3764520Snw141292 " type INTEGER,"\ 3774520Snw141292 " expiration INTEGER"\ 3784520Snw141292 ");"\ 3794520Snw141292 "CREATE UNIQUE INDEX name_cache_sid ON name_cache"\ 3804520Snw141292 " (sidprefix, rid);" 3814520Snw141292 3824520Snw141292 #define DB_SQL\ 3834520Snw141292 "CREATE TABLE namerules ("\ 3844520Snw141292 " is_user INTEGER NOT NULL,"\ 3854520Snw141292 " windomain TEXT,"\ 3864520Snw141292 " winname TEXT NOT NULL,"\ 3874520Snw141292 " is_nt4 INTEGER NOT NULL,"\ 3884520Snw141292 " unixname NOT NULL,"\ 3894520Snw141292 " w2u_order INTEGER,"\ 3904520Snw141292 " u2w_order INTEGER"\ 3914520Snw141292 ");"\ 3924520Snw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules"\ 3934520Snw141292 " (winname, windomain, is_user, w2u_order);"\ 3944520Snw141292 "CREATE UNIQUE INDEX namerules_u2w ON namerules"\ 3954520Snw141292 " (unixname, is_user, u2w_order);" 3964520Snw141292 3974520Snw141292 /* 3984520Snw141292 * Initialize cache and db 3994520Snw141292 */ 4004520Snw141292 int 4014520Snw141292 init_dbs() { 4024520Snw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 4034520Snw141292 if (init_db_instance(IDMAP_DBNAME, DB_SQL, FAIL_IF_CORRUPT, NULL) < 0) 4044520Snw141292 return (-1); 4054520Snw141292 4064520Snw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 4074520Snw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_SQL, REMOVE_IF_CORRUPT, 4084520Snw141292 &_idmapdstate.new_eph_db) < 0) 4094520Snw141292 return (-1); 4104520Snw141292 4114520Snw141292 return (0); 4124520Snw141292 } 4134520Snw141292 4144520Snw141292 /* 4154520Snw141292 * Finalize databases 4164520Snw141292 */ 4174520Snw141292 void 4184520Snw141292 fini_dbs() { 4194520Snw141292 } 4204520Snw141292 4214520Snw141292 /* 4224520Snw141292 * This table is a listing of status codes that will returned to the 4234520Snw141292 * client when a SQL command fails with the corresponding error message. 4244520Snw141292 */ 4254520Snw141292 static msg_table_t sqlmsgtable[] = { 4264864Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 4274520Snw141292 "columns unixname, is_user, u2w_order are not unique"}, 4284864Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 4294520Snw141292 "columns winname, windomain, is_user, w2u_order are not unique"}, 4304520Snw141292 {-1, NULL} 4314520Snw141292 }; 4324520Snw141292 4334520Snw141292 /* 4344520Snw141292 * idmapd's version of string2stat to map SQLite messages to 4354520Snw141292 * status codes 4364520Snw141292 */ 4374520Snw141292 idmap_retcode 4384520Snw141292 idmapd_string2stat(const char *msg) { 4394520Snw141292 int i; 4404520Snw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 4414520Snw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 4424520Snw141292 return (sqlmsgtable[i].retcode); 4434520Snw141292 } 4444520Snw141292 return (IDMAP_ERR_OTHER); 4454520Snw141292 } 4464520Snw141292 4474520Snw141292 /* 4484520Snw141292 * Execute the given SQL statment without using any callbacks 4494520Snw141292 */ 4504520Snw141292 idmap_retcode 4514520Snw141292 sql_exec_no_cb(sqlite *db, char *sql) { 4524520Snw141292 char *errmsg = NULL; 4534884Sjp151216 int r; 4544520Snw141292 idmap_retcode retcode; 4554520Snw141292 4564884Sjp151216 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 4574884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 4584520Snw141292 4594520Snw141292 if (r != SQLITE_OK) { 4604520Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 4614520Snw141292 sql, CHECK_NULL(errmsg)); 4624884Sjp151216 retcode = idmapd_string2stat(errmsg); 4634864Sbaban if (errmsg != NULL) 4644520Snw141292 sqlite_freemem(errmsg); 4654520Snw141292 return (retcode); 4664520Snw141292 } 4674520Snw141292 4684520Snw141292 return (IDMAP_SUCCESS); 4694520Snw141292 } 4704520Snw141292 4714520Snw141292 /* 4724520Snw141292 * Generate expression that can be used in WHERE statements. 4734520Snw141292 * Examples: 4744520Snw141292 * <prefix> <col> <op> <value> <suffix> 4754520Snw141292 * "" "unixuser" "=" "foo" "AND" 4764520Snw141292 */ 4774520Snw141292 idmap_retcode 4784520Snw141292 gen_sql_expr_from_utf8str(const char *prefix, const char *col, 479*5064Sdm199847 const char *op, char *value, 4804520Snw141292 const char *suffix, char **out) { 4814520Snw141292 if (out == NULL) 4824520Snw141292 return (IDMAP_ERR_ARG); 4834520Snw141292 4844520Snw141292 if (value == NULL) 4854520Snw141292 return (IDMAP_SUCCESS); 4864520Snw141292 4874520Snw141292 if (prefix == NULL) 4884520Snw141292 prefix = ""; 4894520Snw141292 if (suffix == NULL) 4904520Snw141292 suffix = ""; 4914520Snw141292 4924520Snw141292 *out = sqlite_mprintf("%s %s %s %Q %s", 493*5064Sdm199847 prefix, col, op, value, suffix); 4944520Snw141292 if (*out == NULL) 4954520Snw141292 return (IDMAP_ERR_MEMORY); 4964520Snw141292 return (IDMAP_SUCCESS); 4974520Snw141292 } 4984520Snw141292 4994520Snw141292 /* 5004520Snw141292 * Generate and execute SQL statement for LIST RPC calls 5014520Snw141292 */ 5024520Snw141292 idmap_retcode 5034520Snw141292 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 5044520Snw141292 list_svc_cb cb, void *result) { 5054520Snw141292 list_cb_data_t cb_data; 5064520Snw141292 char *errmsg = NULL; 5074884Sjp151216 int r; 5084520Snw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 5094520Snw141292 5104520Snw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 5114520Snw141292 cb_data.result = result; 5124520Snw141292 cb_data.limit = limit; 5134520Snw141292 5144884Sjp151216 5154884Sjp151216 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 5164884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 5174884Sjp151216 switch (r) { 5184884Sjp151216 case SQLITE_OK: 5194884Sjp151216 retcode = IDMAP_SUCCESS; 5204884Sjp151216 break; 5214884Sjp151216 5224884Sjp151216 default: 5234884Sjp151216 retcode = IDMAP_ERR_INTERNAL; 5244884Sjp151216 idmapdlog(LOG_ERR, 5254884Sjp151216 "Database error during %s (%s)", 5264884Sjp151216 sql, CHECK_NULL(errmsg)); 5274884Sjp151216 break; 5284520Snw141292 } 5294864Sbaban if (errmsg != NULL) 5304520Snw141292 sqlite_freemem(errmsg); 5314520Snw141292 return (retcode); 5324520Snw141292 } 5334520Snw141292 5344520Snw141292 /* 5354520Snw141292 * This routine is called by callbacks that process the results of 5364520Snw141292 * LIST RPC calls to validate data and to allocate memory for 5374520Snw141292 * the result array. 5384520Snw141292 */ 5394520Snw141292 idmap_retcode 5404520Snw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 5414520Snw141292 int ncol, uchar_t **list, size_t valsize) { 5424520Snw141292 size_t nsize; 5434520Snw141292 void *tmplist; 5444520Snw141292 5454520Snw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 5464520Snw141292 return (IDMAP_NEXT); 5474520Snw141292 5484520Snw141292 if (argc < ncol || argv == NULL) { 5494520Snw141292 idmapdlog(LOG_ERR, "Invalid data"); 5504520Snw141292 return (IDMAP_ERR_INTERNAL); 5514520Snw141292 } 5524520Snw141292 5534520Snw141292 /* alloc in bulk to reduce number of reallocs */ 5544520Snw141292 if (cb_data->next >= cb_data->len) { 5554520Snw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 5564520Snw141292 tmplist = realloc(*list, nsize); 5574520Snw141292 if (tmplist == NULL) { 5584520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 5594520Snw141292 return (IDMAP_ERR_MEMORY); 5604520Snw141292 } 5614520Snw141292 *list = tmplist; 5624520Snw141292 (void) memset(*list + (cb_data->len * valsize), 0, 5634520Snw141292 SIZE_INCR * valsize); 5644520Snw141292 cb_data->len += SIZE_INCR; 5654520Snw141292 } 5664520Snw141292 return (IDMAP_SUCCESS); 5674520Snw141292 } 5684520Snw141292 5694520Snw141292 static idmap_retcode 5704520Snw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 5714520Snw141292 int direction, int *w2u_order, int *u2w_order) { 5724520Snw141292 5734520Snw141292 *w2u_order = 0; 5744520Snw141292 *u2w_order = 0; 5754520Snw141292 5764520Snw141292 /* 5774520Snw141292 * Windows to UNIX lookup order: 5784520Snw141292 * 1. winname@domain (or winname) to "" 5794520Snw141292 * 2. winname@domain (or winname) to unixname 5804520Snw141292 * 3. winname@* to "" 5814520Snw141292 * 4. winname@* to unixname 5824520Snw141292 * 5. *@domain (or *) to * 5834520Snw141292 * 6. *@domain (or *) to "" 5844520Snw141292 * 7. *@domain (or *) to unixname 5854520Snw141292 * 8. *@* to * 5864520Snw141292 * 9. *@* to "" 5874520Snw141292 * 10. *@* to unixname 5884520Snw141292 * 5894520Snw141292 * winname is a special case of winname@domain when domain is the 5904520Snw141292 * default domain. Similarly * is a special case of *@domain when 5914520Snw141292 * domain is the default domain. 5924520Snw141292 * 5934520Snw141292 * Note that "" has priority over specific names because "" inhibits 5944520Snw141292 * mappings and traditionally deny rules always had higher priority. 5954520Snw141292 */ 5964644Sbaban if (direction != IDMAP_DIRECTION_U2W) { 5974644Sbaban /* bi-directional or from windows to unix */ 5984520Snw141292 if (winname == NULL) 5994520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6004520Snw141292 else if (unixname == NULL) 6014520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6024520Snw141292 else if (EMPTY_NAME(winname)) 6034520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6044520Snw141292 else if (*winname == '*' && windomain && *windomain == '*') { 6054520Snw141292 if (*unixname == '*') 6064520Snw141292 *w2u_order = 8; 6074520Snw141292 else if (EMPTY_NAME(unixname)) 6084520Snw141292 *w2u_order = 9; 6094520Snw141292 else /* unixname == name */ 6104520Snw141292 *w2u_order = 10; 6114520Snw141292 } else if (*winname == '*') { 6124520Snw141292 if (*unixname == '*') 6134520Snw141292 *w2u_order = 5; 6144520Snw141292 else if (EMPTY_NAME(unixname)) 6154520Snw141292 *w2u_order = 6; 6164520Snw141292 else /* name */ 6174520Snw141292 *w2u_order = 7; 6184864Sbaban } else if (windomain != NULL && *windomain == '*') { 6194520Snw141292 /* winname == name */ 6204520Snw141292 if (*unixname == '*') 6214520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6224520Snw141292 else if (EMPTY_NAME(unixname)) 6234520Snw141292 *w2u_order = 3; 6244520Snw141292 else /* name */ 6254520Snw141292 *w2u_order = 4; 6264520Snw141292 } else { 6274520Snw141292 /* winname == name && windomain == null or name */ 6284520Snw141292 if (*unixname == '*') 6294520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6304520Snw141292 else if (EMPTY_NAME(unixname)) 6314520Snw141292 *w2u_order = 1; 6324520Snw141292 else /* name */ 6334520Snw141292 *w2u_order = 2; 6344520Snw141292 } 6354520Snw141292 } 6364520Snw141292 6374520Snw141292 /* 6384520Snw141292 * 1. unixname to "" 6394520Snw141292 * 2. unixname to winname@domain (or winname) 6404520Snw141292 * 3. * to *@domain (or *) 6414520Snw141292 * 4. * to "" 6424520Snw141292 * 5. * to winname@domain (or winname) 6434520Snw141292 */ 6444644Sbaban if (direction != IDMAP_DIRECTION_W2U) { 6454644Sbaban /* bi-directional or from unix to windows */ 6464520Snw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 6474520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6484520Snw141292 else if (winname == NULL) 6494520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6504864Sbaban else if (windomain != NULL && *windomain == '*') 6514644Sbaban return (IDMAP_ERR_U2W_NAMERULE); 6524520Snw141292 else if (*unixname == '*') { 6534520Snw141292 if (*winname == '*') 6544520Snw141292 *u2w_order = 3; 6554520Snw141292 else if (EMPTY_NAME(winname)) 6564520Snw141292 *u2w_order = 4; 6574520Snw141292 else 6584520Snw141292 *u2w_order = 5; 6594520Snw141292 } else { 6604520Snw141292 if (*winname == '*') 6614520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6624520Snw141292 else if (EMPTY_NAME(winname)) 6634520Snw141292 *u2w_order = 1; 6644520Snw141292 else 6654520Snw141292 *u2w_order = 2; 6664520Snw141292 } 6674520Snw141292 } 6684520Snw141292 return (IDMAP_SUCCESS); 6694520Snw141292 } 6704520Snw141292 6714520Snw141292 /* 6724520Snw141292 * Generate and execute SQL statement to add name-based mapping rule 6734520Snw141292 */ 6744520Snw141292 idmap_retcode 6754520Snw141292 add_namerule(sqlite *db, idmap_namerule *rule) { 6764520Snw141292 char *sql = NULL; 6774520Snw141292 idmap_stat retcode; 678*5064Sdm199847 char *dom = NULL; 6794520Snw141292 int w2u_order, u2w_order; 6804520Snw141292 char w2ubuf[11], u2wbuf[11]; 6814520Snw141292 682*5064Sdm199847 retcode = get_namerule_order(rule->winname, rule->windomain, 683*5064Sdm199847 rule->unixname, rule->direction, &w2u_order, &u2w_order); 6844520Snw141292 if (retcode != IDMAP_SUCCESS) 6854520Snw141292 goto out; 6864520Snw141292 6874520Snw141292 if (w2u_order) 6884520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 6894520Snw141292 if (u2w_order) 6904520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 6914520Snw141292 6924864Sbaban /* 6934864Sbaban * For the triggers on namerules table to work correctly: 6944864Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 6954864Sbaban * 2) Use "" instead of NULL for "no domain" 6964864Sbaban */ 6974864Sbaban 698*5064Sdm199847 if (rule->windomain != NULL) 699*5064Sdm199847 dom = rule->windomain; 700*5064Sdm199847 else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL) 7014864Sbaban == IDMAP_SUCCESS) { 7024864Sbaban /* well-known SIDs don't need domain */ 7034864Sbaban dom = ""; 7044864Sbaban } 7054520Snw141292 7064520Snw141292 RDLOCK_CONFIG(); 7074864Sbaban if (dom == NULL) { 7084864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain) 7094864Sbaban dom = _idmapdstate.cfg->pgcfg.mapping_domain; 7104864Sbaban else 7114864Sbaban dom = ""; 7124864Sbaban } 7134884Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 7144520Snw141292 "(is_user, windomain, winname, is_nt4, " 7154520Snw141292 "unixname, w2u_order, u2w_order) " 7164520Snw141292 "VALUES(%d, %Q, %Q, %d, %Q, %q, %q);", 7174520Snw141292 rule->is_user?1:0, 7184520Snw141292 dom, 719*5064Sdm199847 rule->winname, rule->is_nt4?1:0, 720*5064Sdm199847 rule->unixname, 7214520Snw141292 w2u_order?w2ubuf:NULL, 7224520Snw141292 u2w_order?u2wbuf:NULL); 7234520Snw141292 UNLOCK_CONFIG(); 7244520Snw141292 7254520Snw141292 if (sql == NULL) { 7264520Snw141292 retcode = IDMAP_ERR_INTERNAL; 7274520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7284520Snw141292 goto out; 7294520Snw141292 } 7304520Snw141292 7314520Snw141292 retcode = sql_exec_no_cb(db, sql); 7324520Snw141292 7334520Snw141292 if (retcode == IDMAP_ERR_OTHER) 7344520Snw141292 retcode = IDMAP_ERR_CFG; 7354520Snw141292 7364520Snw141292 out: 7374864Sbaban if (sql != NULL) 7384520Snw141292 sqlite_freemem(sql); 7394520Snw141292 return (retcode); 7404520Snw141292 } 7414520Snw141292 7424520Snw141292 /* 7434520Snw141292 * Flush name-based mapping rules 7444520Snw141292 */ 7454520Snw141292 idmap_retcode 7464520Snw141292 flush_namerules(sqlite *db, bool_t is_user) { 7474520Snw141292 char *sql = NULL; 7484520Snw141292 idmap_stat retcode; 7494520Snw141292 7504520Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 7514520Snw141292 "is_user = %d;", is_user?1:0); 7524520Snw141292 7534520Snw141292 if (sql == NULL) { 7544520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7554520Snw141292 return (IDMAP_ERR_MEMORY); 7564520Snw141292 } 7574520Snw141292 7584520Snw141292 retcode = sql_exec_no_cb(db, sql); 7594520Snw141292 7604520Snw141292 sqlite_freemem(sql); 7614520Snw141292 return (retcode); 7624520Snw141292 } 7634520Snw141292 7644520Snw141292 /* 7654520Snw141292 * Generate and execute SQL statement to remove a name-based mapping rule 7664520Snw141292 */ 7674520Snw141292 idmap_retcode 7684520Snw141292 rm_namerule(sqlite *db, idmap_namerule *rule) { 7694520Snw141292 char *sql = NULL; 7704520Snw141292 idmap_stat retcode; 7714520Snw141292 char *s_windomain = NULL, *s_winname = NULL; 7724520Snw141292 char *s_unixname = NULL; 7734520Snw141292 char buf[80]; 7744520Snw141292 775*5064Sdm199847 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 776*5064Sdm199847 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 7774520Snw141292 return (IDMAP_SUCCESS); 7784520Snw141292 7794520Snw141292 if (rule->direction < 0) { 7804520Snw141292 buf[0] = 0; 7814644Sbaban } else if (rule->direction == IDMAP_DIRECTION_BI) { 7824520Snw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 7834520Snw141292 " AND u2w_order > 0"); 7844644Sbaban } else if (rule->direction == IDMAP_DIRECTION_W2U) { 7854520Snw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 7864520Snw141292 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 7874644Sbaban } else if (rule->direction == IDMAP_DIRECTION_U2W) { 7884520Snw141292 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 7894520Snw141292 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 7904520Snw141292 } 7914520Snw141292 7924520Snw141292 retcode = IDMAP_ERR_INTERNAL; 793*5064Sdm199847 if (!EMPTY_STRING(rule->windomain)) { 7944520Snw141292 if (gen_sql_expr_from_utf8str("AND", "windomain", "=", 795*5064Sdm199847 rule->windomain, "", &s_windomain) != IDMAP_SUCCESS) 7964520Snw141292 goto out; 7974520Snw141292 } 7984520Snw141292 799*5064Sdm199847 if (!EMPTY_STRING(rule->winname)) { 8004520Snw141292 if (gen_sql_expr_from_utf8str("AND", "winname", "=", 801*5064Sdm199847 rule->winname, "", &s_winname) != IDMAP_SUCCESS) 8024520Snw141292 goto out; 8034520Snw141292 } 8044520Snw141292 805*5064Sdm199847 if (!EMPTY_STRING(rule->unixname)) { 8064520Snw141292 if (gen_sql_expr_from_utf8str("AND", "unixname", "=", 807*5064Sdm199847 rule->unixname, "", &s_unixname) != IDMAP_SUCCESS) 8084520Snw141292 goto out; 8094520Snw141292 } 8104520Snw141292 8114520Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 8124520Snw141292 "is_user = %d %s %s %s %s;", 8134520Snw141292 rule->is_user?1:0, 8144520Snw141292 s_windomain?s_windomain:"", 8154520Snw141292 s_winname?s_winname:"", 8164520Snw141292 s_unixname?s_unixname:"", 8174520Snw141292 buf); 8184520Snw141292 8194520Snw141292 if (sql == NULL) { 8204520Snw141292 retcode = IDMAP_ERR_INTERNAL; 8214520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 8224520Snw141292 goto out; 8234520Snw141292 } 8244520Snw141292 8254520Snw141292 retcode = sql_exec_no_cb(db, sql); 8264520Snw141292 8274520Snw141292 out: 8284864Sbaban if (s_windomain != NULL) 8294520Snw141292 sqlite_freemem(s_windomain); 8304864Sbaban if (s_winname != NULL) 8314520Snw141292 sqlite_freemem(s_winname); 8324864Sbaban if (s_unixname != NULL) 8334520Snw141292 sqlite_freemem(s_unixname); 8344864Sbaban if (sql != NULL) 8354520Snw141292 sqlite_freemem(sql); 8364520Snw141292 return (retcode); 8374520Snw141292 } 8384520Snw141292 8394520Snw141292 /* 8404520Snw141292 * Compile the given SQL query and step just once. 8414520Snw141292 * 8424520Snw141292 * Input: 8434520Snw141292 * db - db handle 8444520Snw141292 * sql - SQL statement 8454520Snw141292 * 8464520Snw141292 * Output: 8474520Snw141292 * vm - virtual SQL machine 8484520Snw141292 * ncol - number of columns in the result 8494520Snw141292 * values - column values 8504520Snw141292 * 8514520Snw141292 * Return values: 8524520Snw141292 * IDMAP_SUCCESS 8534520Snw141292 * IDMAP_ERR_NOTFOUND 8544520Snw141292 * IDMAP_ERR_INTERNAL 8554520Snw141292 */ 8564520Snw141292 8574520Snw141292 static idmap_retcode 8584520Snw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 8594520Snw141292 int reqcol, const char ***values) { 8604520Snw141292 char *errmsg = NULL; 8614884Sjp151216 int r; 8624884Sjp151216 8634884Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 8644520Snw141292 idmapdlog(LOG_ERR, 8654520Snw141292 "Database error during %s (%s)", 8664520Snw141292 sql, CHECK_NULL(errmsg)); 8674520Snw141292 sqlite_freemem(errmsg); 8684520Snw141292 return (IDMAP_ERR_INTERNAL); 8694520Snw141292 } 8704520Snw141292 8714884Sjp151216 r = sqlite_step(*vm, ncol, values, NULL); 8724884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 8734884Sjp151216 8744884Sjp151216 if (r == SQLITE_ROW) { 8754864Sbaban if (ncol != NULL && *ncol < reqcol) { 8764520Snw141292 (void) sqlite_finalize(*vm, NULL); 8774520Snw141292 *vm = NULL; 8784520Snw141292 return (IDMAP_ERR_INTERNAL); 8794520Snw141292 } 8804520Snw141292 /* Caller will call finalize after using the results */ 8814520Snw141292 return (IDMAP_SUCCESS); 8824520Snw141292 } else if (r == SQLITE_DONE) { 8834520Snw141292 (void) sqlite_finalize(*vm, NULL); 8844520Snw141292 *vm = NULL; 8854520Snw141292 return (IDMAP_ERR_NOTFOUND); 8864520Snw141292 } 8874520Snw141292 8884520Snw141292 (void) sqlite_finalize(*vm, &errmsg); 8894520Snw141292 *vm = NULL; 8904520Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 8914884Sjp151216 sql, CHECK_NULL(errmsg)); 8924520Snw141292 sqlite_freemem(errmsg); 8934520Snw141292 return (IDMAP_ERR_INTERNAL); 8944520Snw141292 } 8954520Snw141292 8964864Sbaban /* 8974864Sbaban * Table for well-known SIDs. 8984864Sbaban * 8994864Sbaban * Background: 9004864Sbaban * 9014864Sbaban * These well-known principals are stored (as of Windows Server 2003) under: 9024864Sbaban * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 9034864Sbaban * They belong to objectClass "foreignSecurityPrincipal". They don't have 9044864Sbaban * "samAccountName" nor "userPrincipalName" attributes. Their names are 9054864Sbaban * available in "cn" and "name" attributes. Some of these principals have a 9064864Sbaban * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 9074864Sbaban * these duplicate entries have the stringified SID in the "name" and "cn" 9084864Sbaban * attributes instead of the actual name. 9094864Sbaban * 9104864Sbaban * These principals remain constant across all operating systems. Using 9114864Sbaban * a hard-coded table here improves performance and avoids additional 9124864Sbaban * complexity in the AD lookup code in adutils.c 9134864Sbaban * 9144864Sbaban * Currently we don't support localization of well-known SID names, 9154864Sbaban * unlike Windows. 9164864Sbaban * 9174864Sbaban * Note that other well-known SIDs (i.e. S-1-5-<domain>-<w-k RID> and 9184864Sbaban * S-1-5-32-<w-k RID>) are not stored here because AD does have normal 9194864Sbaban * user/group objects for these objects and can be looked up using the 9204864Sbaban * existing AD lookup code. 9214864Sbaban */ 9224864Sbaban static wksids_table_t wksids[] = { 9234864Sbaban {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 9244864Sbaban {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 9254864Sbaban {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 9264864Sbaban {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 9274864Sbaban {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 9284864Sbaban {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 9294864Sbaban {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 9304864Sbaban {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 9314864Sbaban {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 9324864Sbaban {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 9334864Sbaban {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 9344864Sbaban {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 9354864Sbaban {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 9364864Sbaban {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 9374864Sbaban {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 9384864Sbaban {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 9394864Sbaban {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 9404864Sbaban {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 9414864Sbaban {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 9424864Sbaban {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 9434864Sbaban {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 9444864Sbaban {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 9454864Sbaban {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 9464864Sbaban {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 9474864Sbaban {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 9484864Sbaban {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 9494864Sbaban {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 9504520Snw141292 }; 9514520Snw141292 9524520Snw141292 static idmap_retcode 9534520Snw141292 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) { 9544520Snw141292 int i; 9554864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 9564864Sbaban if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 9574864Sbaban (strcasecmp(wksids[i].sidprefix, 9584864Sbaban req->id1.idmap_id_u.sid.prefix) == 0)) { 9594864Sbaban 9604864Sbaban if (wksids[i].pid == SENTINEL_PID) 9614864Sbaban /* Not mapped, break */ 9624864Sbaban break; 9634864Sbaban else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 9644864Sbaban continue; 9654864Sbaban 9664520Snw141292 switch (req->id2.idtype) { 9674520Snw141292 case IDMAP_UID: 9684864Sbaban if (wksids[i].is_user == 0) 9694864Sbaban continue; 9704864Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 9714864Sbaban res->direction = wksids[i].direction; 9724520Snw141292 return (IDMAP_SUCCESS); 9734520Snw141292 case IDMAP_GID: 9744864Sbaban if (wksids[i].is_user == 1) 9754864Sbaban continue; 9764864Sbaban res->id.idmap_id_u.gid = wksids[i].pid; 9774864Sbaban res->direction = wksids[i].direction; 9784520Snw141292 return (IDMAP_SUCCESS); 9794520Snw141292 case IDMAP_POSIXID: 9804864Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 9814864Sbaban res->id.idtype = (!wksids[i].is_user)? 9824520Snw141292 IDMAP_GID:IDMAP_UID; 9834864Sbaban res->direction = wksids[i].direction; 9844520Snw141292 return (IDMAP_SUCCESS); 9854520Snw141292 default: 9864520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 9874520Snw141292 } 9884520Snw141292 } 9894520Snw141292 } 9904520Snw141292 return (IDMAP_ERR_NOTFOUND); 9914520Snw141292 } 9924520Snw141292 9934520Snw141292 static idmap_retcode 9944520Snw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) { 9954520Snw141292 int i; 9964864Sbaban if (req->id2.idtype != IDMAP_SID) 9974864Sbaban return (IDMAP_ERR_NOTSUPPORTED); 9984864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 9994864Sbaban if (wksids[i].pid == req->id1.idmap_id_u.uid && 10004864Sbaban wksids[i].is_user == is_user && 10014864Sbaban wksids[i].direction != IDMAP_DIRECTION_W2U) { 10024864Sbaban res->id.idmap_id_u.sid.rid = wksids[i].rid; 10034864Sbaban res->id.idmap_id_u.sid.prefix = 10044864Sbaban strdup(wksids[i].sidprefix); 10054864Sbaban if (res->id.idmap_id_u.sid.prefix == NULL) { 10064864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10074864Sbaban return (IDMAP_ERR_MEMORY); 10084520Snw141292 } 10094864Sbaban res->direction = wksids[i].direction; 10104864Sbaban return (IDMAP_SUCCESS); 10114864Sbaban } 10124864Sbaban } 10134864Sbaban return (IDMAP_ERR_NOTFOUND); 10144864Sbaban } 10154864Sbaban 10164864Sbaban static idmap_retcode 10174864Sbaban lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 10184864Sbaban int *type) { 10194864Sbaban int i; 10204864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10214864Sbaban if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 10224864Sbaban wksids[i].rid == rid) { 10234864Sbaban if ((*name = strdup(wksids[i].winname)) == NULL) { 10244864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10254864Sbaban return (IDMAP_ERR_MEMORY); 10264864Sbaban } 10274864Sbaban *type = (wksids[i].is_user)? 10284864Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 10294864Sbaban return (IDMAP_SUCCESS); 10304864Sbaban } 10314864Sbaban } 10324864Sbaban return (IDMAP_ERR_NOTFOUND); 10334864Sbaban } 10344864Sbaban 10354864Sbaban static idmap_retcode 10364864Sbaban lookup_wksids_name2sid(const char *name, char **sidprefix, idmap_rid_t *rid, 10374864Sbaban int *type) { 10384864Sbaban int i; 10394864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10404864Sbaban if (strcasecmp(wksids[i].winname, name) == 0) { 10414864Sbaban if (sidprefix != NULL && (*sidprefix = 10424864Sbaban strdup(wksids[i].sidprefix)) == NULL) { 10434864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10444864Sbaban return (IDMAP_ERR_MEMORY); 10454864Sbaban } 10464864Sbaban if (type != NULL) 10474864Sbaban *type = (wksids[i].is_user)? 10484864Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 10494864Sbaban if (rid != NULL) 10504864Sbaban *rid = wksids[i].rid; 10514864Sbaban return (IDMAP_SUCCESS); 10524520Snw141292 } 10534520Snw141292 } 10544520Snw141292 return (IDMAP_ERR_NOTFOUND); 10554520Snw141292 } 10564520Snw141292 10574520Snw141292 static idmap_retcode 10584520Snw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 10594520Snw141292 char *end; 10604520Snw141292 char *sql = NULL; 10614520Snw141292 const char **values; 10624520Snw141292 sqlite_vm *vm = NULL; 10634520Snw141292 int ncol, is_user; 10644520Snw141292 uid_t pid; 10654520Snw141292 time_t curtime, exp; 10664520Snw141292 idmap_retcode retcode; 10674520Snw141292 10684520Snw141292 /* Current time */ 10694520Snw141292 errno = 0; 10704520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 10714520Snw141292 idmapdlog(LOG_ERR, 10724520Snw141292 "Failed to get current time (%s)", 10734520Snw141292 strerror(errno)); 10744520Snw141292 retcode = IDMAP_ERR_INTERNAL; 10754520Snw141292 goto out; 10764520Snw141292 } 10774520Snw141292 10784520Snw141292 /* SQL to lookup the cache */ 10794520Snw141292 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 10804520Snw141292 "FROM idmap_cache WHERE " 10814520Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 10824520Snw141292 "(pid >= 2147483648 OR " 10834520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 10844520Snw141292 "expiration > %d));", 10854520Snw141292 req->id1.idmap_id_u.sid.prefix, 10864520Snw141292 req->id1.idmap_id_u.sid.rid, 10874520Snw141292 curtime); 10884520Snw141292 if (sql == NULL) { 10894520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 10904520Snw141292 retcode = IDMAP_ERR_MEMORY; 10914520Snw141292 goto out; 10924520Snw141292 } 10934520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 10944520Snw141292 sqlite_freemem(sql); 10954520Snw141292 10964520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 10974520Snw141292 goto out; 10984520Snw141292 } else if (retcode == IDMAP_SUCCESS) { 10994520Snw141292 /* sanity checks */ 11004520Snw141292 if (values[0] == NULL || values[1] == NULL) { 11014520Snw141292 retcode = IDMAP_ERR_CACHE; 11024520Snw141292 goto out; 11034520Snw141292 } 11044520Snw141292 11054520Snw141292 pid = strtoul(values[0], &end, 10); 11064520Snw141292 is_user = strncmp(values[1], "0", 2)?1:0; 11074520Snw141292 11084520Snw141292 /* 11094520Snw141292 * We may have an expired ephemeral mapping. Consider 11104520Snw141292 * the expired entry as valid if we are not going to 11114520Snw141292 * perform name-based mapping. But do not renew the 11124520Snw141292 * expiration. 11134520Snw141292 * If we will be doing name-based mapping then store the 11144520Snw141292 * ephemeral pid in the result so that we can use it 11154520Snw141292 * if we end up doing dynamic mapping again. 11164520Snw141292 */ 11174520Snw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 11184520Snw141292 !AVOID_NAMESERVICE(req)) { 11194864Sbaban if (IS_EPHEMERAL(pid) && values[2] != NULL) { 11204520Snw141292 exp = strtoll(values[2], &end, 10); 11214520Snw141292 if (exp && exp <= curtime) { 11224520Snw141292 /* Store the ephemeral pid */ 11234520Snw141292 res->id.idmap_id_u.uid = pid; 11244520Snw141292 res->id.idtype = is_user? 11254520Snw141292 IDMAP_UID:IDMAP_GID; 11264644Sbaban res->direction = IDMAP_DIRECTION_BI; 11274520Snw141292 req->direction |= is_user? 11284520Snw141292 _IDMAP_F_EXP_EPH_UID: 11294520Snw141292 _IDMAP_F_EXP_EPH_GID; 11304520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 11314520Snw141292 goto out; 11324520Snw141292 } 11334520Snw141292 } 11344520Snw141292 } 11354520Snw141292 11364520Snw141292 switch (req->id2.idtype) { 11374520Snw141292 case IDMAP_UID: 11384520Snw141292 if (!is_user) 11394520Snw141292 retcode = IDMAP_ERR_NOTUSER; 11404520Snw141292 else 11414520Snw141292 res->id.idmap_id_u.uid = pid; 11424520Snw141292 break; 11434520Snw141292 case IDMAP_GID: 11444520Snw141292 if (is_user) 11454520Snw141292 retcode = IDMAP_ERR_NOTGROUP; 11464520Snw141292 else 11474520Snw141292 res->id.idmap_id_u.gid = pid; 11484520Snw141292 break; 11494520Snw141292 case IDMAP_POSIXID: 11504520Snw141292 res->id.idmap_id_u.uid = pid; 11514520Snw141292 res->id.idtype = (is_user)?IDMAP_UID:IDMAP_GID; 11524520Snw141292 break; 11534520Snw141292 default: 11544520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 11554520Snw141292 break; 11564520Snw141292 } 11574520Snw141292 } 11584520Snw141292 11594520Snw141292 out: 11604520Snw141292 if (retcode == IDMAP_SUCCESS) { 11614864Sbaban if (values[4] != NULL) 11624520Snw141292 res->direction = 11634644Sbaban (strtol(values[4], &end, 10) == 0)? 11644644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 11654520Snw141292 else 11664644Sbaban res->direction = IDMAP_DIRECTION_W2U; 11674520Snw141292 11684864Sbaban if (values[3] != NULL) { 1169*5064Sdm199847 req->id2name = strdup(values[3]); 1170*5064Sdm199847 if (req->id2name == NULL) { 11714520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 11724520Snw141292 retcode = IDMAP_ERR_MEMORY; 11734520Snw141292 } 11744520Snw141292 } 11754520Snw141292 } 11764864Sbaban if (vm != NULL) 11774520Snw141292 (void) sqlite_finalize(vm, NULL); 11784520Snw141292 return (retcode); 11794520Snw141292 } 11804520Snw141292 11814520Snw141292 static idmap_retcode 11824864Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 11834520Snw141292 char **name, char **domain, int *type) { 11844520Snw141292 char *end; 11854520Snw141292 char *sql = NULL; 11864520Snw141292 const char **values; 11874520Snw141292 sqlite_vm *vm = NULL; 11884520Snw141292 int ncol; 11894520Snw141292 time_t curtime; 11904520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 11914520Snw141292 11924520Snw141292 /* Get current time */ 11934520Snw141292 errno = 0; 11944520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 11954520Snw141292 idmapdlog(LOG_ERR, 11964520Snw141292 "Failed to get current time (%s)", 11974520Snw141292 strerror(errno)); 11984520Snw141292 retcode = IDMAP_ERR_INTERNAL; 11994520Snw141292 goto out; 12004520Snw141292 } 12014520Snw141292 12024520Snw141292 /* SQL to lookup the cache */ 12034520Snw141292 sql = sqlite_mprintf("SELECT name, domain, type FROM name_cache WHERE " 12044520Snw141292 "sidprefix = %Q AND rid = %u AND " 12054520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 12064520Snw141292 "expiration > %d);", 12074520Snw141292 sidprefix, rid, curtime); 12084520Snw141292 if (sql == NULL) { 12094520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12104520Snw141292 retcode = IDMAP_ERR_MEMORY; 12114520Snw141292 goto out; 12124520Snw141292 } 12134520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 12144520Snw141292 sqlite_freemem(sql); 12154520Snw141292 12164520Snw141292 if (retcode == IDMAP_SUCCESS) { 12174864Sbaban if (type != NULL) { 12184520Snw141292 if (values[2] == NULL) { 12194520Snw141292 retcode = IDMAP_ERR_CACHE; 12204520Snw141292 goto out; 12214520Snw141292 } 12224520Snw141292 *type = strtol(values[2], &end, 10); 12234520Snw141292 } 12244520Snw141292 12254864Sbaban if (name != NULL && values[0] != NULL) { 12264520Snw141292 if ((*name = strdup(values[0])) == NULL) { 12274520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12284520Snw141292 retcode = IDMAP_ERR_MEMORY; 12294520Snw141292 goto out; 12304520Snw141292 } 12314520Snw141292 } 12324520Snw141292 12334864Sbaban if (domain != NULL && values[1] != NULL) { 12344520Snw141292 if ((*domain = strdup(values[1])) == NULL) { 12354864Sbaban if (name != NULL && *name) { 12364520Snw141292 free(*name); 12374520Snw141292 *name = NULL; 12384520Snw141292 } 12394520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12404520Snw141292 retcode = IDMAP_ERR_MEMORY; 12414520Snw141292 goto out; 12424520Snw141292 } 12434520Snw141292 } 12444520Snw141292 } 12454520Snw141292 12464520Snw141292 out: 12474864Sbaban if (vm != NULL) 12484520Snw141292 (void) sqlite_finalize(vm, NULL); 12494520Snw141292 return (retcode); 12504520Snw141292 } 12514520Snw141292 12524520Snw141292 static idmap_retcode 12534520Snw141292 verify_type(idmap_id_type idtype, int type, idmap_id_res *res) { 12544520Snw141292 switch (idtype) { 12554520Snw141292 case IDMAP_UID: 12564520Snw141292 if (type != _IDMAP_T_USER) 12574520Snw141292 return (IDMAP_ERR_NOTUSER); 12584520Snw141292 res->id.idtype = IDMAP_UID; 12594520Snw141292 break; 12604520Snw141292 case IDMAP_GID: 12614520Snw141292 if (type != _IDMAP_T_GROUP) 12624520Snw141292 return (IDMAP_ERR_NOTGROUP); 12634520Snw141292 res->id.idtype = IDMAP_GID; 12644520Snw141292 break; 12654520Snw141292 case IDMAP_POSIXID: 12664520Snw141292 if (type == _IDMAP_T_USER) 12674520Snw141292 res->id.idtype = IDMAP_UID; 12684520Snw141292 else if (type == _IDMAP_T_GROUP) 12694520Snw141292 res->id.idtype = IDMAP_GID; 12704520Snw141292 else 12714520Snw141292 return (IDMAP_ERR_SID); 12724520Snw141292 break; 12734520Snw141292 default: 12744520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 12754520Snw141292 } 12764520Snw141292 return (IDMAP_SUCCESS); 12774520Snw141292 } 12784520Snw141292 12794520Snw141292 /* 12804864Sbaban * Lookup sid to name locally 12814520Snw141292 */ 12824520Snw141292 static idmap_retcode 12834864Sbaban lookup_local_sid2name(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 12844520Snw141292 int type = -1; 12854520Snw141292 idmap_retcode retcode; 12864520Snw141292 char *sidprefix; 12874520Snw141292 idmap_rid_t rid; 12884520Snw141292 char *name = NULL, *domain = NULL; 12894520Snw141292 12904520Snw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 12914520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 12924520Snw141292 12934864Sbaban /* Lookup sids to name in well-known sids table */ 12944864Sbaban retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 12954864Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 12964864Sbaban goto out; 12974864Sbaban 12984520Snw141292 /* Lookup sid to name in cache */ 12994864Sbaban retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 13004520Snw141292 &domain, &type); 13014520Snw141292 if (retcode != IDMAP_SUCCESS) 13024520Snw141292 goto out; 13034520Snw141292 13044520Snw141292 out: 13054520Snw141292 if (retcode == IDMAP_SUCCESS) { 13064864Sbaban /* Verify that the sid type matches the request */ 13074864Sbaban retcode = verify_type(req->id2.idtype, type, res); 13084864Sbaban 13094520Snw141292 /* update state in 'req' */ 1310*5064Sdm199847 if (name != NULL) 1311*5064Sdm199847 req->id1name = name; 1312*5064Sdm199847 if (domain != NULL) 1313*5064Sdm199847 req->id1domain = domain; 13144520Snw141292 } else { 13154864Sbaban if (name != NULL) 13164520Snw141292 free(name); 13174864Sbaban if (domain != NULL) 13184520Snw141292 free(domain); 13194520Snw141292 } 13204520Snw141292 return (retcode); 13214520Snw141292 } 13224520Snw141292 13234520Snw141292 idmap_retcode 13244520Snw141292 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 13254520Snw141292 idmap_ids_res *result) { 13264520Snw141292 idmap_retcode retcode; 13274520Snw141292 int ret, i; 13284520Snw141292 int retries = 0; 13294520Snw141292 idmap_mapping *req; 13304520Snw141292 idmap_id_res *res; 13314520Snw141292 13324520Snw141292 if (state->ad_nqueries == 0) 13334520Snw141292 return (IDMAP_SUCCESS); 13344520Snw141292 13354520Snw141292 retry: 13364520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 13374520Snw141292 &state->ad_lookup); 13384520Snw141292 if (ret != 0) { 13394520Snw141292 idmapdlog(LOG_ERR, 13404520Snw141292 "Failed to create sid2name batch for AD lookup"); 13414520Snw141292 return (IDMAP_ERR_INTERNAL); 13424520Snw141292 } 13434520Snw141292 13444520Snw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 13454520Snw141292 req = &batch->idmap_mapping_batch_val[i]; 13464520Snw141292 res = &result->ids.ids_val[i]; 13474520Snw141292 13484520Snw141292 if (req->id1.idtype == IDMAP_SID && 13494520Snw141292 req->direction & _IDMAP_F_S2N_AD) { 13504864Sbaban if (retries == 0) 13514864Sbaban res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 13524864Sbaban else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 13534864Sbaban continue; 13544520Snw141292 retcode = idmap_sid2name_batch_add1( 13554520Snw141292 state->ad_lookup, 13564520Snw141292 req->id1.idmap_id_u.sid.prefix, 13574520Snw141292 &req->id1.idmap_id_u.sid.rid, 1358*5064Sdm199847 &req->id1name, 1359*5064Sdm199847 &req->id1domain, 13604520Snw141292 (int *)&res->id.idtype, 13614520Snw141292 &res->retcode); 13624520Snw141292 13634520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 13644520Snw141292 break; 13654520Snw141292 if (retcode != IDMAP_SUCCESS) 13664520Snw141292 goto out; 13674520Snw141292 } 13684520Snw141292 } 13694520Snw141292 13704520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 13714884Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 13724520Snw141292 else 13734520Snw141292 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 13744520Snw141292 13754520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 13764520Snw141292 goto retry; 13774520Snw141292 13784520Snw141292 return (retcode); 13794520Snw141292 13804520Snw141292 out: 13814520Snw141292 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 13824884Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 13834520Snw141292 return (retcode); 13844520Snw141292 } 13854520Snw141292 13864520Snw141292 idmap_retcode 13874520Snw141292 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 13884520Snw141292 idmap_id_res *res) { 13894520Snw141292 idmap_retcode retcode; 13904520Snw141292 13914520Snw141292 /* 13924520Snw141292 * The req->direction field is used to maintain state of the 13934520Snw141292 * sid2pid request. 13944520Snw141292 */ 13954520Snw141292 req->direction = _IDMAP_F_DONE; 13964520Snw141292 13974520Snw141292 if (req->id1.idmap_id_u.sid.prefix == NULL) { 13984520Snw141292 retcode = IDMAP_ERR_SID; 13994520Snw141292 goto out; 14004520Snw141292 } 14014520Snw141292 res->id.idtype = req->id2.idtype; 14024520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 14034520Snw141292 14044864Sbaban /* Lookup well-known sid to pid mapping */ 14054520Snw141292 retcode = lookup_wksids_sid2pid(req, res); 14064520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 14074520Snw141292 goto out; 14084520Snw141292 14094520Snw141292 /* Lookup sid to pid in cache */ 14104520Snw141292 retcode = lookup_cache_sid2pid(cache, req, res); 14114520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 14124520Snw141292 goto out; 14134520Snw141292 14144520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 14154520Snw141292 res->id.idmap_id_u.uid = SENTINEL_PID; 14164520Snw141292 goto out; 14174520Snw141292 } 14184520Snw141292 14194520Snw141292 /* 14204520Snw141292 * Failed to find non-expired entry in cache. Tell the caller 14214520Snw141292 * that we are not done yet. 14224520Snw141292 */ 14234520Snw141292 state->sid2pid_done = FALSE; 14244520Snw141292 14254520Snw141292 /* 14264520Snw141292 * Our next step is name-based mapping. To lookup name-based 14274520Snw141292 * mapping rules, we need the windows name and domain-name 14284520Snw141292 * associated with the SID. 14294520Snw141292 */ 14304520Snw141292 14314520Snw141292 /* 14324520Snw141292 * Check if we already have the name (i.e name2pid lookups) 14334520Snw141292 */ 1434*5064Sdm199847 if (req->id1name != NULL && 1435*5064Sdm199847 req->id1domain != NULL) { 14364520Snw141292 retcode = IDMAP_SUCCESS; 14374520Snw141292 req->direction |= _IDMAP_F_S2N_CACHE; 14384520Snw141292 goto out; 14394520Snw141292 } 14404520Snw141292 14414864Sbaban /* Lookup sid to winname@domain locally first */ 14424864Sbaban retcode = lookup_local_sid2name(cache, req, res); 14434864Sbaban if (retcode == IDMAP_SUCCESS) { 14444864Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 14454864Sbaban } else if (retcode == IDMAP_ERR_NOTFOUND) { 14464520Snw141292 /* Batch sid to name AD lookup request */ 14474520Snw141292 retcode = IDMAP_SUCCESS; 14484520Snw141292 req->direction |= _IDMAP_F_S2N_AD; 14494520Snw141292 state->ad_nqueries++; 14504520Snw141292 goto out; 14514520Snw141292 } 14524520Snw141292 14534520Snw141292 14544520Snw141292 out: 14554520Snw141292 res->retcode = idmap_stat4prot(retcode); 14564520Snw141292 return (retcode); 14574520Snw141292 } 14584520Snw141292 14594520Snw141292 /* 14604520Snw141292 * Generate SID using the following convention 14614520Snw141292 * <machine-sid-prefix>-<1000 + uid> 14624520Snw141292 * <machine-sid-prefix>-<2^31 + gid> 14634520Snw141292 */ 14644520Snw141292 static idmap_retcode 14654520Snw141292 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) { 14664520Snw141292 14674864Sbaban if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 14684520Snw141292 /* Skip 1000 UIDs */ 14694520Snw141292 if (is_user && req->id1.idmap_id_u.uid > 14704520Snw141292 (INT32_MAX - LOCALRID_MIN)) 14714864Sbaban return (IDMAP_ERR_NOMAPPING); 14724520Snw141292 14734520Snw141292 RDLOCK_CONFIG(); 14744520Snw141292 res->id.idmap_id_u.sid.prefix = 14754520Snw141292 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 14764520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 14774520Snw141292 UNLOCK_CONFIG(); 14784520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 14794520Snw141292 return (IDMAP_ERR_MEMORY); 14804520Snw141292 } 14814520Snw141292 UNLOCK_CONFIG(); 14824520Snw141292 res->id.idmap_id_u.sid.rid = 14834520Snw141292 (is_user)?req->id1.idmap_id_u.uid + LOCALRID_MIN: 14844520Snw141292 req->id1.idmap_id_u.gid + INT32_MAX + 1; 14854644Sbaban res->direction = IDMAP_DIRECTION_BI; 14864520Snw141292 14874520Snw141292 /* 14884520Snw141292 * Don't update name_cache because local sids don't have 14894520Snw141292 * valid windows names. 14904520Snw141292 * We mark the entry as being found in the namecache so that 14914520Snw141292 * the cache update routine doesn't update namecache. 14924520Snw141292 */ 14934520Snw141292 req->direction = _IDMAP_F_S2N_CACHE; 14944868Sbaban return (IDMAP_SUCCESS); 14954520Snw141292 } 14964520Snw141292 14974864Sbaban return (IDMAP_ERR_NOMAPPING); 14984520Snw141292 } 14994520Snw141292 15004520Snw141292 static idmap_retcode 15014520Snw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) { 15024520Snw141292 char *sidprefix; 15034520Snw141292 uint32_t rid; 15044520Snw141292 int s; 15054520Snw141292 15064520Snw141292 /* 15074520Snw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 15084520Snw141292 * GID = last RID - 2^31. 15094520Snw141292 */ 15104520Snw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 15114520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 15124520Snw141292 15134520Snw141292 RDLOCK_CONFIG(); 15144520Snw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid)? 15154520Snw141292 strcasecmp(sidprefix, 15164520Snw141292 _idmapdstate.cfg->pgcfg.machine_sid):1; 15174520Snw141292 UNLOCK_CONFIG(); 15184520Snw141292 15194520Snw141292 if (s == 0) { 15204520Snw141292 switch (req->id2.idtype) { 15214520Snw141292 case IDMAP_UID: 15224520Snw141292 if (rid > INT32_MAX) { 15234520Snw141292 return (IDMAP_ERR_NOTUSER); 15244520Snw141292 } else if (rid < LOCALRID_MIN) { 15254520Snw141292 return (IDMAP_ERR_NOTFOUND); 15264520Snw141292 } 15274520Snw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 15284520Snw141292 res->id.idtype = IDMAP_UID; 15294520Snw141292 break; 15304520Snw141292 case IDMAP_GID: 15314520Snw141292 if (rid <= INT32_MAX) { 15324520Snw141292 return (IDMAP_ERR_NOTGROUP); 15334520Snw141292 } 15344520Snw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 15354520Snw141292 res->id.idtype = IDMAP_GID; 15364520Snw141292 break; 15374520Snw141292 case IDMAP_POSIXID: 15384520Snw141292 if (rid > INT32_MAX) { 15394520Snw141292 res->id.idmap_id_u.gid = 15404520Snw141292 rid - INT32_MAX - 1; 15414520Snw141292 res->id.idtype = IDMAP_GID; 15424520Snw141292 } else if (rid < LOCALRID_MIN) { 15434520Snw141292 return (IDMAP_ERR_NOTFOUND); 15444520Snw141292 } else { 15454520Snw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 15464520Snw141292 res->id.idtype = IDMAP_UID; 15474520Snw141292 } 15484520Snw141292 break; 15494520Snw141292 default: 15504520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 15514520Snw141292 } 15524520Snw141292 return (IDMAP_SUCCESS); 15534520Snw141292 } 15544520Snw141292 15554520Snw141292 return (IDMAP_ERR_NOTFOUND); 15564520Snw141292 } 15574520Snw141292 15584520Snw141292 static idmap_retcode 15594520Snw141292 ns_lookup_byname(int is_user, const char *name, idmap_id_res *res) { 15604520Snw141292 struct passwd pwd; 15614520Snw141292 struct group grp; 15624520Snw141292 char buf[1024]; 15634520Snw141292 int errnum; 15644520Snw141292 const char *me = "ns_lookup_byname"; 15654520Snw141292 15664520Snw141292 if (is_user) { 15674520Snw141292 if (getpwnam_r(name, &pwd, buf, sizeof (buf)) == NULL) { 15684520Snw141292 errnum = errno; 15694520Snw141292 idmapdlog(LOG_WARNING, 15704520Snw141292 "%s: getpwnam_r(%s) failed (%s).", 15714520Snw141292 me, name, 15724520Snw141292 errnum?strerror(errnum):"not found"); 15734520Snw141292 if (errnum == 0) 15744520Snw141292 return (IDMAP_ERR_NOTFOUND); 15754520Snw141292 else 15764520Snw141292 return (IDMAP_ERR_INTERNAL); 15774520Snw141292 } 15784520Snw141292 res->id.idmap_id_u.uid = pwd.pw_uid; 15794520Snw141292 res->id.idtype = IDMAP_UID; 15804520Snw141292 } else { 15814520Snw141292 if (getgrnam_r(name, &grp, buf, sizeof (buf)) == NULL) { 15824520Snw141292 errnum = errno; 15834520Snw141292 idmapdlog(LOG_WARNING, 15844520Snw141292 "%s: getgrnam_r(%s) failed (%s).", 15854520Snw141292 me, name, 15864520Snw141292 errnum?strerror(errnum):"not found"); 15874520Snw141292 if (errnum == 0) 15884520Snw141292 return (IDMAP_ERR_NOTFOUND); 15894520Snw141292 else 15904520Snw141292 return (IDMAP_ERR_INTERNAL); 15914520Snw141292 } 15924520Snw141292 res->id.idmap_id_u.gid = grp.gr_gid; 15934520Snw141292 res->id.idtype = IDMAP_GID; 15944520Snw141292 } 15954520Snw141292 return (IDMAP_SUCCESS); 15964520Snw141292 } 15974520Snw141292 15984520Snw141292 /* 15994520Snw141292 * Name-based mapping 16004520Snw141292 * 16014520Snw141292 * Case 1: If no rule matches do ephemeral 16024520Snw141292 * 16034520Snw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 16044520Snw141292 * 16054520Snw141292 * Case 3: If rule matches and unixname is specified then lookup name 16064520Snw141292 * service using the unixname. If unixname not found then return no mapping. 16074520Snw141292 * 16084520Snw141292 * Case 4: If rule matches and unixname is * then lookup name service 16094520Snw141292 * using winname as the unixname. If unixname not found then process 16104520Snw141292 * other rules using the lookup order. If no other rule matches then do 16114520Snw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 16124520Snw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 16134520Snw141292 * instead of the default behaviour of doing ephemeral mapping. 16144520Snw141292 * 16154520Snw141292 * Example 1: 16164520Snw141292 * *@sfbay == * 16174520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16184520Snw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 16194520Snw141292 * 16204520Snw141292 * Example 2: 16214520Snw141292 * *@sfbay == * 16224520Snw141292 * *@sfbay => guest 16234520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16244520Snw141292 * the name service then foo@sfbay will be mapped to guest. 16254520Snw141292 * 16264520Snw141292 * Example 3: 16274520Snw141292 * *@sfbay == * 16284520Snw141292 * *@sfbay => "" 16294520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16304520Snw141292 * the name service then we will return no mapping for foo@sfbay. 16314520Snw141292 * 16324520Snw141292 */ 16334520Snw141292 static idmap_retcode 16344520Snw141292 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) { 16354520Snw141292 const char *unixname, *winname, *windomain; 16364520Snw141292 char *sql = NULL, *errmsg = NULL; 16374520Snw141292 idmap_retcode retcode; 16384520Snw141292 char *end; 16394520Snw141292 const char **values; 16404520Snw141292 sqlite_vm *vm = NULL; 16414884Sjp151216 int ncol, r, i, is_user; 16424520Snw141292 const char *me = "name_based_mapping_sid2pid"; 16434520Snw141292 1644*5064Sdm199847 winname = req->id1name; 1645*5064Sdm199847 windomain = req->id1domain; 16464520Snw141292 is_user = (res->id.idtype == IDMAP_UID)?1:0; 16474520Snw141292 16484520Snw141292 i = 0; 16494864Sbaban if (windomain == NULL) { 16504864Sbaban windomain = ""; 16514864Sbaban } else { 16524864Sbaban RDLOCK_CONFIG(); 16534864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 16544864Sbaban if (strcasecmp(_idmapdstate.cfg->pgcfg.mapping_domain, 16554864Sbaban windomain) == 0) 16564864Sbaban i = 1; 16574864Sbaban } 16584864Sbaban UNLOCK_CONFIG(); 16594520Snw141292 } 16604520Snw141292 16614520Snw141292 sql = sqlite_mprintf( 16624520Snw141292 "SELECT unixname, u2w_order FROM namerules WHERE " 16634520Snw141292 "w2u_order > 0 AND is_user = %d AND " 16644520Snw141292 "(winname = %Q OR winname = '*') AND " 16654520Snw141292 "(windomain = %Q OR windomain = '*' %s) " 16664520Snw141292 "ORDER BY w2u_order ASC;", 16674864Sbaban is_user, winname, 16684864Sbaban windomain, 16694864Sbaban i?"OR windomain ISNULL OR windomain = ''":""); 16704520Snw141292 if (sql == NULL) { 16714520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 16724520Snw141292 retcode = IDMAP_ERR_MEMORY; 16734520Snw141292 goto out; 16744520Snw141292 } 16754520Snw141292 16764520Snw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 16774520Snw141292 retcode = IDMAP_ERR_INTERNAL; 16784520Snw141292 idmapdlog(LOG_ERR, 16794520Snw141292 "%s: database error (%s)", 16804520Snw141292 me, CHECK_NULL(errmsg)); 16814520Snw141292 sqlite_freemem(errmsg); 16824520Snw141292 goto out; 16834520Snw141292 } 16844520Snw141292 16854884Sjp151216 for (; ; ) { 16864520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 16874884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 16884884Sjp151216 16894884Sjp151216 if (r == SQLITE_ROW) { 16904520Snw141292 if (ncol < 2) { 16914520Snw141292 retcode = IDMAP_ERR_INTERNAL; 16924520Snw141292 goto out; 16934520Snw141292 } 16944520Snw141292 if (values[0] == NULL) { 16954520Snw141292 retcode = IDMAP_ERR_INTERNAL; 16964520Snw141292 goto out; 16974520Snw141292 } 16984520Snw141292 16994520Snw141292 if (EMPTY_NAME(values[0])) { 17004520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 17014520Snw141292 goto out; 17024520Snw141292 } 17034520Snw141292 unixname = (values[0][0] == '*')?winname:values[0]; 17044520Snw141292 retcode = ns_lookup_byname(is_user, unixname, res); 17054520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 17064520Snw141292 if (unixname == winname) 17074520Snw141292 /* Case 4 */ 17084520Snw141292 continue; 17094520Snw141292 else 17104520Snw141292 /* Case 3 */ 17114520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 17124520Snw141292 } 17134520Snw141292 goto out; 17144520Snw141292 } else if (r == SQLITE_DONE) { 17154520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 17164520Snw141292 goto out; 17174520Snw141292 } else { 17184520Snw141292 (void) sqlite_finalize(vm, &errmsg); 17194520Snw141292 vm = NULL; 17204520Snw141292 idmapdlog(LOG_ERR, 17214520Snw141292 "%s: database error (%s)", 17224520Snw141292 me, CHECK_NULL(errmsg)); 17234520Snw141292 sqlite_freemem(errmsg); 17244520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17254520Snw141292 goto out; 17264520Snw141292 } 17274520Snw141292 } 17284520Snw141292 17294520Snw141292 out: 17304864Sbaban if (sql != NULL) 17314520Snw141292 sqlite_freemem(sql); 17324520Snw141292 if (retcode == IDMAP_SUCCESS) { 17334864Sbaban if (values[1] != NULL) 17344520Snw141292 res->direction = 17354644Sbaban (strtol(values[1], &end, 10) == 0)? 17364644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 17374520Snw141292 else 17384644Sbaban res->direction = IDMAP_DIRECTION_W2U; 1739*5064Sdm199847 req->id2name = strdup(unixname); 17404520Snw141292 } 17414864Sbaban if (vm != NULL) 17424520Snw141292 (void) sqlite_finalize(vm, NULL); 17434520Snw141292 return (retcode); 17444520Snw141292 } 17454520Snw141292 17464520Snw141292 static 17474520Snw141292 int 17484520Snw141292 get_next_eph_uid(uid_t *next_uid) 17494520Snw141292 { 17504520Snw141292 uid_t uid; 17514520Snw141292 gid_t gid; 17524520Snw141292 int err; 17534520Snw141292 17544520Snw141292 *next_uid = (uid_t)-1; 17554520Snw141292 uid = _idmapdstate.next_uid++; 17564520Snw141292 if (uid >= _idmapdstate.limit_uid) { 17574520Snw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 17584520Snw141292 return (err); 17594520Snw141292 17604520Snw141292 _idmapdstate.limit_uid = uid + 8192; 17614520Snw141292 _idmapdstate.next_uid = uid; 17624520Snw141292 } 17634520Snw141292 *next_uid = uid; 17644520Snw141292 17654520Snw141292 return (0); 17664520Snw141292 } 17674520Snw141292 17684520Snw141292 static 17694520Snw141292 int 17704520Snw141292 get_next_eph_gid(gid_t *next_gid) 17714520Snw141292 { 17724520Snw141292 uid_t uid; 17734520Snw141292 gid_t gid; 17744520Snw141292 int err; 17754520Snw141292 17764520Snw141292 *next_gid = (uid_t)-1; 17774520Snw141292 gid = _idmapdstate.next_gid++; 17784520Snw141292 if (gid >= _idmapdstate.limit_gid) { 17794520Snw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 17804520Snw141292 return (err); 17814520Snw141292 17824520Snw141292 _idmapdstate.limit_gid = gid + 8192; 17834520Snw141292 _idmapdstate.next_gid = gid; 17844520Snw141292 } 17854520Snw141292 *next_gid = gid; 17864520Snw141292 17874520Snw141292 return (0); 17884520Snw141292 } 17894520Snw141292 17904864Sbaban static 17914864Sbaban int 17924864Sbaban gethash(const char *str, uint32_t num, uint_t htsize) { 17934864Sbaban uint_t hval, i, len; 17944864Sbaban 17954864Sbaban if (str == NULL) 17964864Sbaban return (0); 17974864Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 17984864Sbaban hval += str[i]; 17994864Sbaban hval += (hval << 10); 18004864Sbaban hval ^= (hval >> 6); 18014864Sbaban } 18024864Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 18034864Sbaban hval += str[i]; 18044864Sbaban hval += (hval << 10); 18054864Sbaban hval ^= (hval >> 6); 18064864Sbaban } 18074864Sbaban hval += (hval << 3); 18084864Sbaban hval ^= (hval >> 11); 18094864Sbaban hval += (hval << 15); 18104864Sbaban return (hval % htsize); 18114864Sbaban } 18124864Sbaban 18134864Sbaban static 18144864Sbaban int 18154864Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 18164864Sbaban uid_t *pid) { 18174864Sbaban uint_t next, key; 18184864Sbaban uint_t htsize = state->sid_history_size; 18194864Sbaban idmap_sid *sid; 18204864Sbaban 18214864Sbaban next = gethash(prefix, rid, htsize); 18224864Sbaban while (next != htsize) { 18234864Sbaban key = state->sid_history[next].key; 18244864Sbaban if (key == htsize) 18254864Sbaban return (0); 18264864Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 18274864Sbaban idmap_id_u.sid; 18284864Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 18294864Sbaban *pid = state->result->ids.ids_val[key].id. 18304864Sbaban idmap_id_u.uid; 18314864Sbaban return (1); 18324864Sbaban } 18334864Sbaban next = state->sid_history[next].next; 18344864Sbaban } 18354864Sbaban return (0); 18364864Sbaban } 18374864Sbaban 18384864Sbaban static 18394864Sbaban void 18404864Sbaban add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) { 18414864Sbaban uint_t hash, next; 18424864Sbaban uint_t htsize = state->sid_history_size; 18434864Sbaban 18444864Sbaban hash = next = gethash(prefix, rid, htsize); 18454864Sbaban while (state->sid_history[next].key != htsize) { 18464864Sbaban next++; 18474864Sbaban next %= htsize; 18484864Sbaban } 18494864Sbaban state->sid_history[next].key = state->curpos; 18504864Sbaban if (hash == next) 18514864Sbaban return; 18524864Sbaban state->sid_history[next].next = state->sid_history[hash].next; 18534864Sbaban state->sid_history[hash].next = next; 18544864Sbaban } 18554520Snw141292 18564520Snw141292 /* ARGSUSED */ 18574520Snw141292 static 18584520Snw141292 idmap_retcode 18594864Sbaban dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 18604864Sbaban idmap_mapping *req, idmap_id_res *res) { 18614520Snw141292 18624520Snw141292 uid_t next_pid; 18634520Snw141292 18644864Sbaban res->direction = IDMAP_DIRECTION_BI; 18654864Sbaban 18664864Sbaban if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 18674864Sbaban return (IDMAP_SUCCESS); 18684864Sbaban 18694864Sbaban if (state->sid_history != NULL && 18704864Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 18714864Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 18724864Sbaban res->id.idmap_id_u.uid = next_pid; 18734864Sbaban return (IDMAP_SUCCESS); 18744864Sbaban } 18754864Sbaban 18764864Sbaban if (res->id.idtype == IDMAP_UID) { 18774520Snw141292 if (get_next_eph_uid(&next_pid) != 0) 18784520Snw141292 return (IDMAP_ERR_INTERNAL); 18794520Snw141292 res->id.idmap_id_u.uid = next_pid; 18804520Snw141292 } else { 18814520Snw141292 if (get_next_eph_gid(&next_pid) != 0) 18824520Snw141292 return (IDMAP_ERR_INTERNAL); 18834520Snw141292 res->id.idmap_id_u.gid = next_pid; 18844520Snw141292 } 18854520Snw141292 18864864Sbaban if (state->sid_history != NULL) 18874864Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 18884864Sbaban req->id1.idmap_id_u.sid.rid); 18894864Sbaban 18904520Snw141292 return (IDMAP_SUCCESS); 18914520Snw141292 } 18924520Snw141292 18934520Snw141292 idmap_retcode 18944520Snw141292 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 18954520Snw141292 idmap_mapping *req, idmap_id_res *res) { 18964520Snw141292 idmap_retcode retcode; 18974520Snw141292 18984520Snw141292 /* 18994520Snw141292 * The req->direction field is used to maintain state of the 19004520Snw141292 * sid2pid request. 19014520Snw141292 */ 19024520Snw141292 19034520Snw141292 /* Check if second pass is needed */ 19044520Snw141292 if (req->direction == _IDMAP_F_DONE) 19054520Snw141292 return (res->retcode); 19064520Snw141292 19074520Snw141292 /* Get status from previous pass */ 19084520Snw141292 retcode = (res->retcode == IDMAP_NEXT)?IDMAP_SUCCESS:res->retcode; 19094520Snw141292 19104520Snw141292 if (retcode != IDMAP_SUCCESS) { 19114520Snw141292 /* Reset return type */ 19124520Snw141292 res->id.idtype = req->id2.idtype; 19134520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 19144520Snw141292 19154520Snw141292 /* Check if this is a localsid */ 19164520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND && 19174864Sbaban _idmapdstate.cfg->pgcfg.machine_sid) { 19184520Snw141292 retcode = lookup_localsid2pid(req, res); 19194520Snw141292 if (retcode == IDMAP_SUCCESS) { 19204520Snw141292 state->sid2pid_done = FALSE; 19214520Snw141292 req->direction = _IDMAP_F_S2N_CACHE; 19224520Snw141292 } 19234520Snw141292 } 19244520Snw141292 goto out; 19254520Snw141292 } 19264520Snw141292 19274520Snw141292 /* 19284520Snw141292 * Verify that the sid type matches the request if the 19294520Snw141292 * SID was validated by an AD lookup. 19304520Snw141292 */ 19314520Snw141292 if (req->direction & _IDMAP_F_S2N_AD) { 19324520Snw141292 retcode = verify_type(req->id2.idtype, 19334520Snw141292 (int)res->id.idtype, res); 19344520Snw141292 if (retcode != IDMAP_SUCCESS) { 19354520Snw141292 res->id.idtype = req->id2.idtype; 19364520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 19374520Snw141292 goto out; 19384520Snw141292 } 19394520Snw141292 } 19404520Snw141292 19414520Snw141292 /* Name-based mapping */ 19424520Snw141292 retcode = name_based_mapping_sid2pid(db, req, res); 19434520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 19444520Snw141292 /* If not found, do ephemeral mapping */ 19454520Snw141292 goto ephemeral; 19464520Snw141292 else if (retcode != IDMAP_SUCCESS) 19474520Snw141292 goto out; 19484520Snw141292 19494520Snw141292 state->sid2pid_done = FALSE; 19504520Snw141292 goto out; 19514520Snw141292 19524520Snw141292 19534520Snw141292 ephemeral: 19544864Sbaban retcode = dynamic_ephemeral_mapping(state, cache, req, res); 19554520Snw141292 if (retcode == IDMAP_SUCCESS) 19564520Snw141292 state->sid2pid_done = FALSE; 19574520Snw141292 19584520Snw141292 out: 19594520Snw141292 res->retcode = idmap_stat4prot(retcode); 19604520Snw141292 return (retcode); 19614520Snw141292 } 19624520Snw141292 19634520Snw141292 idmap_retcode 19644520Snw141292 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 19654520Snw141292 idmap_mapping *req, idmap_id_res *res) { 19664520Snw141292 char *sql = NULL; 19674520Snw141292 idmap_retcode retcode; 19684520Snw141292 19694520Snw141292 /* Check if we need to cache anything */ 19704520Snw141292 if (req->direction == _IDMAP_F_DONE) 19714520Snw141292 return (IDMAP_SUCCESS); 19724520Snw141292 19734520Snw141292 /* We don't cache negative entries */ 19744520Snw141292 if (res->retcode != IDMAP_SUCCESS) 19754520Snw141292 return (IDMAP_SUCCESS); 19764520Snw141292 19774520Snw141292 /* 19784520Snw141292 * Using NULL for u2w instead of 0 so that our trigger allows 19794520Snw141292 * the same pid to be the destination in multiple entries 19804520Snw141292 */ 19814520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 19824520Snw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 19834520Snw141292 "is_user, expiration, w2u, u2w) " 19844520Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 19854520Snw141292 "strftime('%%s','now') + 600, %q, 1); ", 19864520Snw141292 res->id.idmap_id_u.sid.prefix, 19874520Snw141292 res->id.idmap_id_u.sid.rid, 1988*5064Sdm199847 req->id2domain, 1989*5064Sdm199847 req->id2name, 19904520Snw141292 req->id1.idmap_id_u.uid, 1991*5064Sdm199847 req->id1name, 19924520Snw141292 (req->id1.idtype == IDMAP_UID)?1:0, 19934520Snw141292 (res->direction == 0)?"1":NULL); 19944520Snw141292 19954520Snw141292 if (sql == NULL) { 19964520Snw141292 retcode = IDMAP_ERR_INTERNAL; 19974520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 19984520Snw141292 goto out; 19994520Snw141292 } 20004520Snw141292 20014520Snw141292 retcode = sql_exec_no_cb(cache, sql); 20024520Snw141292 if (retcode != IDMAP_SUCCESS) 20034520Snw141292 goto out; 20044520Snw141292 20054520Snw141292 state->pid2sid_done = FALSE; 20064520Snw141292 sqlite_freemem(sql); 20074520Snw141292 sql = NULL; 20084520Snw141292 20094520Snw141292 /* If sid2name was found in the cache, no need to update namecache */ 20104520Snw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 20114520Snw141292 goto out; 20124520Snw141292 2013*5064Sdm199847 if (req->id2name == NULL) 20144520Snw141292 goto out; 20154520Snw141292 20164520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 20174520Snw141292 "(sidprefix, rid, name, domain, type, expiration) " 20184520Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 20194520Snw141292 res->id.idmap_id_u.sid.prefix, 20204520Snw141292 res->id.idmap_id_u.sid.rid, 2021*5064Sdm199847 req->id2name, 2022*5064Sdm199847 req->id2domain, 20234520Snw141292 (req->id1.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 20244520Snw141292 20254520Snw141292 if (sql == NULL) { 20264520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20274520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 20284520Snw141292 goto out; 20294520Snw141292 } 20304520Snw141292 20314520Snw141292 retcode = sql_exec_no_cb(cache, sql); 20324520Snw141292 20334520Snw141292 out: 20344864Sbaban if (sql != NULL) 20354520Snw141292 sqlite_freemem(sql); 20364520Snw141292 return (retcode); 20374520Snw141292 } 20384520Snw141292 20394520Snw141292 idmap_retcode 20404520Snw141292 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 20414520Snw141292 idmap_mapping *req, idmap_id_res *res) { 20424520Snw141292 char *sql = NULL; 20434520Snw141292 idmap_retcode retcode; 20444520Snw141292 int is_eph_user; 20454520Snw141292 20464520Snw141292 /* Check if we need to cache anything */ 20474520Snw141292 if (req->direction == _IDMAP_F_DONE) 20484520Snw141292 return (IDMAP_SUCCESS); 20494520Snw141292 20504520Snw141292 /* We don't cache negative entries */ 20514520Snw141292 if (res->retcode != IDMAP_SUCCESS) 20524520Snw141292 return (IDMAP_SUCCESS); 20534520Snw141292 20544520Snw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 20554520Snw141292 is_eph_user = 1; 20564520Snw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 20574520Snw141292 is_eph_user = 0; 20584520Snw141292 else 20594520Snw141292 is_eph_user = -1; 20604520Snw141292 20614520Snw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 20624520Snw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 20634520Snw141292 "SET w2u = 0 WHERE " 20644520Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 20654520Snw141292 "pid >= 2147483648 AND is_user = %d;", 20664520Snw141292 req->id1.idmap_id_u.sid.prefix, 20674520Snw141292 req->id1.idmap_id_u.sid.rid, 20684520Snw141292 is_eph_user); 20694520Snw141292 if (sql == NULL) { 20704520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20714520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 20724520Snw141292 goto out; 20734520Snw141292 } 20744520Snw141292 20754520Snw141292 retcode = sql_exec_no_cb(cache, sql); 20764520Snw141292 if (retcode != IDMAP_SUCCESS) 20774520Snw141292 goto out; 20784520Snw141292 20794520Snw141292 sqlite_freemem(sql); 20804520Snw141292 sql = NULL; 20814520Snw141292 } 20824520Snw141292 20834520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 20844520Snw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 20854520Snw141292 "is_user, expiration, w2u, u2w) " 20864520Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 20874520Snw141292 "strftime('%%s','now') + 600, 1, %q); ", 20884520Snw141292 req->id1.idmap_id_u.sid.prefix, 20894520Snw141292 req->id1.idmap_id_u.sid.rid, 2090*5064Sdm199847 req->id1domain, 2091*5064Sdm199847 req->id1name, 20924520Snw141292 res->id.idmap_id_u.uid, 2093*5064Sdm199847 req->id2name, 20944520Snw141292 (res->id.idtype == IDMAP_UID)?1:0, 20954520Snw141292 (res->direction == 0)?"1":NULL); 20964520Snw141292 20974520Snw141292 if (sql == NULL) { 20984520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20994520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21004520Snw141292 goto out; 21014520Snw141292 } 21024520Snw141292 21034520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21044520Snw141292 if (retcode != IDMAP_SUCCESS) 21054520Snw141292 goto out; 21064520Snw141292 21074520Snw141292 state->sid2pid_done = FALSE; 21084520Snw141292 sqlite_freemem(sql); 21094520Snw141292 sql = NULL; 21104520Snw141292 21114520Snw141292 /* If name2sid was found in the cache, no need to update namecache */ 21124520Snw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 21134520Snw141292 goto out; 21144520Snw141292 2115*5064Sdm199847 if (req->id1name == NULL) 21164520Snw141292 goto out; 21174520Snw141292 21184520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 21194520Snw141292 "(sidprefix, rid, name, domain, type, expiration) " 21204520Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 21214520Snw141292 req->id1.idmap_id_u.sid.prefix, 21224520Snw141292 req->id1.idmap_id_u.sid.rid, 2123*5064Sdm199847 req->id1name, 2124*5064Sdm199847 req->id1domain, 21254520Snw141292 (res->id.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 21264520Snw141292 21274520Snw141292 if (sql == NULL) { 21284520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21294520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21304520Snw141292 goto out; 21314520Snw141292 } 21324520Snw141292 21334520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21344520Snw141292 21354520Snw141292 out: 21364864Sbaban if (sql != NULL) 21374520Snw141292 sqlite_freemem(sql); 21384520Snw141292 return (retcode); 21394520Snw141292 } 21404520Snw141292 21414520Snw141292 static idmap_retcode 21424520Snw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 21434520Snw141292 int is_user, int getname) { 21444520Snw141292 char *end; 21454520Snw141292 char *sql = NULL; 21464520Snw141292 const char **values; 21474520Snw141292 sqlite_vm *vm = NULL; 21484520Snw141292 int ncol; 21494520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 21504520Snw141292 time_t curtime; 21514520Snw141292 21524520Snw141292 /* Current time */ 21534520Snw141292 errno = 0; 21544520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 21554520Snw141292 idmapdlog(LOG_ERR, 21564520Snw141292 "Failed to get current time (%s)", 21574520Snw141292 strerror(errno)); 21584520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21594520Snw141292 goto out; 21604520Snw141292 } 21614520Snw141292 21624520Snw141292 /* SQL to lookup the cache */ 21634520Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, winname, windomain, w2u " 21644520Snw141292 "FROM idmap_cache WHERE " 21654520Snw141292 "pid = %u AND u2w = 1 AND is_user = %d AND " 21664520Snw141292 "(pid >= 2147483648 OR " 21674520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 21684520Snw141292 "expiration > %d));", 21694520Snw141292 req->id1.idmap_id_u.uid, is_user, curtime); 21704520Snw141292 if (sql == NULL) { 21714520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21724520Snw141292 retcode = IDMAP_ERR_MEMORY; 21734520Snw141292 goto out; 21744520Snw141292 } 21754520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 21764520Snw141292 sqlite_freemem(sql); 21774520Snw141292 21784520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 21794520Snw141292 goto out; 21804520Snw141292 else if (retcode == IDMAP_SUCCESS) { 21814520Snw141292 /* sanity checks */ 21824520Snw141292 if (values[0] == NULL || values[1] == NULL) { 21834520Snw141292 retcode = IDMAP_ERR_CACHE; 21844520Snw141292 goto out; 21854520Snw141292 } 21864520Snw141292 21874520Snw141292 switch (req->id2.idtype) { 21884520Snw141292 case IDMAP_SID: 21894520Snw141292 res->id.idmap_id_u.sid.rid = 21904520Snw141292 strtoul(values[1], &end, 10); 21914520Snw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 21924520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 21934520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21944520Snw141292 retcode = IDMAP_ERR_MEMORY; 21954520Snw141292 goto out; 21964520Snw141292 } 21974520Snw141292 21984864Sbaban if (values[4] != NULL) 21994520Snw141292 res->direction = 22004644Sbaban (strtol(values[4], &end, 10) == 0)? 22014644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 22024520Snw141292 else 22034644Sbaban res->direction = IDMAP_DIRECTION_U2W; 22044520Snw141292 22054520Snw141292 if (getname == 0 || values[2] == NULL) 22064520Snw141292 break; 2207*5064Sdm199847 req->id2name = strdup(values[2]); 2208*5064Sdm199847 if (req->id2name == NULL) { 22094520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22104520Snw141292 retcode = IDMAP_ERR_MEMORY; 22114520Snw141292 goto out; 22124520Snw141292 } 22134520Snw141292 22144520Snw141292 if (values[3] == NULL) 22154520Snw141292 break; 2216*5064Sdm199847 req->id2domain = strdup(values[3]); 2217*5064Sdm199847 if (req->id2domain == NULL) { 22184520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22194520Snw141292 retcode = IDMAP_ERR_MEMORY; 22204520Snw141292 goto out; 22214520Snw141292 } 22224520Snw141292 break; 22234520Snw141292 default: 22244520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 22254520Snw141292 break; 22264520Snw141292 } 22274520Snw141292 } 22284520Snw141292 22294520Snw141292 out: 22304864Sbaban if (vm != NULL) 22314520Snw141292 (void) sqlite_finalize(vm, NULL); 22324520Snw141292 return (retcode); 22334520Snw141292 } 22344520Snw141292 22354520Snw141292 static idmap_retcode 22364520Snw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 22374520Snw141292 char **sidprefix, idmap_rid_t *rid, int *type) { 22384520Snw141292 char *end; 22394520Snw141292 char *sql = NULL; 22404520Snw141292 const char **values; 22414520Snw141292 sqlite_vm *vm = NULL; 22424520Snw141292 int ncol; 22434520Snw141292 time_t curtime; 22444520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 22454520Snw141292 22464520Snw141292 /* Get current time */ 22474520Snw141292 errno = 0; 22484520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 22494520Snw141292 idmapdlog(LOG_ERR, 22504520Snw141292 "Failed to get current time (%s)", 22514520Snw141292 strerror(errno)); 22524520Snw141292 retcode = IDMAP_ERR_INTERNAL; 22534520Snw141292 goto out; 22544520Snw141292 } 22554520Snw141292 22564520Snw141292 /* SQL to lookup the cache */ 22574520Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type FROM name_cache " 22584520Snw141292 "WHERE name = %Q AND domain = %Q AND " 22594520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 22604520Snw141292 "expiration > %d);", 22614520Snw141292 name, domain, curtime); 22624520Snw141292 if (sql == NULL) { 22634520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22644520Snw141292 retcode = IDMAP_ERR_MEMORY; 22654520Snw141292 goto out; 22664520Snw141292 } 22674520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 22684520Snw141292 sqlite_freemem(sql); 22694520Snw141292 22704520Snw141292 if (retcode == IDMAP_SUCCESS) { 22714864Sbaban if (type != NULL) { 22724520Snw141292 if (values[2] == NULL) { 22734520Snw141292 retcode = IDMAP_ERR_CACHE; 22744520Snw141292 goto out; 22754520Snw141292 } 22764520Snw141292 *type = strtol(values[2], &end, 10); 22774520Snw141292 } 22784520Snw141292 22794520Snw141292 if (values[0] == NULL || values[1] == NULL) { 22804520Snw141292 retcode = IDMAP_ERR_CACHE; 22814520Snw141292 goto out; 22824520Snw141292 } 22834520Snw141292 if ((*sidprefix = strdup(values[0])) == NULL) { 22844520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22854520Snw141292 retcode = IDMAP_ERR_MEMORY; 22864520Snw141292 goto out; 22874520Snw141292 } 22884520Snw141292 *rid = strtoul(values[1], &end, 10); 22894520Snw141292 } 22904520Snw141292 22914520Snw141292 out: 22924864Sbaban if (vm != NULL) 22934520Snw141292 (void) sqlite_finalize(vm, NULL); 22944520Snw141292 return (retcode); 22954520Snw141292 } 22964520Snw141292 22974520Snw141292 static idmap_retcode 22984520Snw141292 lookup_win_name2sid(const char *name, const char *domain, char **sidprefix, 22994520Snw141292 idmap_rid_t *rid, int *type) { 23004520Snw141292 int ret; 23014520Snw141292 int retries = 0; 23024520Snw141292 idmap_query_state_t *qs = NULL; 23034520Snw141292 idmap_retcode rc, retcode; 23044520Snw141292 23054520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 23064520Snw141292 23074520Snw141292 retry: 23084520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 23094520Snw141292 if (ret != 0) { 23104520Snw141292 idmapdlog(LOG_ERR, 23114520Snw141292 "Failed to create name2sid batch for AD lookup"); 23124520Snw141292 return (IDMAP_ERR_INTERNAL); 23134520Snw141292 } 23144520Snw141292 23154520Snw141292 retcode = idmap_name2sid_batch_add1(qs, name, domain, sidprefix, 23164520Snw141292 rid, type, &rc); 23174520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 23184520Snw141292 goto out; 23194520Snw141292 23204520Snw141292 if (retcode != IDMAP_SUCCESS) { 23214520Snw141292 idmapdlog(LOG_ERR, 23224520Snw141292 "Failed to batch name2sid for AD lookup"); 23234884Sjp151216 idmap_lookup_release_batch(&qs); 23244520Snw141292 return (IDMAP_ERR_INTERNAL); 23254520Snw141292 } 23264520Snw141292 23274520Snw141292 out: 23284520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 23294884Sjp151216 idmap_lookup_release_batch(&qs); 23304520Snw141292 else 23314520Snw141292 retcode = idmap_lookup_batch_end(&qs, NULL); 23324520Snw141292 23334520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 23344520Snw141292 goto retry; 23354520Snw141292 23364520Snw141292 if (retcode != IDMAP_SUCCESS) { 23374520Snw141292 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 23384520Snw141292 "failed"); 23394520Snw141292 return (retcode); 23404520Snw141292 } else 23414520Snw141292 return (rc); 23424520Snw141292 /* NOTREACHED */ 23434520Snw141292 } 23444520Snw141292 23454520Snw141292 static idmap_retcode 23464520Snw141292 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 23474520Snw141292 int *is_user, char **sidprefix, idmap_rid_t *rid, 23484520Snw141292 idmap_mapping *req) { 23494520Snw141292 int type; 23504520Snw141292 idmap_retcode retcode; 23514520Snw141292 23524864Sbaban /* Lookup name@domain to sid in the well-known sids table */ 23534864Sbaban retcode = lookup_wksids_name2sid(name, sidprefix, rid, &type); 23544864Sbaban if (retcode == IDMAP_SUCCESS) { 23554864Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 23564864Sbaban goto out; 23574864Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 23584864Sbaban return (retcode); 23594864Sbaban } 23604864Sbaban 23614864Sbaban /* Lookup name@domain to sid in cache */ 23624520Snw141292 retcode = lookup_cache_name2sid(cache, name, domain, sidprefix, 23634520Snw141292 rid, &type); 23644520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 23654520Snw141292 /* Lookup Windows NT/AD to map name@domain to sid */ 23664520Snw141292 retcode = lookup_win_name2sid(name, domain, sidprefix, rid, 23674520Snw141292 &type); 23684520Snw141292 if (retcode != IDMAP_SUCCESS) 23694520Snw141292 return (retcode); 23704520Snw141292 req->direction |= _IDMAP_F_S2N_AD; 23714520Snw141292 } else if (retcode != IDMAP_SUCCESS) { 23724520Snw141292 return (retcode); 23734520Snw141292 } else { 23744520Snw141292 /* Set flag */ 23754520Snw141292 req->direction |= _IDMAP_F_S2N_CACHE; 23764520Snw141292 } 23774520Snw141292 23784864Sbaban out: 23794520Snw141292 /* 23804520Snw141292 * Entry found (cache or Windows lookup) 23814520Snw141292 * is_user is both input as well as output parameter 23824520Snw141292 */ 23834520Snw141292 if (*is_user == 1) { 23844520Snw141292 if (type != _IDMAP_T_USER) 23854520Snw141292 return (IDMAP_ERR_NOTUSER); 23864520Snw141292 } else if (*is_user == 0) { 23874520Snw141292 if (type != _IDMAP_T_GROUP) 23884520Snw141292 return (IDMAP_ERR_NOTGROUP); 23894520Snw141292 } else if (*is_user == -1) { 23904520Snw141292 /* Caller wants to know if its user or group */ 23914520Snw141292 if (type == _IDMAP_T_USER) 23924520Snw141292 *is_user = 1; 23934520Snw141292 else if (type == _IDMAP_T_GROUP) 23944520Snw141292 *is_user = 0; 23954520Snw141292 else 23964520Snw141292 return (IDMAP_ERR_SID); 23974520Snw141292 } 23984520Snw141292 23994520Snw141292 return (retcode); 24004520Snw141292 } 24014520Snw141292 24024520Snw141292 static idmap_retcode 24034520Snw141292 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 24044520Snw141292 int is_user, idmap_mapping *req, idmap_id_res *res) { 24054520Snw141292 const char *winname, *windomain; 24064520Snw141292 char *mapping_domain = NULL; 24074520Snw141292 char *sql = NULL, *errmsg = NULL; 24084520Snw141292 idmap_retcode retcode; 24094520Snw141292 char *end; 24104520Snw141292 const char **values; 24114520Snw141292 sqlite_vm *vm = NULL; 24124884Sjp151216 int ncol, r; 24134520Snw141292 const char *me = "name_based_mapping_pid2sid"; 24144520Snw141292 24154520Snw141292 RDLOCK_CONFIG(); 24164864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 24174520Snw141292 mapping_domain = 24184520Snw141292 strdup(_idmapdstate.cfg->pgcfg.mapping_domain); 24194520Snw141292 if (mapping_domain == NULL) { 24204520Snw141292 UNLOCK_CONFIG(); 24214520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 24224520Snw141292 retcode = IDMAP_ERR_MEMORY; 24234520Snw141292 goto out; 24244520Snw141292 } 24254520Snw141292 } 24264520Snw141292 UNLOCK_CONFIG(); 24274520Snw141292 24284520Snw141292 sql = sqlite_mprintf( 24294520Snw141292 "SELECT winname, windomain, w2u_order FROM namerules WHERE " 24304520Snw141292 "u2w_order > 0 AND is_user = %d AND " 24314520Snw141292 "(unixname = %Q OR unixname = '*') " 24324520Snw141292 "ORDER BY u2w_order ASC;", 24334520Snw141292 is_user, unixname); 24344520Snw141292 if (sql == NULL) { 24354520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 24364520Snw141292 retcode = IDMAP_ERR_MEMORY; 24374520Snw141292 goto out; 24384520Snw141292 } 24394520Snw141292 24404520Snw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 24414520Snw141292 retcode = IDMAP_ERR_INTERNAL; 24424520Snw141292 idmapdlog(LOG_ERR, 24434520Snw141292 "%s: database error (%s)", 24444520Snw141292 me, CHECK_NULL(errmsg)); 24454520Snw141292 sqlite_freemem(errmsg); 24464520Snw141292 goto out; 24474520Snw141292 } 24484520Snw141292 24494884Sjp151216 for (;;) { 24504520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 24514884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 24524884Sjp151216 if (r == SQLITE_ROW) { 24534520Snw141292 if (ncol < 3) { 24544520Snw141292 retcode = IDMAP_ERR_INTERNAL; 24554520Snw141292 goto out; 24564520Snw141292 } 24574520Snw141292 if (values[0] == NULL) { 24584520Snw141292 /* values [1] and [2] can be null */ 24594520Snw141292 retcode = IDMAP_ERR_INTERNAL; 24604520Snw141292 goto out; 24614520Snw141292 } 24624520Snw141292 if (EMPTY_NAME(values[0])) { 24634520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 24644520Snw141292 goto out; 24654520Snw141292 } 24664520Snw141292 winname = (values[0][0] == '*')?unixname:values[0]; 24674864Sbaban if (values[1] != NULL) 24684520Snw141292 windomain = values[1]; 24694864Sbaban else if (mapping_domain != NULL) 24704520Snw141292 windomain = mapping_domain; 24714520Snw141292 else { 24724520Snw141292 idmapdlog(LOG_ERR, 24734520Snw141292 "%s: no domain", me); 24744520Snw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 24754520Snw141292 goto out; 24764520Snw141292 } 24774520Snw141292 /* Lookup winname@domain to sid */ 24784520Snw141292 retcode = lookup_name2sid(cache, winname, windomain, 24794520Snw141292 &is_user, &res->id.idmap_id_u.sid.prefix, 24804520Snw141292 &res->id.idmap_id_u.sid.rid, req); 24814520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 24824520Snw141292 if (winname == unixname) 24834520Snw141292 continue; 24844520Snw141292 else 24854520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 24864520Snw141292 } 24874520Snw141292 goto out; 24884520Snw141292 } else if (r == SQLITE_DONE) { 24894520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 24904520Snw141292 goto out; 24914520Snw141292 } else { 24924520Snw141292 (void) sqlite_finalize(vm, &errmsg); 24934520Snw141292 vm = NULL; 24944520Snw141292 idmapdlog(LOG_ERR, 24954520Snw141292 "%s: database error (%s)", 24964520Snw141292 me, CHECK_NULL(errmsg)); 24974520Snw141292 sqlite_freemem(errmsg); 24984520Snw141292 retcode = IDMAP_ERR_INTERNAL; 24994520Snw141292 goto out; 25004520Snw141292 } 25014520Snw141292 } 25024520Snw141292 25034520Snw141292 out: 25044864Sbaban if (sql != NULL) 25054520Snw141292 sqlite_freemem(sql); 25064520Snw141292 if (retcode == IDMAP_SUCCESS) { 25074864Sbaban if (values[2] != NULL) 25084520Snw141292 res->direction = 25094644Sbaban (strtol(values[2], &end, 10) == 0)? 25104644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 25114520Snw141292 else 25124644Sbaban res->direction = IDMAP_DIRECTION_U2W; 2513*5064Sdm199847 2514*5064Sdm199847 req->id2name = strdup(winname); 2515*5064Sdm199847 if (req->id2name != NULL) { 25164520Snw141292 if (windomain == mapping_domain) { 2517*5064Sdm199847 req->id2domain = (char *)windomain; 25184520Snw141292 mapping_domain = NULL; 2519*5064Sdm199847 } else { 2520*5064Sdm199847 req->id2domain = strdup(windomain); 2521*5064Sdm199847 } 25224520Snw141292 } 25234520Snw141292 } 25244864Sbaban if (vm != NULL) 25254520Snw141292 (void) sqlite_finalize(vm, NULL); 25264864Sbaban if (mapping_domain != NULL) 25274520Snw141292 free(mapping_domain); 25284520Snw141292 return (retcode); 25294520Snw141292 } 25304520Snw141292 25314520Snw141292 idmap_retcode 25324520Snw141292 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 25334520Snw141292 idmap_mapping *req, idmap_id_res *res, int is_user, 25344520Snw141292 int getname) { 25354520Snw141292 char *unixname = NULL; 25364520Snw141292 struct passwd pwd; 25374520Snw141292 struct group grp; 25384520Snw141292 char buf[1024]; 25394520Snw141292 int errnum; 25404520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 25414520Snw141292 const char *me = "pid2sid"; 25424520Snw141292 25434520Snw141292 req->direction = _IDMAP_F_DONE; 25444520Snw141292 res->id.idtype = req->id2.idtype; 25454520Snw141292 25464520Snw141292 /* Lookup well-known SIDs */ 25474520Snw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 25484520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 25494520Snw141292 goto out; 25504520Snw141292 25514520Snw141292 /* Lookup pid to sid in cache */ 25524520Snw141292 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 25534520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 25544520Snw141292 goto out; 25554520Snw141292 25564520Snw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 25574520Snw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 25584864Sbaban retcode = IDMAP_ERR_NOMAPPING; 25594520Snw141292 goto out; 25604520Snw141292 } 25614520Snw141292 25624520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 25634864Sbaban retcode = IDMAP_ERR_NOMAPPING; 25644520Snw141292 goto out; 25654520Snw141292 } 25664520Snw141292 25674520Snw141292 /* uid/gid to name */ 2568*5064Sdm199847 if (req->id1name != NULL) { 2569*5064Sdm199847 unixname = req->id1name; 2570*5064Sdm199847 } else if (is_user) { 25714520Snw141292 errno = 0; 25724520Snw141292 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 25734520Snw141292 sizeof (buf)) == NULL) { 25744520Snw141292 errnum = errno; 25754520Snw141292 idmapdlog(LOG_WARNING, 25764520Snw141292 "%s: getpwuid_r(%u) failed (%s).", 25774520Snw141292 me, req->id1.idmap_id_u.uid, 25784520Snw141292 errnum?strerror(errnum):"not found"); 25794520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 25804520Snw141292 IDMAP_ERR_INTERNAL; 25814520Snw141292 goto fallback_localsid; 25824520Snw141292 } 25834520Snw141292 unixname = pwd.pw_name; 25844520Snw141292 } else { 25854520Snw141292 errno = 0; 25864520Snw141292 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 25874520Snw141292 sizeof (buf)) == NULL) { 25884520Snw141292 errnum = errno; 25894520Snw141292 idmapdlog(LOG_WARNING, 25904520Snw141292 "%s: getgrgid_r(%u) failed (%s).", 25914520Snw141292 me, req->id1.idmap_id_u.gid, 25924520Snw141292 errnum?strerror(errnum):"not found"); 25934520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 25944520Snw141292 IDMAP_ERR_INTERNAL; 25954520Snw141292 goto fallback_localsid; 25964520Snw141292 } 25974520Snw141292 unixname = grp.gr_name; 25984520Snw141292 } 25994520Snw141292 26004520Snw141292 /* Name-based mapping */ 26014520Snw141292 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 26024520Snw141292 req, res); 26034520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 26044520Snw141292 retcode = generate_localsid(req, res, is_user); 26054520Snw141292 goto out; 26064520Snw141292 } else if (retcode == IDMAP_SUCCESS) 26074520Snw141292 goto out; 26084520Snw141292 26094520Snw141292 fallback_localsid: 26104520Snw141292 /* 26114520Snw141292 * Here we generate localsid as fallback id on errors. Our 26124520Snw141292 * return status is the error that's been previously assigned. 26134520Snw141292 */ 26144520Snw141292 (void) generate_localsid(req, res, is_user); 26154520Snw141292 26164520Snw141292 out: 2617*5064Sdm199847 if (retcode == IDMAP_SUCCESS && req->id1name == NULL && 2618*5064Sdm199847 unixname != NULL) { 2619*5064Sdm199847 req->id1name = strdup(unixname); 26204520Snw141292 } 26214520Snw141292 if (req->direction != _IDMAP_F_DONE) 26224520Snw141292 state->pid2sid_done = FALSE; 26234520Snw141292 res->retcode = idmap_stat4prot(retcode); 26244520Snw141292 return (retcode); 26254520Snw141292 } 26264520Snw141292 26274520Snw141292 static idmap_retcode 26284520Snw141292 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 26294520Snw141292 char **domain, int *type) { 26304520Snw141292 int ret; 26314520Snw141292 idmap_query_state_t *qs = NULL; 26324520Snw141292 idmap_retcode rc, retcode; 26334520Snw141292 26344520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 26354520Snw141292 26364520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 26374520Snw141292 if (ret != 0) { 26384520Snw141292 idmapdlog(LOG_ERR, 26394520Snw141292 "Failed to create sid2name batch for AD lookup"); 26404520Snw141292 retcode = IDMAP_ERR_INTERNAL; 26414520Snw141292 goto out; 26424520Snw141292 } 26434520Snw141292 26444520Snw141292 ret = idmap_sid2name_batch_add1( 26454520Snw141292 qs, sidprefix, &rid, name, domain, type, &rc); 26464520Snw141292 if (ret != 0) { 26474520Snw141292 idmapdlog(LOG_ERR, 26484520Snw141292 "Failed to batch sid2name for AD lookup"); 26494520Snw141292 retcode = IDMAP_ERR_INTERNAL; 26504520Snw141292 goto out; 26514520Snw141292 } 26524520Snw141292 26534520Snw141292 out: 26544864Sbaban if (qs != NULL) { 26554520Snw141292 ret = idmap_lookup_batch_end(&qs, NULL); 26564520Snw141292 if (ret != 0) { 26574520Snw141292 idmapdlog(LOG_ERR, 26584520Snw141292 "Failed to execute sid2name AD lookup"); 26594520Snw141292 retcode = IDMAP_ERR_INTERNAL; 26604520Snw141292 } else 26614520Snw141292 retcode = rc; 26624520Snw141292 } 26634520Snw141292 26644520Snw141292 return (retcode); 26654520Snw141292 } 26664520Snw141292 26674644Sbaban static int 26684644Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 26694520Snw141292 { 26704644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 26714644Sbaban 26724520Snw141292 mapping->flag = request->flag; 26734520Snw141292 mapping->direction = request->direction; 26744644Sbaban mapping->id2.idtype = request->id2.idtype; 26754520Snw141292 26764520Snw141292 mapping->id1.idtype = request->id1.idtype; 26774520Snw141292 if (request->id1.idtype == IDMAP_SID) { 26784520Snw141292 mapping->id1.idmap_id_u.sid.rid = 26794520Snw141292 request->id1.idmap_id_u.sid.rid; 26804644Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 26814520Snw141292 mapping->id1.idmap_id_u.sid.prefix = 26824520Snw141292 strdup(request->id1.idmap_id_u.sid.prefix); 26834644Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 2684*5064Sdm199847 goto errout; 26854644Sbaban } 26864520Snw141292 } else { 26874520Snw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 26884520Snw141292 } 26894520Snw141292 2690*5064Sdm199847 mapping->id1domain = strdup(request->id1domain); 2691*5064Sdm199847 if (mapping->id1domain == NULL) 2692*5064Sdm199847 goto errout; 26934520Snw141292 2694*5064Sdm199847 mapping->id1name = strdup(request->id1name); 2695*5064Sdm199847 if (mapping->id1name == NULL) 2696*5064Sdm199847 goto errout; 26974520Snw141292 26984644Sbaban /* We don't need the rest of the request i.e request->id2 */ 26994644Sbaban return (0); 27004644Sbaban 27014644Sbaban errout: 2702*5064Sdm199847 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 27034644Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 2704*5064Sdm199847 if (mapping->id1domain != NULL) 2705*5064Sdm199847 free(mapping->id1domain); 2706*5064Sdm199847 if (mapping->id1name != NULL) 2707*5064Sdm199847 free(mapping->id1name); 27084644Sbaban 27094644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 27104644Sbaban return (-1); 27114520Snw141292 } 27124520Snw141292 27134520Snw141292 27144520Snw141292 idmap_retcode 27154520Snw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 27164520Snw141292 idmap_mapping *mapping) { 27174520Snw141292 idmap_id_res idres; 27184520Snw141292 lookup_state_t state; 27195043Sbaban char *cp; 27204520Snw141292 int is_user; 27214520Snw141292 idmap_retcode retcode; 27224520Snw141292 const char *winname, *windomain; 27234520Snw141292 27244520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 27254520Snw141292 (void) memset(&state, 0, sizeof (state)); 27264520Snw141292 27274520Snw141292 if (request->id2.idtype == IDMAP_UID) 27284520Snw141292 is_user = 1; 27294520Snw141292 else if (request->id2.idtype == IDMAP_GID) 27304520Snw141292 is_user = 0; 27314520Snw141292 else if (request->id2.idtype == IDMAP_POSIXID) 27324520Snw141292 is_user = -1; 27334520Snw141292 else { 27344520Snw141292 retcode = IDMAP_ERR_IDTYPE; 27354520Snw141292 goto out; 27364520Snw141292 } 27374520Snw141292 27384520Snw141292 /* Copy data from request to result */ 27394644Sbaban if (copy_mapping_request(mapping, request) < 0) { 27404644Sbaban retcode = IDMAP_ERR_MEMORY; 27414644Sbaban goto out; 27424644Sbaban } 27434520Snw141292 2744*5064Sdm199847 winname = mapping->id1name; 2745*5064Sdm199847 windomain = mapping->id1domain; 27464520Snw141292 27474864Sbaban if (winname == NULL && windomain != NULL) { 27484520Snw141292 retcode = IDMAP_ERR_ARG; 27494520Snw141292 goto out; 27504520Snw141292 } 27514520Snw141292 27524864Sbaban if (winname != NULL && windomain == NULL) { 2753*5064Sdm199847 retcode = IDMAP_SUCCESS; 27545043Sbaban if ((cp = strchr(winname, '@')) != NULL) { 27555043Sbaban /* 27565043Sbaban * if winname is qualified with a domain, use it. 27575043Sbaban */ 27585043Sbaban *cp = '\0'; 2759*5064Sdm199847 mapping->id1domain = strdup(cp + 1); 2760*5064Sdm199847 if (mapping->id1domain == NULL) 2761*5064Sdm199847 retcode = IDMAP_ERR_MEMORY; 2762*5064Sdm199847 } else { 2763*5064Sdm199847 RDLOCK_CONFIG(); 2764*5064Sdm199847 if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 27655043Sbaban /* 27665043Sbaban * otherwise use the mapping domain 27675043Sbaban */ 2768*5064Sdm199847 mapping->id1domain = 2769*5064Sdm199847 strdup(_idmapdstate.cfg-> 2770*5064Sdm199847 pgcfg.mapping_domain); 2771*5064Sdm199847 if (mapping->id1domain == NULL) 2772*5064Sdm199847 retcode = IDMAP_ERR_MEMORY; 2773*5064Sdm199847 } 27745043Sbaban UNLOCK_CONFIG(); 2775*5064Sdm199847 } 27765043Sbaban 27775043Sbaban if (retcode != IDMAP_SUCCESS) { 27785043Sbaban idmapdlog(LOG_ERR, "Out of memory"); 27795043Sbaban goto out; 27804520Snw141292 } 2781*5064Sdm199847 windomain = mapping->id1domain; 27824520Snw141292 } 27834520Snw141292 27844864Sbaban if (winname != NULL && mapping->id1.idmap_id_u.sid.prefix == NULL) { 27854520Snw141292 retcode = lookup_name2sid(cache, winname, windomain, 27864520Snw141292 &is_user, &mapping->id1.idmap_id_u.sid.prefix, 27874520Snw141292 &mapping->id1.idmap_id_u.sid.rid, mapping); 27884520Snw141292 if (retcode != IDMAP_SUCCESS) 27894520Snw141292 goto out; 27904520Snw141292 if (mapping->id2.idtype == IDMAP_POSIXID) 27914520Snw141292 mapping->id2.idtype = is_user?IDMAP_UID:IDMAP_GID; 27924520Snw141292 } 27934520Snw141292 27944520Snw141292 state.sid2pid_done = TRUE; 27954520Snw141292 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 27964520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 27974520Snw141292 goto out; 27984520Snw141292 27994520Snw141292 if (state.ad_nqueries) { 28004520Snw141292 /* sid2name AD lookup */ 28014520Snw141292 retcode = lookup_win_sid2name( 28024520Snw141292 mapping->id1.idmap_id_u.sid.prefix, 28034520Snw141292 mapping->id1.idmap_id_u.sid.rid, 2804*5064Sdm199847 &mapping->id1name, 2805*5064Sdm199847 &mapping->id1domain, 28064520Snw141292 (int *)&idres.id.idtype); 28074520Snw141292 28084520Snw141292 idres.retcode = retcode; 28094520Snw141292 } 28104520Snw141292 28114520Snw141292 state.sid2pid_done = TRUE; 28124520Snw141292 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 28134520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 28144520Snw141292 goto out; 28154520Snw141292 28164520Snw141292 /* Update cache */ 28174520Snw141292 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 28184520Snw141292 28194520Snw141292 out: 28204520Snw141292 if (retcode == IDMAP_SUCCESS) { 28214520Snw141292 mapping->direction = idres.direction; 28224520Snw141292 mapping->id2 = idres.id; 28234520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 28244864Sbaban } else { 28254864Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 28264520Snw141292 } 28274520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 28284520Snw141292 return (retcode); 28294520Snw141292 } 28304520Snw141292 28314520Snw141292 idmap_retcode 28324520Snw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 28334520Snw141292 idmap_mapping *mapping, int is_user) { 28344520Snw141292 idmap_id_res idres; 28354520Snw141292 lookup_state_t state; 28364520Snw141292 struct passwd pwd; 28374520Snw141292 struct group grp; 28384520Snw141292 char buf[1024]; 28394520Snw141292 int errnum; 28404520Snw141292 idmap_retcode retcode; 28414520Snw141292 const char *unixname; 28424520Snw141292 const char *me = "get_u2w_mapping"; 28434520Snw141292 28444520Snw141292 /* 28454520Snw141292 * In order to re-use the pid2sid code, we convert 28464520Snw141292 * our input data into structs that are expected by 28474520Snw141292 * pid2sid_first_pass. 28484520Snw141292 */ 28494520Snw141292 28504520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 28514520Snw141292 (void) memset(&state, 0, sizeof (state)); 28524520Snw141292 28534520Snw141292 /* Copy data from request to result */ 28544644Sbaban if (copy_mapping_request(mapping, request) < 0) { 28554644Sbaban retcode = IDMAP_ERR_MEMORY; 28564644Sbaban goto out; 28574644Sbaban } 28584520Snw141292 2859*5064Sdm199847 unixname = mapping->id1name; 28604520Snw141292 28614520Snw141292 if (unixname == NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 28624520Snw141292 retcode = IDMAP_ERR_ARG; 28634520Snw141292 goto out; 28644520Snw141292 } 28654520Snw141292 28664864Sbaban if (unixname != NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 28674520Snw141292 /* Get uid/gid by name */ 28684520Snw141292 if (is_user) { 28694520Snw141292 errno = 0; 28704520Snw141292 if (getpwnam_r(unixname, &pwd, buf, 28714520Snw141292 sizeof (buf)) == NULL) { 28724520Snw141292 errnum = errno; 28734520Snw141292 idmapdlog(LOG_WARNING, 28744520Snw141292 "%s: getpwnam_r(%s) failed (%s).", 28754520Snw141292 me, unixname, 28764520Snw141292 errnum?strerror(errnum):"not found"); 28774520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 28784520Snw141292 IDMAP_ERR_INTERNAL; 28794520Snw141292 goto out; 28804520Snw141292 } 28814520Snw141292 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 28824520Snw141292 } else { 28834520Snw141292 errno = 0; 28844520Snw141292 if (getgrnam_r(unixname, &grp, buf, 28854520Snw141292 sizeof (buf)) == NULL) { 28864520Snw141292 errnum = errno; 28874520Snw141292 idmapdlog(LOG_WARNING, 28884520Snw141292 "%s: getgrnam_r(%s) failed (%s).", 28894520Snw141292 me, unixname, 28904520Snw141292 errnum?strerror(errnum):"not found"); 28914520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 28924520Snw141292 IDMAP_ERR_INTERNAL; 28934520Snw141292 goto out; 28944520Snw141292 } 28954520Snw141292 mapping->id1.idmap_id_u.gid = grp.gr_gid; 28964520Snw141292 } 28974520Snw141292 } 28984520Snw141292 28994520Snw141292 state.pid2sid_done = TRUE; 29004520Snw141292 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 29014520Snw141292 is_user, 1); 29024520Snw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 29034520Snw141292 goto out; 29044520Snw141292 29054520Snw141292 /* Update cache */ 29064520Snw141292 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 29074520Snw141292 29084520Snw141292 out: 29094520Snw141292 mapping->direction = idres.direction; 29104520Snw141292 mapping->id2 = idres.id; 29114520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 29124520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 29134520Snw141292 return (retcode); 29144520Snw141292 } 2915