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 32*5317Sjp151216 #include <atomic.h> 334520Snw141292 #include <stdio.h> 344520Snw141292 #include <stdlib.h> 354520Snw141292 #include <string.h> 364520Snw141292 #include <errno.h> 374520Snw141292 #include <sys/types.h> 384520Snw141292 #include <sys/stat.h> 394520Snw141292 #include <rpc/rpc.h> 404520Snw141292 #include <sys/sid.h> 414520Snw141292 #include <time.h> 424520Snw141292 #include <pwd.h> 434520Snw141292 #include <grp.h> 444884Sjp151216 #include <pthread.h> 454884Sjp151216 #include <assert.h> 464520Snw141292 474520Snw141292 #include "idmapd.h" 484520Snw141292 #include "adutils.h" 494520Snw141292 #include "string.h" 504520Snw141292 #include "idmap_priv.h" 514520Snw141292 524884Sjp151216 53*5317Sjp151216 static int degraded = 0; /* whether the FMRI has been marked degraded */ 54*5317Sjp151216 554520Snw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 564520Snw141292 sqlite_vm **, int *, int, const char ***); 574864Sbaban static idmap_retcode lookup_wksids_name2sid(const char *, char **, 584864Sbaban idmap_rid_t *, int *); 594520Snw141292 604520Snw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 614520Snw141292 624520Snw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 634520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 644520Snw141292 654520Snw141292 #define AVOID_NAMESERVICE(req)\ 664520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 674520Snw141292 684520Snw141292 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 694520Snw141292 704520Snw141292 #define LOCALRID_MIN 1000 714520Snw141292 724520Snw141292 734520Snw141292 744520Snw141292 typedef enum init_db_option { 754520Snw141292 FAIL_IF_CORRUPT = 0, 764520Snw141292 REMOVE_IF_CORRUPT = 1 774520Snw141292 } init_db_option_t; 784520Snw141292 794884Sjp151216 /* 804884Sjp151216 * Thread specfic data to hold the database handles so that the 814884Sjp151216 * databaes are not opened and closed for every request. It also 824884Sjp151216 * contains the sqlite busy handler structure. 834884Sjp151216 */ 844884Sjp151216 854884Sjp151216 struct idmap_busy { 864884Sjp151216 const char *name; 874884Sjp151216 const int *delays; 884884Sjp151216 int delay_size; 894884Sjp151216 int total; 904884Sjp151216 int sec; 914884Sjp151216 }; 924884Sjp151216 934884Sjp151216 944884Sjp151216 typedef struct idmap_tsd { 954884Sjp151216 sqlite *db_db; 964884Sjp151216 sqlite *cache_db; 974884Sjp151216 struct idmap_busy cache_busy; 984884Sjp151216 struct idmap_busy db_busy; 994884Sjp151216 } idmap_tsd_t; 1004884Sjp151216 1014884Sjp151216 1024884Sjp151216 1034884Sjp151216 static const int cache_delay_table[] = 1044884Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 1054884Sjp151216 50, 50, 60, 70, 80, 90, 100}; 1064884Sjp151216 1074884Sjp151216 static const int db_delay_table[] = 1084884Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 1094884Sjp151216 1104884Sjp151216 1114884Sjp151216 static pthread_key_t idmap_tsd_key; 1124884Sjp151216 1134884Sjp151216 void 1144884Sjp151216 idmap_tsd_destroy(void *key) 1154884Sjp151216 { 1164884Sjp151216 1174884Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 1184884Sjp151216 if (tsd) { 1194884Sjp151216 if (tsd->db_db) 1204884Sjp151216 (void) sqlite_close(tsd->db_db); 1214884Sjp151216 if (tsd->cache_db) 1224884Sjp151216 (void) sqlite_close(tsd->cache_db); 1234884Sjp151216 free(tsd); 1244884Sjp151216 } 1254884Sjp151216 } 1264884Sjp151216 1274884Sjp151216 int 1284884Sjp151216 idmap_init_tsd_key(void) { 1294884Sjp151216 1304884Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 1314884Sjp151216 } 1324884Sjp151216 1334884Sjp151216 1344884Sjp151216 1354884Sjp151216 idmap_tsd_t * 1364884Sjp151216 idmap_get_tsd(void) 1374884Sjp151216 { 1384884Sjp151216 idmap_tsd_t *tsd; 1394884Sjp151216 1404884Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 1414884Sjp151216 /* No thread specific data so create it */ 1424884Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 1434884Sjp151216 /* Initialize thread specific data */ 1444884Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 1454884Sjp151216 /* save the trhread specific data */ 1464884Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 1474884Sjp151216 /* Can't store key */ 1484884Sjp151216 free(tsd); 1494884Sjp151216 tsd = NULL; 1504884Sjp151216 } 1514884Sjp151216 } else { 1524884Sjp151216 tsd = NULL; 1534884Sjp151216 } 1544884Sjp151216 } 1554884Sjp151216 1564884Sjp151216 return (tsd); 1574884Sjp151216 } 1584884Sjp151216 159*5317Sjp151216 /* 160*5317Sjp151216 * Wrappers for smf_degrade/restore_instance() 161*5317Sjp151216 * 162*5317Sjp151216 * smf_restore_instance() is too heavy duty to be calling every time we 163*5317Sjp151216 * have a successful AD name<->SID lookup. 164*5317Sjp151216 */ 165*5317Sjp151216 void 166*5317Sjp151216 degrade_svc(void) 167*5317Sjp151216 { 168*5317Sjp151216 membar_consumer(); 169*5317Sjp151216 if (degraded) 170*5317Sjp151216 return; 171*5317Sjp151216 (void) smf_degrade_instance(NULL, 0); 172*5317Sjp151216 membar_producer(); 173*5317Sjp151216 degraded = 1; 174*5317Sjp151216 } 175*5317Sjp151216 176*5317Sjp151216 177*5317Sjp151216 void 178*5317Sjp151216 restore_svc(void) 179*5317Sjp151216 { 180*5317Sjp151216 membar_consumer(); 181*5317Sjp151216 if (!degraded) 182*5317Sjp151216 return; 183*5317Sjp151216 (void) smf_restore_instance(NULL); 184*5317Sjp151216 membar_producer(); 185*5317Sjp151216 degraded = 0; 186*5317Sjp151216 } 1874884Sjp151216 1884520Snw141292 1894520Snw141292 /* 1904520Snw141292 * Initialize 'dbname' using 'sql' 1914520Snw141292 */ 1924520Snw141292 static int 1934520Snw141292 init_db_instance(const char *dbname, const char *sql, init_db_option_t opt, 1944520Snw141292 int *new_db_created) 1954520Snw141292 { 1964520Snw141292 int rc = 0; 1974520Snw141292 int tries = 0; 1984520Snw141292 sqlite *db = NULL; 1994520Snw141292 char *str = NULL; 2004520Snw141292 2014520Snw141292 if (new_db_created != NULL) 2024520Snw141292 *new_db_created = 0; 2034520Snw141292 2044520Snw141292 db = sqlite_open(dbname, 0600, &str); 2054520Snw141292 while (db == NULL) { 2064520Snw141292 idmapdlog(LOG_ERR, 2074520Snw141292 "Error creating database %s (%s)", 2084520Snw141292 dbname, CHECK_NULL(str)); 2094520Snw141292 sqlite_freemem(str); 2104520Snw141292 if (opt == FAIL_IF_CORRUPT || opt != REMOVE_IF_CORRUPT || 2114520Snw141292 tries > 0) 2124520Snw141292 return (-1); 2134520Snw141292 2144520Snw141292 tries++; 2154520Snw141292 (void) unlink(dbname); 2164520Snw141292 db = sqlite_open(dbname, 0600, &str); 2174520Snw141292 } 2184520Snw141292 2194520Snw141292 sqlite_busy_timeout(db, 3000); 2204520Snw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &str); 2214520Snw141292 if (SQLITE_OK != rc) { 2224520Snw141292 idmapdlog(LOG_ERR, "Cannot begin database transaction (%s)", 2234520Snw141292 str); 2244520Snw141292 sqlite_freemem(str); 2254520Snw141292 sqlite_close(db); 2264520Snw141292 return (1); 2274520Snw141292 } 2284520Snw141292 2294520Snw141292 switch (sqlite_exec(db, sql, NULL, NULL, &str)) { 2304520Snw141292 case SQLITE_ERROR: 2314520Snw141292 /* 2324520Snw141292 * This is the normal situation: CREATE probably failed because tables 2334520Snw141292 * already exist. It may indicate an error in SQL as well, but we cannot 2344520Snw141292 * tell. 2354520Snw141292 */ 2364520Snw141292 sqlite_freemem(str); 2374520Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 2384520Snw141292 NULL, NULL, &str); 2394520Snw141292 break; 2404520Snw141292 case SQLITE_OK: 2414520Snw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", 2424520Snw141292 NULL, NULL, &str); 2434520Snw141292 idmapdlog(LOG_INFO, 2444520Snw141292 "Database created at %s", dbname); 2454520Snw141292 2464520Snw141292 if (new_db_created != NULL) 2474520Snw141292 *new_db_created = 1; 2484520Snw141292 break; 2494520Snw141292 default: 2504520Snw141292 idmapdlog(LOG_ERR, 2514520Snw141292 "Error initializing database %s (%s)", 2524520Snw141292 dbname, str); 2534520Snw141292 sqlite_freemem(str); 2544520Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 2554520Snw141292 NULL, NULL, &str); 2564520Snw141292 break; 2574520Snw141292 } 2584520Snw141292 2594520Snw141292 if (SQLITE_OK != rc) { 2604520Snw141292 /* this is bad - database may be left in a locked state */ 2614520Snw141292 idmapdlog(LOG_ERR, 2624520Snw141292 "Error closing transaction (%s)", str); 2634520Snw141292 sqlite_freemem(str); 2644520Snw141292 } 2654520Snw141292 2664520Snw141292 (void) sqlite_close(db); 2674520Snw141292 return (rc); 2684520Snw141292 } 2694520Snw141292 2704884Sjp151216 2714884Sjp151216 /* 2724884Sjp151216 * This is the SQLite database busy handler that retries the SQL 2734884Sjp151216 * operation until it is successful. 2744884Sjp151216 */ 2754884Sjp151216 int 2764884Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 2774884Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 2784884Sjp151216 { 2794884Sjp151216 struct idmap_busy *busy = arg; 2804884Sjp151216 int delay; 2814884Sjp151216 struct timespec rqtp; 2824884Sjp151216 2834884Sjp151216 if (count == 1) { 2844884Sjp151216 busy->total = 0; 2854884Sjp151216 busy->sec = 2; 2864884Sjp151216 } 2874884Sjp151216 if (busy->total > 1000 * busy->sec) { 2884884Sjp151216 idmapdlog(LOG_ERR, 2894884Sjp151216 "Thread %d waited %d sec for the %s database", 2904884Sjp151216 pthread_self(), busy->sec, busy->name); 2914884Sjp151216 busy->sec++; 2924884Sjp151216 } 2934884Sjp151216 2944884Sjp151216 if (count <= busy->delay_size) { 2954884Sjp151216 delay = busy->delays[count-1]; 2964884Sjp151216 } else { 2974884Sjp151216 delay = busy->delays[busy->delay_size - 1]; 2984884Sjp151216 } 2994884Sjp151216 busy->total += delay; 3004884Sjp151216 rqtp.tv_sec = 0; 3014884Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 3024884Sjp151216 (void) nanosleep(&rqtp, NULL); 3034884Sjp151216 return (1); 3044884Sjp151216 } 3054884Sjp151216 3064884Sjp151216 3074520Snw141292 /* 3084520Snw141292 * Get the database handle 3094520Snw141292 */ 3104520Snw141292 idmap_retcode 3114520Snw141292 get_db_handle(sqlite **db) { 3124520Snw141292 char *errmsg; 3134884Sjp151216 idmap_tsd_t *tsd; 3144520Snw141292 3154520Snw141292 /* 3164884Sjp151216 * Retrieve the db handle from thread-specific storage 3174520Snw141292 * If none exists, open and store in thread-specific storage. 3184520Snw141292 */ 3194884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 3204520Snw141292 idmapdlog(LOG_ERR, 3214884Sjp151216 "Error getting thread specific data for %s", 3224884Sjp151216 IDMAP_DBNAME); 3234884Sjp151216 return (IDMAP_ERR_MEMORY); 3244520Snw141292 } 3254884Sjp151216 3264884Sjp151216 if (tsd->db_db == NULL) { 3274884Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 3284884Sjp151216 if (tsd->db_db == NULL) { 3294884Sjp151216 idmapdlog(LOG_ERR, 3304884Sjp151216 "Error opening database %s (%s)", 3314884Sjp151216 IDMAP_DBNAME, CHECK_NULL(errmsg)); 3324884Sjp151216 sqlite_freemem(errmsg); 3334884Sjp151216 return (IDMAP_ERR_INTERNAL); 3344884Sjp151216 } 3354884Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 3364884Sjp151216 tsd->db_busy.delays = db_delay_table; 3374884Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 3384884Sjp151216 sizeof (int); 3394884Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 3404884Sjp151216 &tsd->db_busy); 3414884Sjp151216 } 3424884Sjp151216 *db = tsd->db_db; 3434520Snw141292 return (IDMAP_SUCCESS); 3444520Snw141292 } 3454520Snw141292 3464520Snw141292 /* 3474520Snw141292 * Get the cache handle 3484520Snw141292 */ 3494520Snw141292 idmap_retcode 3504884Sjp151216 get_cache_handle(sqlite **cache) { 3514520Snw141292 char *errmsg; 3524884Sjp151216 idmap_tsd_t *tsd; 3534520Snw141292 3544520Snw141292 /* 3554884Sjp151216 * Retrieve the db handle from thread-specific storage 3564520Snw141292 * If none exists, open and store in thread-specific storage. 3574520Snw141292 */ 3584884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 3594520Snw141292 idmapdlog(LOG_ERR, 3604884Sjp151216 "Error getting thread specific data for %s", 3614884Sjp151216 IDMAP_DBNAME); 3624884Sjp151216 return (IDMAP_ERR_MEMORY); 3634520Snw141292 } 3644884Sjp151216 3654884Sjp151216 if (tsd->cache_db == NULL) { 3664884Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 3674884Sjp151216 if (tsd->cache_db == NULL) { 3684884Sjp151216 idmapdlog(LOG_ERR, 3694884Sjp151216 "Error opening database %s (%s)", 3704884Sjp151216 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 3714884Sjp151216 sqlite_freemem(errmsg); 3724884Sjp151216 return (IDMAP_ERR_INTERNAL); 3734884Sjp151216 } 3744884Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 3754884Sjp151216 tsd->cache_busy.delays = cache_delay_table; 3764884Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 3774884Sjp151216 sizeof (int); 3784884Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 3794884Sjp151216 &tsd->cache_busy); 3804884Sjp151216 } 3814884Sjp151216 *cache = tsd->cache_db; 3824520Snw141292 return (IDMAP_SUCCESS); 3834520Snw141292 } 3844520Snw141292 3854520Snw141292 #define CACHE_SQL\ 3864520Snw141292 "CREATE TABLE idmap_cache ("\ 3874520Snw141292 " sidprefix TEXT,"\ 3884520Snw141292 " rid INTEGER,"\ 3894520Snw141292 " windomain TEXT,"\ 3904520Snw141292 " winname TEXT,"\ 3914520Snw141292 " pid INTEGER,"\ 3924520Snw141292 " unixname TEXT,"\ 3934520Snw141292 " is_user INTEGER,"\ 3944520Snw141292 " w2u INTEGER,"\ 3954520Snw141292 " u2w INTEGER,"\ 3964520Snw141292 " expiration INTEGER"\ 3974520Snw141292 ");"\ 3984520Snw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache"\ 3994520Snw141292 " (sidprefix, rid, w2u);"\ 4004520Snw141292 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache"\ 4014520Snw141292 " (pid, is_user, u2w);"\ 4024520Snw141292 "CREATE TABLE name_cache ("\ 4034520Snw141292 " sidprefix TEXT,"\ 4044520Snw141292 " rid INTEGER,"\ 4054520Snw141292 " name TEXT,"\ 4064520Snw141292 " domain TEXT,"\ 4074520Snw141292 " type INTEGER,"\ 4084520Snw141292 " expiration INTEGER"\ 4094520Snw141292 ");"\ 4104520Snw141292 "CREATE UNIQUE INDEX name_cache_sid ON name_cache"\ 4114520Snw141292 " (sidprefix, rid);" 4124520Snw141292 4134520Snw141292 #define DB_SQL\ 4144520Snw141292 "CREATE TABLE namerules ("\ 4154520Snw141292 " is_user INTEGER NOT NULL,"\ 4164520Snw141292 " windomain TEXT,"\ 4174520Snw141292 " winname TEXT NOT NULL,"\ 4184520Snw141292 " is_nt4 INTEGER NOT NULL,"\ 4194520Snw141292 " unixname NOT NULL,"\ 4204520Snw141292 " w2u_order INTEGER,"\ 4214520Snw141292 " u2w_order INTEGER"\ 4224520Snw141292 ");"\ 4234520Snw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules"\ 4244520Snw141292 " (winname, windomain, is_user, w2u_order);"\ 4254520Snw141292 "CREATE UNIQUE INDEX namerules_u2w ON namerules"\ 4264520Snw141292 " (unixname, is_user, u2w_order);" 4274520Snw141292 4284520Snw141292 /* 4294520Snw141292 * Initialize cache and db 4304520Snw141292 */ 4314520Snw141292 int 4324520Snw141292 init_dbs() { 4334520Snw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 4344520Snw141292 if (init_db_instance(IDMAP_DBNAME, DB_SQL, FAIL_IF_CORRUPT, NULL) < 0) 4354520Snw141292 return (-1); 4364520Snw141292 4374520Snw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 4384520Snw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_SQL, REMOVE_IF_CORRUPT, 4394520Snw141292 &_idmapdstate.new_eph_db) < 0) 4404520Snw141292 return (-1); 4414520Snw141292 4424520Snw141292 return (0); 4434520Snw141292 } 4444520Snw141292 4454520Snw141292 /* 4464520Snw141292 * Finalize databases 4474520Snw141292 */ 4484520Snw141292 void 4494520Snw141292 fini_dbs() { 4504520Snw141292 } 4514520Snw141292 4524520Snw141292 /* 4534520Snw141292 * This table is a listing of status codes that will returned to the 4544520Snw141292 * client when a SQL command fails with the corresponding error message. 4554520Snw141292 */ 4564520Snw141292 static msg_table_t sqlmsgtable[] = { 4574864Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 4584520Snw141292 "columns unixname, is_user, u2w_order are not unique"}, 4594864Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 4604520Snw141292 "columns winname, windomain, is_user, w2u_order are not unique"}, 4614520Snw141292 {-1, NULL} 4624520Snw141292 }; 4634520Snw141292 4644520Snw141292 /* 4654520Snw141292 * idmapd's version of string2stat to map SQLite messages to 4664520Snw141292 * status codes 4674520Snw141292 */ 4684520Snw141292 idmap_retcode 4694520Snw141292 idmapd_string2stat(const char *msg) { 4704520Snw141292 int i; 4714520Snw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 4724520Snw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 4734520Snw141292 return (sqlmsgtable[i].retcode); 4744520Snw141292 } 4754520Snw141292 return (IDMAP_ERR_OTHER); 4764520Snw141292 } 4774520Snw141292 4784520Snw141292 /* 4794520Snw141292 * Execute the given SQL statment without using any callbacks 4804520Snw141292 */ 4814520Snw141292 idmap_retcode 4824520Snw141292 sql_exec_no_cb(sqlite *db, char *sql) { 4834520Snw141292 char *errmsg = NULL; 4844884Sjp151216 int r; 4854520Snw141292 idmap_retcode retcode; 4864520Snw141292 4874884Sjp151216 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 4884884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 4894520Snw141292 4904520Snw141292 if (r != SQLITE_OK) { 4914520Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 4924520Snw141292 sql, CHECK_NULL(errmsg)); 4934884Sjp151216 retcode = idmapd_string2stat(errmsg); 4944864Sbaban if (errmsg != NULL) 4954520Snw141292 sqlite_freemem(errmsg); 4964520Snw141292 return (retcode); 4974520Snw141292 } 4984520Snw141292 4994520Snw141292 return (IDMAP_SUCCESS); 5004520Snw141292 } 5014520Snw141292 5024520Snw141292 /* 5034520Snw141292 * Generate expression that can be used in WHERE statements. 5044520Snw141292 * Examples: 5054520Snw141292 * <prefix> <col> <op> <value> <suffix> 5064520Snw141292 * "" "unixuser" "=" "foo" "AND" 5074520Snw141292 */ 5084520Snw141292 idmap_retcode 5094520Snw141292 gen_sql_expr_from_utf8str(const char *prefix, const char *col, 5105064Sdm199847 const char *op, char *value, 5114520Snw141292 const char *suffix, char **out) { 5124520Snw141292 if (out == NULL) 5134520Snw141292 return (IDMAP_ERR_ARG); 5144520Snw141292 5154520Snw141292 if (value == NULL) 5164520Snw141292 return (IDMAP_SUCCESS); 5174520Snw141292 5184520Snw141292 if (prefix == NULL) 5194520Snw141292 prefix = ""; 5204520Snw141292 if (suffix == NULL) 5214520Snw141292 suffix = ""; 5224520Snw141292 5234520Snw141292 *out = sqlite_mprintf("%s %s %s %Q %s", 5245064Sdm199847 prefix, col, op, value, suffix); 5254520Snw141292 if (*out == NULL) 5264520Snw141292 return (IDMAP_ERR_MEMORY); 5274520Snw141292 return (IDMAP_SUCCESS); 5284520Snw141292 } 5294520Snw141292 5304520Snw141292 /* 5314520Snw141292 * Generate and execute SQL statement for LIST RPC calls 5324520Snw141292 */ 5334520Snw141292 idmap_retcode 5344520Snw141292 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 5354520Snw141292 list_svc_cb cb, void *result) { 5364520Snw141292 list_cb_data_t cb_data; 5374520Snw141292 char *errmsg = NULL; 5384884Sjp151216 int r; 5394520Snw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 5404520Snw141292 5414520Snw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 5424520Snw141292 cb_data.result = result; 5434520Snw141292 cb_data.limit = limit; 5444520Snw141292 5454884Sjp151216 5464884Sjp151216 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 5474884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 5484884Sjp151216 switch (r) { 5494884Sjp151216 case SQLITE_OK: 5504884Sjp151216 retcode = IDMAP_SUCCESS; 5514884Sjp151216 break; 5524884Sjp151216 5534884Sjp151216 default: 5544884Sjp151216 retcode = IDMAP_ERR_INTERNAL; 5554884Sjp151216 idmapdlog(LOG_ERR, 5564884Sjp151216 "Database error during %s (%s)", 5574884Sjp151216 sql, CHECK_NULL(errmsg)); 5584884Sjp151216 break; 5594520Snw141292 } 5604864Sbaban if (errmsg != NULL) 5614520Snw141292 sqlite_freemem(errmsg); 5624520Snw141292 return (retcode); 5634520Snw141292 } 5644520Snw141292 5654520Snw141292 /* 5664520Snw141292 * This routine is called by callbacks that process the results of 5674520Snw141292 * LIST RPC calls to validate data and to allocate memory for 5684520Snw141292 * the result array. 5694520Snw141292 */ 5704520Snw141292 idmap_retcode 5714520Snw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 5724520Snw141292 int ncol, uchar_t **list, size_t valsize) { 5734520Snw141292 size_t nsize; 5744520Snw141292 void *tmplist; 5754520Snw141292 5764520Snw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 5774520Snw141292 return (IDMAP_NEXT); 5784520Snw141292 5794520Snw141292 if (argc < ncol || argv == NULL) { 5804520Snw141292 idmapdlog(LOG_ERR, "Invalid data"); 5814520Snw141292 return (IDMAP_ERR_INTERNAL); 5824520Snw141292 } 5834520Snw141292 5844520Snw141292 /* alloc in bulk to reduce number of reallocs */ 5854520Snw141292 if (cb_data->next >= cb_data->len) { 5864520Snw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 5874520Snw141292 tmplist = realloc(*list, nsize); 5884520Snw141292 if (tmplist == NULL) { 5894520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 5904520Snw141292 return (IDMAP_ERR_MEMORY); 5914520Snw141292 } 5924520Snw141292 *list = tmplist; 5934520Snw141292 (void) memset(*list + (cb_data->len * valsize), 0, 5944520Snw141292 SIZE_INCR * valsize); 5954520Snw141292 cb_data->len += SIZE_INCR; 5964520Snw141292 } 5974520Snw141292 return (IDMAP_SUCCESS); 5984520Snw141292 } 5994520Snw141292 6004520Snw141292 static idmap_retcode 6014520Snw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 6024520Snw141292 int direction, int *w2u_order, int *u2w_order) { 6034520Snw141292 6044520Snw141292 *w2u_order = 0; 6054520Snw141292 *u2w_order = 0; 6064520Snw141292 6074520Snw141292 /* 6084520Snw141292 * Windows to UNIX lookup order: 6094520Snw141292 * 1. winname@domain (or winname) to "" 6104520Snw141292 * 2. winname@domain (or winname) to unixname 6114520Snw141292 * 3. winname@* to "" 6124520Snw141292 * 4. winname@* to unixname 6134520Snw141292 * 5. *@domain (or *) to * 6144520Snw141292 * 6. *@domain (or *) to "" 6154520Snw141292 * 7. *@domain (or *) to unixname 6164520Snw141292 * 8. *@* to * 6174520Snw141292 * 9. *@* to "" 6184520Snw141292 * 10. *@* to unixname 6194520Snw141292 * 6204520Snw141292 * winname is a special case of winname@domain when domain is the 6214520Snw141292 * default domain. Similarly * is a special case of *@domain when 6224520Snw141292 * domain is the default domain. 6234520Snw141292 * 6244520Snw141292 * Note that "" has priority over specific names because "" inhibits 6254520Snw141292 * mappings and traditionally deny rules always had higher priority. 6264520Snw141292 */ 6274644Sbaban if (direction != IDMAP_DIRECTION_U2W) { 6284644Sbaban /* bi-directional or from windows to unix */ 6294520Snw141292 if (winname == NULL) 6304520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6314520Snw141292 else if (unixname == NULL) 6324520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6334520Snw141292 else if (EMPTY_NAME(winname)) 6344520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6354520Snw141292 else if (*winname == '*' && windomain && *windomain == '*') { 6364520Snw141292 if (*unixname == '*') 6374520Snw141292 *w2u_order = 8; 6384520Snw141292 else if (EMPTY_NAME(unixname)) 6394520Snw141292 *w2u_order = 9; 6404520Snw141292 else /* unixname == name */ 6414520Snw141292 *w2u_order = 10; 6424520Snw141292 } else if (*winname == '*') { 6434520Snw141292 if (*unixname == '*') 6444520Snw141292 *w2u_order = 5; 6454520Snw141292 else if (EMPTY_NAME(unixname)) 6464520Snw141292 *w2u_order = 6; 6474520Snw141292 else /* name */ 6484520Snw141292 *w2u_order = 7; 6494864Sbaban } else if (windomain != NULL && *windomain == '*') { 6504520Snw141292 /* winname == name */ 6514520Snw141292 if (*unixname == '*') 6524520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6534520Snw141292 else if (EMPTY_NAME(unixname)) 6544520Snw141292 *w2u_order = 3; 6554520Snw141292 else /* name */ 6564520Snw141292 *w2u_order = 4; 6574520Snw141292 } else { 6584520Snw141292 /* winname == name && windomain == null or name */ 6594520Snw141292 if (*unixname == '*') 6604520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6614520Snw141292 else if (EMPTY_NAME(unixname)) 6624520Snw141292 *w2u_order = 1; 6634520Snw141292 else /* name */ 6644520Snw141292 *w2u_order = 2; 6654520Snw141292 } 6664520Snw141292 } 6674520Snw141292 6684520Snw141292 /* 6694520Snw141292 * 1. unixname to "" 6704520Snw141292 * 2. unixname to winname@domain (or winname) 6714520Snw141292 * 3. * to *@domain (or *) 6724520Snw141292 * 4. * to "" 6734520Snw141292 * 5. * to winname@domain (or winname) 6744520Snw141292 */ 6754644Sbaban if (direction != IDMAP_DIRECTION_W2U) { 6764644Sbaban /* bi-directional or from unix to windows */ 6774520Snw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 6784520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6794520Snw141292 else if (winname == NULL) 6804520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6814864Sbaban else if (windomain != NULL && *windomain == '*') 6824644Sbaban return (IDMAP_ERR_U2W_NAMERULE); 6834520Snw141292 else if (*unixname == '*') { 6844520Snw141292 if (*winname == '*') 6854520Snw141292 *u2w_order = 3; 6864520Snw141292 else if (EMPTY_NAME(winname)) 6874520Snw141292 *u2w_order = 4; 6884520Snw141292 else 6894520Snw141292 *u2w_order = 5; 6904520Snw141292 } else { 6914520Snw141292 if (*winname == '*') 6924520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6934520Snw141292 else if (EMPTY_NAME(winname)) 6944520Snw141292 *u2w_order = 1; 6954520Snw141292 else 6964520Snw141292 *u2w_order = 2; 6974520Snw141292 } 6984520Snw141292 } 6994520Snw141292 return (IDMAP_SUCCESS); 7004520Snw141292 } 7014520Snw141292 7024520Snw141292 /* 7034520Snw141292 * Generate and execute SQL statement to add name-based mapping rule 7044520Snw141292 */ 7054520Snw141292 idmap_retcode 7064520Snw141292 add_namerule(sqlite *db, idmap_namerule *rule) { 7074520Snw141292 char *sql = NULL; 7084520Snw141292 idmap_stat retcode; 7095064Sdm199847 char *dom = NULL; 7104520Snw141292 int w2u_order, u2w_order; 7114520Snw141292 char w2ubuf[11], u2wbuf[11]; 7124520Snw141292 7135064Sdm199847 retcode = get_namerule_order(rule->winname, rule->windomain, 7145064Sdm199847 rule->unixname, rule->direction, &w2u_order, &u2w_order); 7154520Snw141292 if (retcode != IDMAP_SUCCESS) 7164520Snw141292 goto out; 7174520Snw141292 7184520Snw141292 if (w2u_order) 7194520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 7204520Snw141292 if (u2w_order) 7214520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 7224520Snw141292 7234864Sbaban /* 7244864Sbaban * For the triggers on namerules table to work correctly: 7254864Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 7264864Sbaban * 2) Use "" instead of NULL for "no domain" 7274864Sbaban */ 7284864Sbaban 7295064Sdm199847 if (rule->windomain != NULL) 7305064Sdm199847 dom = rule->windomain; 7315064Sdm199847 else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL) 7324864Sbaban == IDMAP_SUCCESS) { 7334864Sbaban /* well-known SIDs don't need domain */ 7344864Sbaban dom = ""; 7354864Sbaban } 7364520Snw141292 7374520Snw141292 RDLOCK_CONFIG(); 7384864Sbaban if (dom == NULL) { 739*5317Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain) 740*5317Sjp151216 dom = _idmapdstate.cfg->pgcfg.default_domain; 7414864Sbaban else 7424864Sbaban dom = ""; 7434864Sbaban } 7444884Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 7454520Snw141292 "(is_user, windomain, winname, is_nt4, " 7464520Snw141292 "unixname, w2u_order, u2w_order) " 7474520Snw141292 "VALUES(%d, %Q, %Q, %d, %Q, %q, %q);", 7484520Snw141292 rule->is_user?1:0, 7494520Snw141292 dom, 7505064Sdm199847 rule->winname, rule->is_nt4?1:0, 7515064Sdm199847 rule->unixname, 7524520Snw141292 w2u_order?w2ubuf:NULL, 7534520Snw141292 u2w_order?u2wbuf:NULL); 7544520Snw141292 UNLOCK_CONFIG(); 7554520Snw141292 7564520Snw141292 if (sql == NULL) { 7574520Snw141292 retcode = IDMAP_ERR_INTERNAL; 7584520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7594520Snw141292 goto out; 7604520Snw141292 } 7614520Snw141292 7624520Snw141292 retcode = sql_exec_no_cb(db, sql); 7634520Snw141292 7644520Snw141292 if (retcode == IDMAP_ERR_OTHER) 7654520Snw141292 retcode = IDMAP_ERR_CFG; 7664520Snw141292 7674520Snw141292 out: 7684864Sbaban if (sql != NULL) 7694520Snw141292 sqlite_freemem(sql); 7704520Snw141292 return (retcode); 7714520Snw141292 } 7724520Snw141292 7734520Snw141292 /* 7744520Snw141292 * Flush name-based mapping rules 7754520Snw141292 */ 7764520Snw141292 idmap_retcode 7774520Snw141292 flush_namerules(sqlite *db, bool_t is_user) { 7784520Snw141292 char *sql = NULL; 7794520Snw141292 idmap_stat retcode; 7804520Snw141292 7814520Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 7824520Snw141292 "is_user = %d;", is_user?1:0); 7834520Snw141292 7844520Snw141292 if (sql == NULL) { 7854520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7864520Snw141292 return (IDMAP_ERR_MEMORY); 7874520Snw141292 } 7884520Snw141292 7894520Snw141292 retcode = sql_exec_no_cb(db, sql); 7904520Snw141292 7914520Snw141292 sqlite_freemem(sql); 7924520Snw141292 return (retcode); 7934520Snw141292 } 7944520Snw141292 7954520Snw141292 /* 7964520Snw141292 * Generate and execute SQL statement to remove a name-based mapping rule 7974520Snw141292 */ 7984520Snw141292 idmap_retcode 7994520Snw141292 rm_namerule(sqlite *db, idmap_namerule *rule) { 8004520Snw141292 char *sql = NULL; 8014520Snw141292 idmap_stat retcode; 8024520Snw141292 char *s_windomain = NULL, *s_winname = NULL; 8034520Snw141292 char *s_unixname = NULL; 8044520Snw141292 char buf[80]; 8054520Snw141292 8065064Sdm199847 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 8075064Sdm199847 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 8084520Snw141292 return (IDMAP_SUCCESS); 8094520Snw141292 8104520Snw141292 if (rule->direction < 0) { 8114520Snw141292 buf[0] = 0; 8124644Sbaban } else if (rule->direction == IDMAP_DIRECTION_BI) { 8134520Snw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 8144520Snw141292 " AND u2w_order > 0"); 8154644Sbaban } else if (rule->direction == IDMAP_DIRECTION_W2U) { 8164520Snw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 8174520Snw141292 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 8184644Sbaban } else if (rule->direction == IDMAP_DIRECTION_U2W) { 8194520Snw141292 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 8204520Snw141292 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 8214520Snw141292 } 8224520Snw141292 8234520Snw141292 retcode = IDMAP_ERR_INTERNAL; 8245064Sdm199847 if (!EMPTY_STRING(rule->windomain)) { 8254520Snw141292 if (gen_sql_expr_from_utf8str("AND", "windomain", "=", 8265064Sdm199847 rule->windomain, "", &s_windomain) != IDMAP_SUCCESS) 8274520Snw141292 goto out; 8284520Snw141292 } 8294520Snw141292 8305064Sdm199847 if (!EMPTY_STRING(rule->winname)) { 8314520Snw141292 if (gen_sql_expr_from_utf8str("AND", "winname", "=", 8325064Sdm199847 rule->winname, "", &s_winname) != IDMAP_SUCCESS) 8334520Snw141292 goto out; 8344520Snw141292 } 8354520Snw141292 8365064Sdm199847 if (!EMPTY_STRING(rule->unixname)) { 8374520Snw141292 if (gen_sql_expr_from_utf8str("AND", "unixname", "=", 8385064Sdm199847 rule->unixname, "", &s_unixname) != IDMAP_SUCCESS) 8394520Snw141292 goto out; 8404520Snw141292 } 8414520Snw141292 8424520Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 8434520Snw141292 "is_user = %d %s %s %s %s;", 8444520Snw141292 rule->is_user?1:0, 8454520Snw141292 s_windomain?s_windomain:"", 8464520Snw141292 s_winname?s_winname:"", 8474520Snw141292 s_unixname?s_unixname:"", 8484520Snw141292 buf); 8494520Snw141292 8504520Snw141292 if (sql == NULL) { 8514520Snw141292 retcode = IDMAP_ERR_INTERNAL; 8524520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 8534520Snw141292 goto out; 8544520Snw141292 } 8554520Snw141292 8564520Snw141292 retcode = sql_exec_no_cb(db, sql); 8574520Snw141292 8584520Snw141292 out: 8594864Sbaban if (s_windomain != NULL) 8604520Snw141292 sqlite_freemem(s_windomain); 8614864Sbaban if (s_winname != NULL) 8624520Snw141292 sqlite_freemem(s_winname); 8634864Sbaban if (s_unixname != NULL) 8644520Snw141292 sqlite_freemem(s_unixname); 8654864Sbaban if (sql != NULL) 8664520Snw141292 sqlite_freemem(sql); 8674520Snw141292 return (retcode); 8684520Snw141292 } 8694520Snw141292 8704520Snw141292 /* 8714520Snw141292 * Compile the given SQL query and step just once. 8724520Snw141292 * 8734520Snw141292 * Input: 8744520Snw141292 * db - db handle 8754520Snw141292 * sql - SQL statement 8764520Snw141292 * 8774520Snw141292 * Output: 8784520Snw141292 * vm - virtual SQL machine 8794520Snw141292 * ncol - number of columns in the result 8804520Snw141292 * values - column values 8814520Snw141292 * 8824520Snw141292 * Return values: 8834520Snw141292 * IDMAP_SUCCESS 8844520Snw141292 * IDMAP_ERR_NOTFOUND 8854520Snw141292 * IDMAP_ERR_INTERNAL 8864520Snw141292 */ 8874520Snw141292 8884520Snw141292 static idmap_retcode 8894520Snw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 8904520Snw141292 int reqcol, const char ***values) { 8914520Snw141292 char *errmsg = NULL; 8924884Sjp151216 int r; 8934884Sjp151216 8944884Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 8954520Snw141292 idmapdlog(LOG_ERR, 8964520Snw141292 "Database error during %s (%s)", 8974520Snw141292 sql, CHECK_NULL(errmsg)); 8984520Snw141292 sqlite_freemem(errmsg); 8994520Snw141292 return (IDMAP_ERR_INTERNAL); 9004520Snw141292 } 9014520Snw141292 9024884Sjp151216 r = sqlite_step(*vm, ncol, values, NULL); 9034884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 9044884Sjp151216 9054884Sjp151216 if (r == SQLITE_ROW) { 9064864Sbaban if (ncol != NULL && *ncol < reqcol) { 9074520Snw141292 (void) sqlite_finalize(*vm, NULL); 9084520Snw141292 *vm = NULL; 9094520Snw141292 return (IDMAP_ERR_INTERNAL); 9104520Snw141292 } 9114520Snw141292 /* Caller will call finalize after using the results */ 9124520Snw141292 return (IDMAP_SUCCESS); 9134520Snw141292 } else if (r == SQLITE_DONE) { 9144520Snw141292 (void) sqlite_finalize(*vm, NULL); 9154520Snw141292 *vm = NULL; 9164520Snw141292 return (IDMAP_ERR_NOTFOUND); 9174520Snw141292 } 9184520Snw141292 9194520Snw141292 (void) sqlite_finalize(*vm, &errmsg); 9204520Snw141292 *vm = NULL; 9214520Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 9224884Sjp151216 sql, CHECK_NULL(errmsg)); 9234520Snw141292 sqlite_freemem(errmsg); 9244520Snw141292 return (IDMAP_ERR_INTERNAL); 9254520Snw141292 } 9264520Snw141292 9274864Sbaban /* 9284864Sbaban * Table for well-known SIDs. 9294864Sbaban * 9304864Sbaban * Background: 9314864Sbaban * 9325191Sbaban * Some of the well-known principals are stored under: 9334864Sbaban * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 9344864Sbaban * They belong to objectClass "foreignSecurityPrincipal". They don't have 9354864Sbaban * "samAccountName" nor "userPrincipalName" attributes. Their names are 9364864Sbaban * available in "cn" and "name" attributes. Some of these principals have a 9374864Sbaban * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 9384864Sbaban * these duplicate entries have the stringified SID in the "name" and "cn" 9394864Sbaban * attributes instead of the actual name. 9404864Sbaban * 9415191Sbaban * Those of the form S-1-5-32-X are Builtin groups and are stored in the 9425191Sbaban * cn=builtin container (except, Power Users which is not stored in AD) 9434864Sbaban * 9445191Sbaban * These principals are and will remain constant. Therefore doing AD lookups 9455191Sbaban * provides no benefit. Also, using hard-coded table (and thus avoiding AD 9465191Sbaban * lookup) improves performance and avoids additional complexity in the 9475191Sbaban * adutils.c code. Moreover these SIDs can be used when no Active Directory 9485191Sbaban * is available (such as the CIFS server's "workgroup" mode). 9495191Sbaban * 9505191Sbaban * Notes: 9515191Sbaban * 1. Currently we don't support localization of well-known SID names, 9524864Sbaban * unlike Windows. 9534864Sbaban * 9545191Sbaban * 2. Other well-known SIDs i.e. S-1-5-<domain>-<w-k RID> are not stored 9555191Sbaban * here. AD does have normal user/group objects for these objects and 9565191Sbaban * can be looked up using the existing AD lookup code. 9574864Sbaban */ 9584864Sbaban static wksids_table_t wksids[] = { 9594864Sbaban {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 9604864Sbaban {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 9614864Sbaban {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 9624864Sbaban {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 9634864Sbaban {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 9645191Sbaban {"S-1-3", 4, "Owner Rights", 0, SENTINEL_PID, -1}, 9654864Sbaban {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 9664864Sbaban {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 9674864Sbaban {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 9684864Sbaban {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 9694864Sbaban {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 9704864Sbaban {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 9714864Sbaban {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 9724864Sbaban {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 9734864Sbaban {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 9744864Sbaban {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 9754864Sbaban {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 9764864Sbaban {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 9774864Sbaban {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 9784864Sbaban {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 9795191Sbaban {"S-1-5", 17, "IUSR", 0, SENTINEL_PID, -1}, 9804864Sbaban {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 9814864Sbaban {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 9824864Sbaban {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 9834864Sbaban {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 9845191Sbaban {"S-1-5-32", 544, "Administrators", 0, SENTINEL_PID, -1}, 9855191Sbaban {"S-1-5-32", 545, "Users", 0, SENTINEL_PID, -1}, 9865191Sbaban {"S-1-5-32", 546, "Guests", 0, SENTINEL_PID, -1}, 9875191Sbaban {"S-1-5-32", 547, "Power Users", 0, SENTINEL_PID, -1}, 9885191Sbaban {"S-1-5-32", 548, "Account Operators", 0, SENTINEL_PID, -1}, 9895191Sbaban {"S-1-5-32", 549, "Server Operators", 0, SENTINEL_PID, -1}, 9905191Sbaban {"S-1-5-32", 550, "Print Operators", 0, SENTINEL_PID, -1}, 9915191Sbaban {"S-1-5-32", 551, "Backup Operators", 0, SENTINEL_PID, -1}, 9925191Sbaban {"S-1-5-32", 552, "Replicator", 0, SENTINEL_PID, -1}, 9935191Sbaban {"S-1-5-32", 554, "Pre-Windows 2000 Compatible Access", 0, 9945191Sbaban SENTINEL_PID, -1}, 9955191Sbaban {"S-1-5-32", 555, "Remote Desktop Users", 0, SENTINEL_PID, -1}, 9965191Sbaban {"S-1-5-32", 556, "Network Configuration Operators", 0, 9975191Sbaban SENTINEL_PID, -1}, 9985191Sbaban {"S-1-5-32", 557, "Incoming Forest Trust Builders", 0, 9995191Sbaban SENTINEL_PID, -1}, 10005191Sbaban {"S-1-5-32", 558, "Performance Monitor Users", 0, SENTINEL_PID, -1}, 10015191Sbaban {"S-1-5-32", 559, "Performance Log Users", 0, SENTINEL_PID, -1}, 10025191Sbaban {"S-1-5-32", 560, "Windows Authorization Access Group", 0, 10035191Sbaban SENTINEL_PID, -1}, 10045191Sbaban {"S-1-5-32", 561, "Terminal Server License Servers", 0, 10055191Sbaban SENTINEL_PID, -1}, 10065191Sbaban {"S-1-5-32", 561, "Distributed COM Users", 0, SENTINEL_PID, -1}, 10075191Sbaban {"S-1-5-32", 568, "IIS_IUSRS", 0, SENTINEL_PID, -1}, 10085191Sbaban {"S-1-5-32", 569, "Cryptograhic Operators", 0, SENTINEL_PID, -1}, 10095191Sbaban {"S-1-5-32", 573, "Event Log Readers", 0, SENTINEL_PID, -1}, 10105191Sbaban {"S-1-5-32", 574, "Certificate Service DCOM Access", 0, 10115191Sbaban SENTINEL_PID, -1}, 10124864Sbaban {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 10134864Sbaban {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 10144864Sbaban {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 10154864Sbaban {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 10164520Snw141292 }; 10174520Snw141292 10184520Snw141292 static idmap_retcode 10194520Snw141292 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) { 10204520Snw141292 int i; 10214864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10224864Sbaban if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 10234864Sbaban (strcasecmp(wksids[i].sidprefix, 10244864Sbaban req->id1.idmap_id_u.sid.prefix) == 0)) { 10254864Sbaban 10264864Sbaban if (wksids[i].pid == SENTINEL_PID) 10274864Sbaban /* Not mapped, break */ 10284864Sbaban break; 10294864Sbaban else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 10304864Sbaban continue; 10314864Sbaban 10324520Snw141292 switch (req->id2.idtype) { 10334520Snw141292 case IDMAP_UID: 10344864Sbaban if (wksids[i].is_user == 0) 10354864Sbaban continue; 10364864Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 10374864Sbaban res->direction = wksids[i].direction; 10384520Snw141292 return (IDMAP_SUCCESS); 10394520Snw141292 case IDMAP_GID: 10404864Sbaban if (wksids[i].is_user == 1) 10414864Sbaban continue; 10424864Sbaban res->id.idmap_id_u.gid = wksids[i].pid; 10434864Sbaban res->direction = wksids[i].direction; 10444520Snw141292 return (IDMAP_SUCCESS); 10454520Snw141292 case IDMAP_POSIXID: 10464864Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 10474864Sbaban res->id.idtype = (!wksids[i].is_user)? 10484520Snw141292 IDMAP_GID:IDMAP_UID; 10494864Sbaban res->direction = wksids[i].direction; 10504520Snw141292 return (IDMAP_SUCCESS); 10514520Snw141292 default: 10524520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 10534520Snw141292 } 10544520Snw141292 } 10554520Snw141292 } 10564520Snw141292 return (IDMAP_ERR_NOTFOUND); 10574520Snw141292 } 10584520Snw141292 10594520Snw141292 static idmap_retcode 10604520Snw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) { 10614520Snw141292 int i; 10624864Sbaban if (req->id2.idtype != IDMAP_SID) 10634864Sbaban return (IDMAP_ERR_NOTSUPPORTED); 10644864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10654864Sbaban if (wksids[i].pid == req->id1.idmap_id_u.uid && 10664864Sbaban wksids[i].is_user == is_user && 10674864Sbaban wksids[i].direction != IDMAP_DIRECTION_W2U) { 10684864Sbaban res->id.idmap_id_u.sid.rid = wksids[i].rid; 10694864Sbaban res->id.idmap_id_u.sid.prefix = 10704864Sbaban strdup(wksids[i].sidprefix); 10714864Sbaban if (res->id.idmap_id_u.sid.prefix == NULL) { 10724864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10734864Sbaban return (IDMAP_ERR_MEMORY); 10744520Snw141292 } 10754864Sbaban res->direction = wksids[i].direction; 10764864Sbaban return (IDMAP_SUCCESS); 10774864Sbaban } 10784864Sbaban } 10794864Sbaban return (IDMAP_ERR_NOTFOUND); 10804864Sbaban } 10814864Sbaban 10824864Sbaban static idmap_retcode 10834864Sbaban lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 10844864Sbaban int *type) { 10854864Sbaban int i; 10864864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10874864Sbaban if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 10884864Sbaban wksids[i].rid == rid) { 10894864Sbaban if ((*name = strdup(wksids[i].winname)) == NULL) { 10904864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10914864Sbaban return (IDMAP_ERR_MEMORY); 10924864Sbaban } 10934864Sbaban *type = (wksids[i].is_user)? 10944864Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 10954864Sbaban return (IDMAP_SUCCESS); 10964864Sbaban } 10974864Sbaban } 10984864Sbaban return (IDMAP_ERR_NOTFOUND); 10994864Sbaban } 11004864Sbaban 11014864Sbaban static idmap_retcode 11024864Sbaban lookup_wksids_name2sid(const char *name, char **sidprefix, idmap_rid_t *rid, 11034864Sbaban int *type) { 11044864Sbaban int i; 11054864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 11064864Sbaban if (strcasecmp(wksids[i].winname, name) == 0) { 11074864Sbaban if (sidprefix != NULL && (*sidprefix = 11084864Sbaban strdup(wksids[i].sidprefix)) == NULL) { 11094864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 11104864Sbaban return (IDMAP_ERR_MEMORY); 11114864Sbaban } 11124864Sbaban if (type != NULL) 11134864Sbaban *type = (wksids[i].is_user)? 11144864Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 11154864Sbaban if (rid != NULL) 11164864Sbaban *rid = wksids[i].rid; 11174864Sbaban return (IDMAP_SUCCESS); 11184520Snw141292 } 11194520Snw141292 } 11204520Snw141292 return (IDMAP_ERR_NOTFOUND); 11214520Snw141292 } 11224520Snw141292 11234520Snw141292 static idmap_retcode 11244520Snw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 11254520Snw141292 char *end; 11264520Snw141292 char *sql = NULL; 11274520Snw141292 const char **values; 11284520Snw141292 sqlite_vm *vm = NULL; 11294520Snw141292 int ncol, is_user; 11304520Snw141292 uid_t pid; 11314520Snw141292 time_t curtime, exp; 11324520Snw141292 idmap_retcode retcode; 11334520Snw141292 11344520Snw141292 /* Current time */ 11354520Snw141292 errno = 0; 11364520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 11374520Snw141292 idmapdlog(LOG_ERR, 11384520Snw141292 "Failed to get current time (%s)", 11394520Snw141292 strerror(errno)); 11404520Snw141292 retcode = IDMAP_ERR_INTERNAL; 11414520Snw141292 goto out; 11424520Snw141292 } 11434520Snw141292 11444520Snw141292 /* SQL to lookup the cache */ 11454520Snw141292 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 11464520Snw141292 "FROM idmap_cache WHERE " 11474520Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 11484520Snw141292 "(pid >= 2147483648 OR " 11494520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 11504520Snw141292 "expiration > %d));", 11514520Snw141292 req->id1.idmap_id_u.sid.prefix, 11524520Snw141292 req->id1.idmap_id_u.sid.rid, 11534520Snw141292 curtime); 11544520Snw141292 if (sql == NULL) { 11554520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 11564520Snw141292 retcode = IDMAP_ERR_MEMORY; 11574520Snw141292 goto out; 11584520Snw141292 } 11594520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 11604520Snw141292 sqlite_freemem(sql); 11614520Snw141292 11624520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 11634520Snw141292 goto out; 11644520Snw141292 } else if (retcode == IDMAP_SUCCESS) { 11654520Snw141292 /* sanity checks */ 11664520Snw141292 if (values[0] == NULL || values[1] == NULL) { 11674520Snw141292 retcode = IDMAP_ERR_CACHE; 11684520Snw141292 goto out; 11694520Snw141292 } 11704520Snw141292 11714520Snw141292 pid = strtoul(values[0], &end, 10); 11724520Snw141292 is_user = strncmp(values[1], "0", 2)?1:0; 11734520Snw141292 11744520Snw141292 /* 11754520Snw141292 * We may have an expired ephemeral mapping. Consider 11764520Snw141292 * the expired entry as valid if we are not going to 11774520Snw141292 * perform name-based mapping. But do not renew the 11784520Snw141292 * expiration. 11794520Snw141292 * If we will be doing name-based mapping then store the 11804520Snw141292 * ephemeral pid in the result so that we can use it 11814520Snw141292 * if we end up doing dynamic mapping again. 11824520Snw141292 */ 11834520Snw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 11844520Snw141292 !AVOID_NAMESERVICE(req)) { 11854864Sbaban if (IS_EPHEMERAL(pid) && values[2] != NULL) { 11864520Snw141292 exp = strtoll(values[2], &end, 10); 11874520Snw141292 if (exp && exp <= curtime) { 11884520Snw141292 /* Store the ephemeral pid */ 11894520Snw141292 res->id.idmap_id_u.uid = pid; 11904520Snw141292 res->id.idtype = is_user? 11914520Snw141292 IDMAP_UID:IDMAP_GID; 11924644Sbaban res->direction = IDMAP_DIRECTION_BI; 11934520Snw141292 req->direction |= is_user? 11944520Snw141292 _IDMAP_F_EXP_EPH_UID: 11954520Snw141292 _IDMAP_F_EXP_EPH_GID; 11964520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 11974520Snw141292 goto out; 11984520Snw141292 } 11994520Snw141292 } 12004520Snw141292 } 12014520Snw141292 12024520Snw141292 switch (req->id2.idtype) { 12034520Snw141292 case IDMAP_UID: 12044520Snw141292 if (!is_user) 12054520Snw141292 retcode = IDMAP_ERR_NOTUSER; 12064520Snw141292 else 12074520Snw141292 res->id.idmap_id_u.uid = pid; 12084520Snw141292 break; 12094520Snw141292 case IDMAP_GID: 12104520Snw141292 if (is_user) 12114520Snw141292 retcode = IDMAP_ERR_NOTGROUP; 12124520Snw141292 else 12134520Snw141292 res->id.idmap_id_u.gid = pid; 12144520Snw141292 break; 12154520Snw141292 case IDMAP_POSIXID: 12164520Snw141292 res->id.idmap_id_u.uid = pid; 12174520Snw141292 res->id.idtype = (is_user)?IDMAP_UID:IDMAP_GID; 12184520Snw141292 break; 12194520Snw141292 default: 12204520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 12214520Snw141292 break; 12224520Snw141292 } 12234520Snw141292 } 12244520Snw141292 12254520Snw141292 out: 12264520Snw141292 if (retcode == IDMAP_SUCCESS) { 12274864Sbaban if (values[4] != NULL) 12284520Snw141292 res->direction = 12294644Sbaban (strtol(values[4], &end, 10) == 0)? 12304644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 12314520Snw141292 else 12324644Sbaban res->direction = IDMAP_DIRECTION_W2U; 12334520Snw141292 12344864Sbaban if (values[3] != NULL) { 12355064Sdm199847 req->id2name = strdup(values[3]); 12365064Sdm199847 if (req->id2name == NULL) { 12374520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12384520Snw141292 retcode = IDMAP_ERR_MEMORY; 12394520Snw141292 } 12404520Snw141292 } 12414520Snw141292 } 12424864Sbaban if (vm != NULL) 12434520Snw141292 (void) sqlite_finalize(vm, NULL); 12444520Snw141292 return (retcode); 12454520Snw141292 } 12464520Snw141292 12474520Snw141292 static idmap_retcode 12484864Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 12494520Snw141292 char **name, char **domain, int *type) { 12504520Snw141292 char *end; 12514520Snw141292 char *sql = NULL; 12524520Snw141292 const char **values; 12534520Snw141292 sqlite_vm *vm = NULL; 12544520Snw141292 int ncol; 12554520Snw141292 time_t curtime; 12564520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 12574520Snw141292 12584520Snw141292 /* Get current time */ 12594520Snw141292 errno = 0; 12604520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 12614520Snw141292 idmapdlog(LOG_ERR, 12624520Snw141292 "Failed to get current time (%s)", 12634520Snw141292 strerror(errno)); 12644520Snw141292 retcode = IDMAP_ERR_INTERNAL; 12654520Snw141292 goto out; 12664520Snw141292 } 12674520Snw141292 12684520Snw141292 /* SQL to lookup the cache */ 12694520Snw141292 sql = sqlite_mprintf("SELECT name, domain, type FROM name_cache WHERE " 12704520Snw141292 "sidprefix = %Q AND rid = %u AND " 12714520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 12724520Snw141292 "expiration > %d);", 12734520Snw141292 sidprefix, rid, curtime); 12744520Snw141292 if (sql == NULL) { 12754520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12764520Snw141292 retcode = IDMAP_ERR_MEMORY; 12774520Snw141292 goto out; 12784520Snw141292 } 12794520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 12804520Snw141292 sqlite_freemem(sql); 12814520Snw141292 12824520Snw141292 if (retcode == IDMAP_SUCCESS) { 12834864Sbaban if (type != NULL) { 12844520Snw141292 if (values[2] == NULL) { 12854520Snw141292 retcode = IDMAP_ERR_CACHE; 12864520Snw141292 goto out; 12874520Snw141292 } 12884520Snw141292 *type = strtol(values[2], &end, 10); 12894520Snw141292 } 12904520Snw141292 12914864Sbaban if (name != NULL && values[0] != NULL) { 12924520Snw141292 if ((*name = strdup(values[0])) == NULL) { 12934520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12944520Snw141292 retcode = IDMAP_ERR_MEMORY; 12954520Snw141292 goto out; 12964520Snw141292 } 12974520Snw141292 } 12984520Snw141292 12994864Sbaban if (domain != NULL && values[1] != NULL) { 13004520Snw141292 if ((*domain = strdup(values[1])) == NULL) { 13014864Sbaban if (name != NULL && *name) { 13024520Snw141292 free(*name); 13034520Snw141292 *name = NULL; 13044520Snw141292 } 13054520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 13064520Snw141292 retcode = IDMAP_ERR_MEMORY; 13074520Snw141292 goto out; 13084520Snw141292 } 13094520Snw141292 } 13104520Snw141292 } 13114520Snw141292 13124520Snw141292 out: 13134864Sbaban if (vm != NULL) 13144520Snw141292 (void) sqlite_finalize(vm, NULL); 13154520Snw141292 return (retcode); 13164520Snw141292 } 13174520Snw141292 13184520Snw141292 static idmap_retcode 13194520Snw141292 verify_type(idmap_id_type idtype, int type, idmap_id_res *res) { 13204520Snw141292 switch (idtype) { 13214520Snw141292 case IDMAP_UID: 13224520Snw141292 if (type != _IDMAP_T_USER) 13234520Snw141292 return (IDMAP_ERR_NOTUSER); 13244520Snw141292 res->id.idtype = IDMAP_UID; 13254520Snw141292 break; 13264520Snw141292 case IDMAP_GID: 13274520Snw141292 if (type != _IDMAP_T_GROUP) 13284520Snw141292 return (IDMAP_ERR_NOTGROUP); 13294520Snw141292 res->id.idtype = IDMAP_GID; 13304520Snw141292 break; 13314520Snw141292 case IDMAP_POSIXID: 13324520Snw141292 if (type == _IDMAP_T_USER) 13334520Snw141292 res->id.idtype = IDMAP_UID; 13344520Snw141292 else if (type == _IDMAP_T_GROUP) 13354520Snw141292 res->id.idtype = IDMAP_GID; 13364520Snw141292 else 13374520Snw141292 return (IDMAP_ERR_SID); 13384520Snw141292 break; 13394520Snw141292 default: 13404520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 13414520Snw141292 } 13424520Snw141292 return (IDMAP_SUCCESS); 13434520Snw141292 } 13444520Snw141292 13454520Snw141292 /* 13464864Sbaban * Lookup sid to name locally 13474520Snw141292 */ 13484520Snw141292 static idmap_retcode 13494864Sbaban lookup_local_sid2name(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 13504520Snw141292 int type = -1; 13514520Snw141292 idmap_retcode retcode; 13524520Snw141292 char *sidprefix; 13534520Snw141292 idmap_rid_t rid; 13544520Snw141292 char *name = NULL, *domain = NULL; 13554520Snw141292 13564520Snw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 13574520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 13584520Snw141292 13594864Sbaban /* Lookup sids to name in well-known sids table */ 13604864Sbaban retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 13614864Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 13624864Sbaban goto out; 13634864Sbaban 13644520Snw141292 /* Lookup sid to name in cache */ 13654864Sbaban retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 13664520Snw141292 &domain, &type); 13674520Snw141292 if (retcode != IDMAP_SUCCESS) 13684520Snw141292 goto out; 13694520Snw141292 13704520Snw141292 out: 13714520Snw141292 if (retcode == IDMAP_SUCCESS) { 13724864Sbaban /* Verify that the sid type matches the request */ 13734864Sbaban retcode = verify_type(req->id2.idtype, type, res); 13744864Sbaban 13754520Snw141292 /* update state in 'req' */ 13765064Sdm199847 if (name != NULL) 13775064Sdm199847 req->id1name = name; 13785064Sdm199847 if (domain != NULL) 13795064Sdm199847 req->id1domain = domain; 13804520Snw141292 } else { 13814864Sbaban if (name != NULL) 13824520Snw141292 free(name); 13834864Sbaban if (domain != NULL) 13844520Snw141292 free(domain); 13854520Snw141292 } 13864520Snw141292 return (retcode); 13874520Snw141292 } 13884520Snw141292 13894520Snw141292 idmap_retcode 13904520Snw141292 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 13914520Snw141292 idmap_ids_res *result) { 13924520Snw141292 idmap_retcode retcode; 13934520Snw141292 int ret, i; 13944520Snw141292 int retries = 0; 13954520Snw141292 idmap_mapping *req; 13964520Snw141292 idmap_id_res *res; 13974520Snw141292 13984520Snw141292 if (state->ad_nqueries == 0) 13994520Snw141292 return (IDMAP_SUCCESS); 14004520Snw141292 14014520Snw141292 retry: 14024520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 14034520Snw141292 &state->ad_lookup); 14044520Snw141292 if (ret != 0) { 1405*5317Sjp151216 degrade_svc(); 14064520Snw141292 idmapdlog(LOG_ERR, 14074520Snw141292 "Failed to create sid2name batch for AD lookup"); 14084520Snw141292 return (IDMAP_ERR_INTERNAL); 14094520Snw141292 } 14104520Snw141292 1411*5317Sjp151216 restore_svc(); 1412*5317Sjp151216 14134520Snw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 14144520Snw141292 req = &batch->idmap_mapping_batch_val[i]; 14154520Snw141292 res = &result->ids.ids_val[i]; 14164520Snw141292 14174520Snw141292 if (req->id1.idtype == IDMAP_SID && 14184520Snw141292 req->direction & _IDMAP_F_S2N_AD) { 14194864Sbaban if (retries == 0) 14204864Sbaban res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 14214864Sbaban else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 14224864Sbaban continue; 14234520Snw141292 retcode = idmap_sid2name_batch_add1( 14244520Snw141292 state->ad_lookup, 14254520Snw141292 req->id1.idmap_id_u.sid.prefix, 14264520Snw141292 &req->id1.idmap_id_u.sid.rid, 14275064Sdm199847 &req->id1name, 14285064Sdm199847 &req->id1domain, 14294520Snw141292 (int *)&res->id.idtype, 14304520Snw141292 &res->retcode); 14314520Snw141292 14324520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 14334520Snw141292 break; 14344520Snw141292 if (retcode != IDMAP_SUCCESS) 14354520Snw141292 goto out; 14364520Snw141292 } 14374520Snw141292 } 14384520Snw141292 14394520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 14404884Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 14414520Snw141292 else 14424520Snw141292 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 14434520Snw141292 14444520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 14454520Snw141292 goto retry; 1446*5317Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1447*5317Sjp151216 degrade_svc(); 14484520Snw141292 14494520Snw141292 return (retcode); 14504520Snw141292 14514520Snw141292 out: 14524520Snw141292 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 14534884Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 14544520Snw141292 return (retcode); 14554520Snw141292 } 14564520Snw141292 14574520Snw141292 idmap_retcode 14584520Snw141292 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 14594520Snw141292 idmap_id_res *res) { 14604520Snw141292 idmap_retcode retcode; 14614520Snw141292 14624520Snw141292 /* 14634520Snw141292 * The req->direction field is used to maintain state of the 14644520Snw141292 * sid2pid request. 14654520Snw141292 */ 14664520Snw141292 req->direction = _IDMAP_F_DONE; 14674520Snw141292 14685127Sdm199847 if (EMPTY_STRING(req->id1.idmap_id_u.sid.prefix)) { 14694520Snw141292 retcode = IDMAP_ERR_SID; 14704520Snw141292 goto out; 14714520Snw141292 } 14724520Snw141292 res->id.idtype = req->id2.idtype; 14734520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 14744520Snw141292 14754864Sbaban /* Lookup well-known sid to pid mapping */ 14764520Snw141292 retcode = lookup_wksids_sid2pid(req, res); 14774520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 14784520Snw141292 goto out; 14794520Snw141292 14804520Snw141292 /* Lookup sid to pid in cache */ 14814520Snw141292 retcode = lookup_cache_sid2pid(cache, req, res); 14824520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 14834520Snw141292 goto out; 14844520Snw141292 14854520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 14864520Snw141292 res->id.idmap_id_u.uid = SENTINEL_PID; 14874520Snw141292 goto out; 14884520Snw141292 } 14894520Snw141292 14904520Snw141292 /* 14914520Snw141292 * Failed to find non-expired entry in cache. Tell the caller 14924520Snw141292 * that we are not done yet. 14934520Snw141292 */ 14944520Snw141292 state->sid2pid_done = FALSE; 14954520Snw141292 14964520Snw141292 /* 14974520Snw141292 * Our next step is name-based mapping. To lookup name-based 14984520Snw141292 * mapping rules, we need the windows name and domain-name 14994520Snw141292 * associated with the SID. 15004520Snw141292 */ 15014520Snw141292 15024520Snw141292 /* 15034520Snw141292 * Check if we already have the name (i.e name2pid lookups) 15044520Snw141292 */ 15055127Sdm199847 if (!EMPTY_STRING(req->id1name) && 15065127Sdm199847 !EMPTY_STRING(req->id1domain)) { 15074520Snw141292 retcode = IDMAP_SUCCESS; 15084520Snw141292 req->direction |= _IDMAP_F_S2N_CACHE; 15094520Snw141292 goto out; 15104520Snw141292 } 15114520Snw141292 15124864Sbaban /* Lookup sid to winname@domain locally first */ 15134864Sbaban retcode = lookup_local_sid2name(cache, req, res); 15144864Sbaban if (retcode == IDMAP_SUCCESS) { 15154864Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 15164864Sbaban } else if (retcode == IDMAP_ERR_NOTFOUND) { 15174520Snw141292 /* Batch sid to name AD lookup request */ 15184520Snw141292 retcode = IDMAP_SUCCESS; 15194520Snw141292 req->direction |= _IDMAP_F_S2N_AD; 15204520Snw141292 state->ad_nqueries++; 15214520Snw141292 goto out; 15224520Snw141292 } 15234520Snw141292 15244520Snw141292 15254520Snw141292 out: 15264520Snw141292 res->retcode = idmap_stat4prot(retcode); 15274520Snw141292 return (retcode); 15284520Snw141292 } 15294520Snw141292 15304520Snw141292 /* 15314520Snw141292 * Generate SID using the following convention 15324520Snw141292 * <machine-sid-prefix>-<1000 + uid> 15334520Snw141292 * <machine-sid-prefix>-<2^31 + gid> 15344520Snw141292 */ 15354520Snw141292 static idmap_retcode 15364520Snw141292 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) { 15374520Snw141292 15384864Sbaban if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 15394520Snw141292 /* Skip 1000 UIDs */ 15404520Snw141292 if (is_user && req->id1.idmap_id_u.uid > 15414520Snw141292 (INT32_MAX - LOCALRID_MIN)) 15424864Sbaban return (IDMAP_ERR_NOMAPPING); 15434520Snw141292 15444520Snw141292 RDLOCK_CONFIG(); 15454520Snw141292 res->id.idmap_id_u.sid.prefix = 15464520Snw141292 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 15474520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 15484520Snw141292 UNLOCK_CONFIG(); 15494520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 15504520Snw141292 return (IDMAP_ERR_MEMORY); 15514520Snw141292 } 15524520Snw141292 UNLOCK_CONFIG(); 15534520Snw141292 res->id.idmap_id_u.sid.rid = 15544520Snw141292 (is_user)?req->id1.idmap_id_u.uid + LOCALRID_MIN: 15554520Snw141292 req->id1.idmap_id_u.gid + INT32_MAX + 1; 15564644Sbaban res->direction = IDMAP_DIRECTION_BI; 15574520Snw141292 15584520Snw141292 /* 15594520Snw141292 * Don't update name_cache because local sids don't have 15604520Snw141292 * valid windows names. 15614520Snw141292 * We mark the entry as being found in the namecache so that 15624520Snw141292 * the cache update routine doesn't update namecache. 15634520Snw141292 */ 15644520Snw141292 req->direction = _IDMAP_F_S2N_CACHE; 15654868Sbaban return (IDMAP_SUCCESS); 15664520Snw141292 } 15674520Snw141292 15684864Sbaban return (IDMAP_ERR_NOMAPPING); 15694520Snw141292 } 15704520Snw141292 15714520Snw141292 static idmap_retcode 15724520Snw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) { 15734520Snw141292 char *sidprefix; 15744520Snw141292 uint32_t rid; 15754520Snw141292 int s; 15764520Snw141292 15774520Snw141292 /* 15784520Snw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 15794520Snw141292 * GID = last RID - 2^31. 15804520Snw141292 */ 15814520Snw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 15824520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 15834520Snw141292 15844520Snw141292 RDLOCK_CONFIG(); 15854520Snw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid)? 15864520Snw141292 strcasecmp(sidprefix, 15874520Snw141292 _idmapdstate.cfg->pgcfg.machine_sid):1; 15884520Snw141292 UNLOCK_CONFIG(); 15894520Snw141292 15904520Snw141292 if (s == 0) { 15914520Snw141292 switch (req->id2.idtype) { 15924520Snw141292 case IDMAP_UID: 15934520Snw141292 if (rid > INT32_MAX) { 15944520Snw141292 return (IDMAP_ERR_NOTUSER); 15954520Snw141292 } else if (rid < LOCALRID_MIN) { 15964520Snw141292 return (IDMAP_ERR_NOTFOUND); 15974520Snw141292 } 15984520Snw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 15994520Snw141292 res->id.idtype = IDMAP_UID; 16004520Snw141292 break; 16014520Snw141292 case IDMAP_GID: 16024520Snw141292 if (rid <= INT32_MAX) { 16034520Snw141292 return (IDMAP_ERR_NOTGROUP); 16044520Snw141292 } 16054520Snw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 16064520Snw141292 res->id.idtype = IDMAP_GID; 16074520Snw141292 break; 16084520Snw141292 case IDMAP_POSIXID: 16094520Snw141292 if (rid > INT32_MAX) { 16104520Snw141292 res->id.idmap_id_u.gid = 16114520Snw141292 rid - INT32_MAX - 1; 16124520Snw141292 res->id.idtype = IDMAP_GID; 16134520Snw141292 } else if (rid < LOCALRID_MIN) { 16144520Snw141292 return (IDMAP_ERR_NOTFOUND); 16154520Snw141292 } else { 16164520Snw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 16174520Snw141292 res->id.idtype = IDMAP_UID; 16184520Snw141292 } 16194520Snw141292 break; 16204520Snw141292 default: 16214520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 16224520Snw141292 } 16234520Snw141292 return (IDMAP_SUCCESS); 16244520Snw141292 } 16254520Snw141292 16264520Snw141292 return (IDMAP_ERR_NOTFOUND); 16274520Snw141292 } 16284520Snw141292 16294520Snw141292 static idmap_retcode 16304520Snw141292 ns_lookup_byname(int is_user, const char *name, idmap_id_res *res) { 16314520Snw141292 struct passwd pwd; 16324520Snw141292 struct group grp; 16334520Snw141292 char buf[1024]; 16344520Snw141292 int errnum; 16354520Snw141292 const char *me = "ns_lookup_byname"; 16364520Snw141292 16374520Snw141292 if (is_user) { 16384520Snw141292 if (getpwnam_r(name, &pwd, buf, sizeof (buf)) == NULL) { 16394520Snw141292 errnum = errno; 16404520Snw141292 idmapdlog(LOG_WARNING, 16414520Snw141292 "%s: getpwnam_r(%s) failed (%s).", 16424520Snw141292 me, name, 16434520Snw141292 errnum?strerror(errnum):"not found"); 16444520Snw141292 if (errnum == 0) 16454520Snw141292 return (IDMAP_ERR_NOTFOUND); 16464520Snw141292 else 16474520Snw141292 return (IDMAP_ERR_INTERNAL); 16484520Snw141292 } 16494520Snw141292 res->id.idmap_id_u.uid = pwd.pw_uid; 16504520Snw141292 res->id.idtype = IDMAP_UID; 16514520Snw141292 } else { 16524520Snw141292 if (getgrnam_r(name, &grp, buf, sizeof (buf)) == NULL) { 16534520Snw141292 errnum = errno; 16544520Snw141292 idmapdlog(LOG_WARNING, 16554520Snw141292 "%s: getgrnam_r(%s) failed (%s).", 16564520Snw141292 me, name, 16574520Snw141292 errnum?strerror(errnum):"not found"); 16584520Snw141292 if (errnum == 0) 16594520Snw141292 return (IDMAP_ERR_NOTFOUND); 16604520Snw141292 else 16614520Snw141292 return (IDMAP_ERR_INTERNAL); 16624520Snw141292 } 16634520Snw141292 res->id.idmap_id_u.gid = grp.gr_gid; 16644520Snw141292 res->id.idtype = IDMAP_GID; 16654520Snw141292 } 16664520Snw141292 return (IDMAP_SUCCESS); 16674520Snw141292 } 16684520Snw141292 16694520Snw141292 /* 16704520Snw141292 * Name-based mapping 16714520Snw141292 * 16724520Snw141292 * Case 1: If no rule matches do ephemeral 16734520Snw141292 * 16744520Snw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 16754520Snw141292 * 16764520Snw141292 * Case 3: If rule matches and unixname is specified then lookup name 16774520Snw141292 * service using the unixname. If unixname not found then return no mapping. 16784520Snw141292 * 16794520Snw141292 * Case 4: If rule matches and unixname is * then lookup name service 16804520Snw141292 * using winname as the unixname. If unixname not found then process 16814520Snw141292 * other rules using the lookup order. If no other rule matches then do 16824520Snw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 16834520Snw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 16844520Snw141292 * instead of the default behaviour of doing ephemeral mapping. 16854520Snw141292 * 16864520Snw141292 * Example 1: 16874520Snw141292 * *@sfbay == * 16884520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16894520Snw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 16904520Snw141292 * 16914520Snw141292 * Example 2: 16924520Snw141292 * *@sfbay == * 16934520Snw141292 * *@sfbay => guest 16944520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16954520Snw141292 * the name service then foo@sfbay will be mapped to guest. 16964520Snw141292 * 16974520Snw141292 * Example 3: 16984520Snw141292 * *@sfbay == * 16994520Snw141292 * *@sfbay => "" 17004520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 17014520Snw141292 * the name service then we will return no mapping for foo@sfbay. 17024520Snw141292 * 17034520Snw141292 */ 17044520Snw141292 static idmap_retcode 17054520Snw141292 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) { 17064520Snw141292 const char *unixname, *winname, *windomain; 17074520Snw141292 char *sql = NULL, *errmsg = NULL; 17084520Snw141292 idmap_retcode retcode; 17094520Snw141292 char *end; 17104520Snw141292 const char **values; 17114520Snw141292 sqlite_vm *vm = NULL; 17124884Sjp151216 int ncol, r, i, is_user; 17134520Snw141292 const char *me = "name_based_mapping_sid2pid"; 17144520Snw141292 17155064Sdm199847 winname = req->id1name; 17165064Sdm199847 windomain = req->id1domain; 17174520Snw141292 is_user = (res->id.idtype == IDMAP_UID)?1:0; 17184520Snw141292 17194520Snw141292 i = 0; 17204864Sbaban if (windomain == NULL) { 17214864Sbaban windomain = ""; 17224864Sbaban } else { 17234864Sbaban RDLOCK_CONFIG(); 1724*5317Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 1725*5317Sjp151216 if (strcasecmp(_idmapdstate.cfg->pgcfg.default_domain, 17264864Sbaban windomain) == 0) 17274864Sbaban i = 1; 17284864Sbaban } 17294864Sbaban UNLOCK_CONFIG(); 17304520Snw141292 } 17314520Snw141292 17324520Snw141292 sql = sqlite_mprintf( 17334520Snw141292 "SELECT unixname, u2w_order FROM namerules WHERE " 17344520Snw141292 "w2u_order > 0 AND is_user = %d AND " 17354520Snw141292 "(winname = %Q OR winname = '*') AND " 17364520Snw141292 "(windomain = %Q OR windomain = '*' %s) " 17374520Snw141292 "ORDER BY w2u_order ASC;", 17384864Sbaban is_user, winname, 17394864Sbaban windomain, 17404864Sbaban i?"OR windomain ISNULL OR windomain = ''":""); 17414520Snw141292 if (sql == NULL) { 17424520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 17434520Snw141292 retcode = IDMAP_ERR_MEMORY; 17444520Snw141292 goto out; 17454520Snw141292 } 17464520Snw141292 17474520Snw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 17484520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17494520Snw141292 idmapdlog(LOG_ERR, 17504520Snw141292 "%s: database error (%s)", 17514520Snw141292 me, CHECK_NULL(errmsg)); 17524520Snw141292 sqlite_freemem(errmsg); 17534520Snw141292 goto out; 17544520Snw141292 } 17554520Snw141292 17564884Sjp151216 for (; ; ) { 17574520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 17584884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 17594884Sjp151216 17604884Sjp151216 if (r == SQLITE_ROW) { 17614520Snw141292 if (ncol < 2) { 17624520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17634520Snw141292 goto out; 17644520Snw141292 } 17654520Snw141292 if (values[0] == NULL) { 17664520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17674520Snw141292 goto out; 17684520Snw141292 } 17694520Snw141292 17704520Snw141292 if (EMPTY_NAME(values[0])) { 17714520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 17724520Snw141292 goto out; 17734520Snw141292 } 17744520Snw141292 unixname = (values[0][0] == '*')?winname:values[0]; 17754520Snw141292 retcode = ns_lookup_byname(is_user, unixname, res); 17764520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 17774520Snw141292 if (unixname == winname) 17784520Snw141292 /* Case 4 */ 17794520Snw141292 continue; 17804520Snw141292 else 17814520Snw141292 /* Case 3 */ 17824520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 17834520Snw141292 } 17844520Snw141292 goto out; 17854520Snw141292 } else if (r == SQLITE_DONE) { 17864520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 17874520Snw141292 goto out; 17884520Snw141292 } else { 17894520Snw141292 (void) sqlite_finalize(vm, &errmsg); 17904520Snw141292 vm = NULL; 17914520Snw141292 idmapdlog(LOG_ERR, 17924520Snw141292 "%s: database error (%s)", 17934520Snw141292 me, CHECK_NULL(errmsg)); 17944520Snw141292 sqlite_freemem(errmsg); 17954520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17964520Snw141292 goto out; 17974520Snw141292 } 17984520Snw141292 } 17994520Snw141292 18004520Snw141292 out: 18014864Sbaban if (sql != NULL) 18024520Snw141292 sqlite_freemem(sql); 18034520Snw141292 if (retcode == IDMAP_SUCCESS) { 18044864Sbaban if (values[1] != NULL) 18054520Snw141292 res->direction = 18064644Sbaban (strtol(values[1], &end, 10) == 0)? 18074644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 18084520Snw141292 else 18094644Sbaban res->direction = IDMAP_DIRECTION_W2U; 18105064Sdm199847 req->id2name = strdup(unixname); 18114520Snw141292 } 18124864Sbaban if (vm != NULL) 18134520Snw141292 (void) sqlite_finalize(vm, NULL); 18144520Snw141292 return (retcode); 18154520Snw141292 } 18164520Snw141292 18174520Snw141292 static 18184520Snw141292 int 18194520Snw141292 get_next_eph_uid(uid_t *next_uid) 18204520Snw141292 { 18214520Snw141292 uid_t uid; 18224520Snw141292 gid_t gid; 18234520Snw141292 int err; 18244520Snw141292 18254520Snw141292 *next_uid = (uid_t)-1; 18264520Snw141292 uid = _idmapdstate.next_uid++; 18274520Snw141292 if (uid >= _idmapdstate.limit_uid) { 18284520Snw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 18294520Snw141292 return (err); 18304520Snw141292 18314520Snw141292 _idmapdstate.limit_uid = uid + 8192; 18324520Snw141292 _idmapdstate.next_uid = uid; 18334520Snw141292 } 18344520Snw141292 *next_uid = uid; 18354520Snw141292 18364520Snw141292 return (0); 18374520Snw141292 } 18384520Snw141292 18394520Snw141292 static 18404520Snw141292 int 18414520Snw141292 get_next_eph_gid(gid_t *next_gid) 18424520Snw141292 { 18434520Snw141292 uid_t uid; 18444520Snw141292 gid_t gid; 18454520Snw141292 int err; 18464520Snw141292 18474520Snw141292 *next_gid = (uid_t)-1; 18484520Snw141292 gid = _idmapdstate.next_gid++; 18494520Snw141292 if (gid >= _idmapdstate.limit_gid) { 18504520Snw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 18514520Snw141292 return (err); 18524520Snw141292 18534520Snw141292 _idmapdstate.limit_gid = gid + 8192; 18544520Snw141292 _idmapdstate.next_gid = gid; 18554520Snw141292 } 18564520Snw141292 *next_gid = gid; 18574520Snw141292 18584520Snw141292 return (0); 18594520Snw141292 } 18604520Snw141292 18614864Sbaban static 18624864Sbaban int 18634864Sbaban gethash(const char *str, uint32_t num, uint_t htsize) { 18644864Sbaban uint_t hval, i, len; 18654864Sbaban 18664864Sbaban if (str == NULL) 18674864Sbaban return (0); 18684864Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 18694864Sbaban hval += str[i]; 18704864Sbaban hval += (hval << 10); 18714864Sbaban hval ^= (hval >> 6); 18724864Sbaban } 18734864Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 18744864Sbaban hval += str[i]; 18754864Sbaban hval += (hval << 10); 18764864Sbaban hval ^= (hval >> 6); 18774864Sbaban } 18784864Sbaban hval += (hval << 3); 18794864Sbaban hval ^= (hval >> 11); 18804864Sbaban hval += (hval << 15); 18814864Sbaban return (hval % htsize); 18824864Sbaban } 18834864Sbaban 18844864Sbaban static 18854864Sbaban int 18864864Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 18874864Sbaban uid_t *pid) { 18884864Sbaban uint_t next, key; 18894864Sbaban uint_t htsize = state->sid_history_size; 18904864Sbaban idmap_sid *sid; 18914864Sbaban 18924864Sbaban next = gethash(prefix, rid, htsize); 18934864Sbaban while (next != htsize) { 18944864Sbaban key = state->sid_history[next].key; 18954864Sbaban if (key == htsize) 18964864Sbaban return (0); 18974864Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 18984864Sbaban idmap_id_u.sid; 18994864Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 19004864Sbaban *pid = state->result->ids.ids_val[key].id. 19014864Sbaban idmap_id_u.uid; 19024864Sbaban return (1); 19034864Sbaban } 19044864Sbaban next = state->sid_history[next].next; 19054864Sbaban } 19064864Sbaban return (0); 19074864Sbaban } 19084864Sbaban 19094864Sbaban static 19104864Sbaban void 19114864Sbaban add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) { 19124864Sbaban uint_t hash, next; 19134864Sbaban uint_t htsize = state->sid_history_size; 19144864Sbaban 19154864Sbaban hash = next = gethash(prefix, rid, htsize); 19164864Sbaban while (state->sid_history[next].key != htsize) { 19174864Sbaban next++; 19184864Sbaban next %= htsize; 19194864Sbaban } 19204864Sbaban state->sid_history[next].key = state->curpos; 19214864Sbaban if (hash == next) 19224864Sbaban return; 19234864Sbaban state->sid_history[next].next = state->sid_history[hash].next; 19244864Sbaban state->sid_history[hash].next = next; 19254864Sbaban } 19264520Snw141292 19274520Snw141292 /* ARGSUSED */ 19284520Snw141292 static 19294520Snw141292 idmap_retcode 19304864Sbaban dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 19314864Sbaban idmap_mapping *req, idmap_id_res *res) { 19324520Snw141292 19334520Snw141292 uid_t next_pid; 19344520Snw141292 19354864Sbaban res->direction = IDMAP_DIRECTION_BI; 19364864Sbaban 19374864Sbaban if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 19384864Sbaban return (IDMAP_SUCCESS); 19394864Sbaban 19404864Sbaban if (state->sid_history != NULL && 19414864Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 19424864Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 19434864Sbaban res->id.idmap_id_u.uid = next_pid; 19444864Sbaban return (IDMAP_SUCCESS); 19454864Sbaban } 19464864Sbaban 19474864Sbaban if (res->id.idtype == IDMAP_UID) { 19484520Snw141292 if (get_next_eph_uid(&next_pid) != 0) 19494520Snw141292 return (IDMAP_ERR_INTERNAL); 19504520Snw141292 res->id.idmap_id_u.uid = next_pid; 19514520Snw141292 } else { 19524520Snw141292 if (get_next_eph_gid(&next_pid) != 0) 19534520Snw141292 return (IDMAP_ERR_INTERNAL); 19544520Snw141292 res->id.idmap_id_u.gid = next_pid; 19554520Snw141292 } 19564520Snw141292 19574864Sbaban if (state->sid_history != NULL) 19584864Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 19594864Sbaban req->id1.idmap_id_u.sid.rid); 19604864Sbaban 19614520Snw141292 return (IDMAP_SUCCESS); 19624520Snw141292 } 19634520Snw141292 19644520Snw141292 idmap_retcode 19654520Snw141292 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 19664520Snw141292 idmap_mapping *req, idmap_id_res *res) { 19674520Snw141292 idmap_retcode retcode; 19684520Snw141292 19694520Snw141292 /* 19704520Snw141292 * The req->direction field is used to maintain state of the 19714520Snw141292 * sid2pid request. 19724520Snw141292 */ 19734520Snw141292 19744520Snw141292 /* Check if second pass is needed */ 19754520Snw141292 if (req->direction == _IDMAP_F_DONE) 19764520Snw141292 return (res->retcode); 19774520Snw141292 19784520Snw141292 /* Get status from previous pass */ 19794520Snw141292 retcode = (res->retcode == IDMAP_NEXT)?IDMAP_SUCCESS:res->retcode; 19804520Snw141292 19814520Snw141292 if (retcode != IDMAP_SUCCESS) { 19824520Snw141292 /* Reset return type */ 19834520Snw141292 res->id.idtype = req->id2.idtype; 19844520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 19854520Snw141292 19864520Snw141292 /* Check if this is a localsid */ 19874520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND && 19884864Sbaban _idmapdstate.cfg->pgcfg.machine_sid) { 19894520Snw141292 retcode = lookup_localsid2pid(req, res); 19904520Snw141292 if (retcode == IDMAP_SUCCESS) { 19914520Snw141292 state->sid2pid_done = FALSE; 19924520Snw141292 req->direction = _IDMAP_F_S2N_CACHE; 19934520Snw141292 } 19944520Snw141292 } 19954520Snw141292 goto out; 19964520Snw141292 } 19974520Snw141292 19984520Snw141292 /* 19994520Snw141292 * Verify that the sid type matches the request if the 20004520Snw141292 * SID was validated by an AD lookup. 20014520Snw141292 */ 20024520Snw141292 if (req->direction & _IDMAP_F_S2N_AD) { 20034520Snw141292 retcode = verify_type(req->id2.idtype, 20044520Snw141292 (int)res->id.idtype, res); 20054520Snw141292 if (retcode != IDMAP_SUCCESS) { 20064520Snw141292 res->id.idtype = req->id2.idtype; 20074520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 20084520Snw141292 goto out; 20094520Snw141292 } 20104520Snw141292 } 20114520Snw141292 20124520Snw141292 /* Name-based mapping */ 20134520Snw141292 retcode = name_based_mapping_sid2pid(db, req, res); 20144520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 20154520Snw141292 /* If not found, do ephemeral mapping */ 20164520Snw141292 goto ephemeral; 20174520Snw141292 else if (retcode != IDMAP_SUCCESS) 20184520Snw141292 goto out; 20194520Snw141292 20204520Snw141292 state->sid2pid_done = FALSE; 20214520Snw141292 goto out; 20224520Snw141292 20234520Snw141292 20244520Snw141292 ephemeral: 20254864Sbaban retcode = dynamic_ephemeral_mapping(state, cache, req, res); 20264520Snw141292 if (retcode == IDMAP_SUCCESS) 20274520Snw141292 state->sid2pid_done = FALSE; 20284520Snw141292 20294520Snw141292 out: 20304520Snw141292 res->retcode = idmap_stat4prot(retcode); 20314520Snw141292 return (retcode); 20324520Snw141292 } 20334520Snw141292 20344520Snw141292 idmap_retcode 20354520Snw141292 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 20364520Snw141292 idmap_mapping *req, idmap_id_res *res) { 20374520Snw141292 char *sql = NULL; 20384520Snw141292 idmap_retcode retcode; 20394520Snw141292 20404520Snw141292 /* Check if we need to cache anything */ 20414520Snw141292 if (req->direction == _IDMAP_F_DONE) 20424520Snw141292 return (IDMAP_SUCCESS); 20434520Snw141292 20444520Snw141292 /* We don't cache negative entries */ 20454520Snw141292 if (res->retcode != IDMAP_SUCCESS) 20464520Snw141292 return (IDMAP_SUCCESS); 20474520Snw141292 20484520Snw141292 /* 20494520Snw141292 * Using NULL for u2w instead of 0 so that our trigger allows 20504520Snw141292 * the same pid to be the destination in multiple entries 20514520Snw141292 */ 20524520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 20534520Snw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 20544520Snw141292 "is_user, expiration, w2u, u2w) " 20554520Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 20564520Snw141292 "strftime('%%s','now') + 600, %q, 1); ", 20574520Snw141292 res->id.idmap_id_u.sid.prefix, 20584520Snw141292 res->id.idmap_id_u.sid.rid, 20595064Sdm199847 req->id2domain, 20605064Sdm199847 req->id2name, 20614520Snw141292 req->id1.idmap_id_u.uid, 20625064Sdm199847 req->id1name, 20634520Snw141292 (req->id1.idtype == IDMAP_UID)?1:0, 20644520Snw141292 (res->direction == 0)?"1":NULL); 20654520Snw141292 20664520Snw141292 if (sql == NULL) { 20674520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20684520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 20694520Snw141292 goto out; 20704520Snw141292 } 20714520Snw141292 20724520Snw141292 retcode = sql_exec_no_cb(cache, sql); 20734520Snw141292 if (retcode != IDMAP_SUCCESS) 20744520Snw141292 goto out; 20754520Snw141292 20764520Snw141292 state->pid2sid_done = FALSE; 20774520Snw141292 sqlite_freemem(sql); 20784520Snw141292 sql = NULL; 20794520Snw141292 20804520Snw141292 /* If sid2name was found in the cache, no need to update namecache */ 20814520Snw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 20824520Snw141292 goto out; 20834520Snw141292 20845064Sdm199847 if (req->id2name == NULL) 20854520Snw141292 goto out; 20864520Snw141292 20874520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 20884520Snw141292 "(sidprefix, rid, name, domain, type, expiration) " 20894520Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 20904520Snw141292 res->id.idmap_id_u.sid.prefix, 20914520Snw141292 res->id.idmap_id_u.sid.rid, 20925064Sdm199847 req->id2name, 20935064Sdm199847 req->id2domain, 20944520Snw141292 (req->id1.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 20954520Snw141292 20964520Snw141292 if (sql == NULL) { 20974520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20984520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 20994520Snw141292 goto out; 21004520Snw141292 } 21014520Snw141292 21024520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21034520Snw141292 21044520Snw141292 out: 21054864Sbaban if (sql != NULL) 21064520Snw141292 sqlite_freemem(sql); 21074520Snw141292 return (retcode); 21084520Snw141292 } 21094520Snw141292 21104520Snw141292 idmap_retcode 21114520Snw141292 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 21124520Snw141292 idmap_mapping *req, idmap_id_res *res) { 21134520Snw141292 char *sql = NULL; 21144520Snw141292 idmap_retcode retcode; 21154520Snw141292 int is_eph_user; 21164520Snw141292 21174520Snw141292 /* Check if we need to cache anything */ 21184520Snw141292 if (req->direction == _IDMAP_F_DONE) 21194520Snw141292 return (IDMAP_SUCCESS); 21204520Snw141292 21214520Snw141292 /* We don't cache negative entries */ 21224520Snw141292 if (res->retcode != IDMAP_SUCCESS) 21234520Snw141292 return (IDMAP_SUCCESS); 21244520Snw141292 21254520Snw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 21264520Snw141292 is_eph_user = 1; 21274520Snw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 21284520Snw141292 is_eph_user = 0; 21294520Snw141292 else 21304520Snw141292 is_eph_user = -1; 21314520Snw141292 21324520Snw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 21334520Snw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 21344520Snw141292 "SET w2u = 0 WHERE " 21354520Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 21364520Snw141292 "pid >= 2147483648 AND is_user = %d;", 21374520Snw141292 req->id1.idmap_id_u.sid.prefix, 21384520Snw141292 req->id1.idmap_id_u.sid.rid, 21394520Snw141292 is_eph_user); 21404520Snw141292 if (sql == NULL) { 21414520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21424520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21434520Snw141292 goto out; 21444520Snw141292 } 21454520Snw141292 21464520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21474520Snw141292 if (retcode != IDMAP_SUCCESS) 21484520Snw141292 goto out; 21494520Snw141292 21504520Snw141292 sqlite_freemem(sql); 21514520Snw141292 sql = NULL; 21524520Snw141292 } 21534520Snw141292 21544520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 21554520Snw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 21564520Snw141292 "is_user, expiration, w2u, u2w) " 21574520Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 21584520Snw141292 "strftime('%%s','now') + 600, 1, %q); ", 21594520Snw141292 req->id1.idmap_id_u.sid.prefix, 21604520Snw141292 req->id1.idmap_id_u.sid.rid, 21615064Sdm199847 req->id1domain, 21625064Sdm199847 req->id1name, 21634520Snw141292 res->id.idmap_id_u.uid, 21645064Sdm199847 req->id2name, 21654520Snw141292 (res->id.idtype == IDMAP_UID)?1:0, 21664520Snw141292 (res->direction == 0)?"1":NULL); 21674520Snw141292 21684520Snw141292 if (sql == NULL) { 21694520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21704520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21714520Snw141292 goto out; 21724520Snw141292 } 21734520Snw141292 21744520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21754520Snw141292 if (retcode != IDMAP_SUCCESS) 21764520Snw141292 goto out; 21774520Snw141292 21784520Snw141292 state->sid2pid_done = FALSE; 21794520Snw141292 sqlite_freemem(sql); 21804520Snw141292 sql = NULL; 21814520Snw141292 21824520Snw141292 /* If name2sid was found in the cache, no need to update namecache */ 21834520Snw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 21844520Snw141292 goto out; 21854520Snw141292 21865127Sdm199847 if (EMPTY_STRING(req->id1name)) 21874520Snw141292 goto out; 21884520Snw141292 21894520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 21904520Snw141292 "(sidprefix, rid, name, domain, type, expiration) " 21914520Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 21924520Snw141292 req->id1.idmap_id_u.sid.prefix, 21934520Snw141292 req->id1.idmap_id_u.sid.rid, 21945064Sdm199847 req->id1name, 21955064Sdm199847 req->id1domain, 21964520Snw141292 (res->id.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 21974520Snw141292 21984520Snw141292 if (sql == NULL) { 21994520Snw141292 retcode = IDMAP_ERR_INTERNAL; 22004520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22014520Snw141292 goto out; 22024520Snw141292 } 22034520Snw141292 22044520Snw141292 retcode = sql_exec_no_cb(cache, sql); 22054520Snw141292 22064520Snw141292 out: 22074864Sbaban if (sql != NULL) 22084520Snw141292 sqlite_freemem(sql); 22094520Snw141292 return (retcode); 22104520Snw141292 } 22114520Snw141292 22124520Snw141292 static idmap_retcode 22134520Snw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 22144520Snw141292 int is_user, int getname) { 22154520Snw141292 char *end; 22164520Snw141292 char *sql = NULL; 22174520Snw141292 const char **values; 22184520Snw141292 sqlite_vm *vm = NULL; 22194520Snw141292 int ncol; 22204520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 22214520Snw141292 time_t curtime; 22224520Snw141292 22234520Snw141292 /* Current time */ 22244520Snw141292 errno = 0; 22254520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 22264520Snw141292 idmapdlog(LOG_ERR, 22274520Snw141292 "Failed to get current time (%s)", 22284520Snw141292 strerror(errno)); 22294520Snw141292 retcode = IDMAP_ERR_INTERNAL; 22304520Snw141292 goto out; 22314520Snw141292 } 22324520Snw141292 22334520Snw141292 /* SQL to lookup the cache */ 22344520Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, winname, windomain, w2u " 22354520Snw141292 "FROM idmap_cache WHERE " 22364520Snw141292 "pid = %u AND u2w = 1 AND is_user = %d AND " 22374520Snw141292 "(pid >= 2147483648 OR " 22384520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 22394520Snw141292 "expiration > %d));", 22404520Snw141292 req->id1.idmap_id_u.uid, is_user, curtime); 22414520Snw141292 if (sql == NULL) { 22424520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22434520Snw141292 retcode = IDMAP_ERR_MEMORY; 22444520Snw141292 goto out; 22454520Snw141292 } 22464520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 22474520Snw141292 sqlite_freemem(sql); 22484520Snw141292 22494520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 22504520Snw141292 goto out; 22514520Snw141292 else if (retcode == IDMAP_SUCCESS) { 22524520Snw141292 /* sanity checks */ 22534520Snw141292 if (values[0] == NULL || values[1] == NULL) { 22544520Snw141292 retcode = IDMAP_ERR_CACHE; 22554520Snw141292 goto out; 22564520Snw141292 } 22574520Snw141292 22584520Snw141292 switch (req->id2.idtype) { 22594520Snw141292 case IDMAP_SID: 22604520Snw141292 res->id.idmap_id_u.sid.rid = 22614520Snw141292 strtoul(values[1], &end, 10); 22624520Snw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 22634520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 22644520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22654520Snw141292 retcode = IDMAP_ERR_MEMORY; 22664520Snw141292 goto out; 22674520Snw141292 } 22684520Snw141292 22694864Sbaban if (values[4] != NULL) 22704520Snw141292 res->direction = 22714644Sbaban (strtol(values[4], &end, 10) == 0)? 22724644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 22734520Snw141292 else 22744644Sbaban res->direction = IDMAP_DIRECTION_U2W; 22754520Snw141292 22764520Snw141292 if (getname == 0 || values[2] == NULL) 22774520Snw141292 break; 22785064Sdm199847 req->id2name = strdup(values[2]); 22795064Sdm199847 if (req->id2name == NULL) { 22804520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22814520Snw141292 retcode = IDMAP_ERR_MEMORY; 22824520Snw141292 goto out; 22834520Snw141292 } 22844520Snw141292 22854520Snw141292 if (values[3] == NULL) 22864520Snw141292 break; 22875064Sdm199847 req->id2domain = strdup(values[3]); 22885064Sdm199847 if (req->id2domain == NULL) { 22894520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22904520Snw141292 retcode = IDMAP_ERR_MEMORY; 22914520Snw141292 goto out; 22924520Snw141292 } 22934520Snw141292 break; 22944520Snw141292 default: 22954520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 22964520Snw141292 break; 22974520Snw141292 } 22984520Snw141292 } 22994520Snw141292 23004520Snw141292 out: 23014864Sbaban if (vm != NULL) 23024520Snw141292 (void) sqlite_finalize(vm, NULL); 23034520Snw141292 return (retcode); 23044520Snw141292 } 23054520Snw141292 23064520Snw141292 static idmap_retcode 23074520Snw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 23084520Snw141292 char **sidprefix, idmap_rid_t *rid, int *type) { 23094520Snw141292 char *end; 23104520Snw141292 char *sql = NULL; 23114520Snw141292 const char **values; 23124520Snw141292 sqlite_vm *vm = NULL; 23134520Snw141292 int ncol; 23144520Snw141292 time_t curtime; 23154520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 23164520Snw141292 23174520Snw141292 /* Get current time */ 23184520Snw141292 errno = 0; 23194520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 23204520Snw141292 idmapdlog(LOG_ERR, 23214520Snw141292 "Failed to get current time (%s)", 23224520Snw141292 strerror(errno)); 23234520Snw141292 retcode = IDMAP_ERR_INTERNAL; 23244520Snw141292 goto out; 23254520Snw141292 } 23264520Snw141292 23274520Snw141292 /* SQL to lookup the cache */ 23284520Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type FROM name_cache " 23294520Snw141292 "WHERE name = %Q AND domain = %Q AND " 23304520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 23314520Snw141292 "expiration > %d);", 23324520Snw141292 name, domain, curtime); 23334520Snw141292 if (sql == NULL) { 23344520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 23354520Snw141292 retcode = IDMAP_ERR_MEMORY; 23364520Snw141292 goto out; 23374520Snw141292 } 23384520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 23394520Snw141292 sqlite_freemem(sql); 23404520Snw141292 23414520Snw141292 if (retcode == IDMAP_SUCCESS) { 23424864Sbaban if (type != NULL) { 23434520Snw141292 if (values[2] == NULL) { 23444520Snw141292 retcode = IDMAP_ERR_CACHE; 23454520Snw141292 goto out; 23464520Snw141292 } 23474520Snw141292 *type = strtol(values[2], &end, 10); 23484520Snw141292 } 23494520Snw141292 23504520Snw141292 if (values[0] == NULL || values[1] == NULL) { 23514520Snw141292 retcode = IDMAP_ERR_CACHE; 23524520Snw141292 goto out; 23534520Snw141292 } 23544520Snw141292 if ((*sidprefix = strdup(values[0])) == NULL) { 23554520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 23564520Snw141292 retcode = IDMAP_ERR_MEMORY; 23574520Snw141292 goto out; 23584520Snw141292 } 23594520Snw141292 *rid = strtoul(values[1], &end, 10); 23604520Snw141292 } 23614520Snw141292 23624520Snw141292 out: 23634864Sbaban if (vm != NULL) 23644520Snw141292 (void) sqlite_finalize(vm, NULL); 23654520Snw141292 return (retcode); 23664520Snw141292 } 23674520Snw141292 23684520Snw141292 static idmap_retcode 23694520Snw141292 lookup_win_name2sid(const char *name, const char *domain, char **sidprefix, 23704520Snw141292 idmap_rid_t *rid, int *type) { 23714520Snw141292 int ret; 23724520Snw141292 int retries = 0; 23734520Snw141292 idmap_query_state_t *qs = NULL; 23744520Snw141292 idmap_retcode rc, retcode; 23754520Snw141292 23764520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 23774520Snw141292 23784520Snw141292 retry: 23794520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 23804520Snw141292 if (ret != 0) { 2381*5317Sjp151216 degrade_svc(); 23824520Snw141292 idmapdlog(LOG_ERR, 23834520Snw141292 "Failed to create name2sid batch for AD lookup"); 23844520Snw141292 return (IDMAP_ERR_INTERNAL); 23854520Snw141292 } 23864520Snw141292 2387*5317Sjp151216 restore_svc(); 2388*5317Sjp151216 23894520Snw141292 retcode = idmap_name2sid_batch_add1(qs, name, domain, sidprefix, 23904520Snw141292 rid, type, &rc); 23914520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 23924520Snw141292 goto out; 23934520Snw141292 23944520Snw141292 if (retcode != IDMAP_SUCCESS) { 23954520Snw141292 idmapdlog(LOG_ERR, 23964520Snw141292 "Failed to batch name2sid for AD lookup"); 23974884Sjp151216 idmap_lookup_release_batch(&qs); 23984520Snw141292 return (IDMAP_ERR_INTERNAL); 23994520Snw141292 } 24004520Snw141292 24014520Snw141292 out: 24024520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 24034884Sjp151216 idmap_lookup_release_batch(&qs); 24044520Snw141292 else 24054520Snw141292 retcode = idmap_lookup_batch_end(&qs, NULL); 24064520Snw141292 24074520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 24084520Snw141292 goto retry; 2409*5317Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2410*5317Sjp151216 degrade_svc(); 24114520Snw141292 24124520Snw141292 if (retcode != IDMAP_SUCCESS) { 24134520Snw141292 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 24144520Snw141292 "failed"); 24154520Snw141292 return (retcode); 24164520Snw141292 } else 24174520Snw141292 return (rc); 24184520Snw141292 /* NOTREACHED */ 24194520Snw141292 } 24204520Snw141292 24214520Snw141292 static idmap_retcode 24224520Snw141292 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 24234520Snw141292 int *is_user, char **sidprefix, idmap_rid_t *rid, 24244520Snw141292 idmap_mapping *req) { 24254520Snw141292 int type; 24264520Snw141292 idmap_retcode retcode; 24274520Snw141292 24284864Sbaban /* Lookup name@domain to sid in the well-known sids table */ 24294864Sbaban retcode = lookup_wksids_name2sid(name, sidprefix, rid, &type); 24304864Sbaban if (retcode == IDMAP_SUCCESS) { 24314864Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 24324864Sbaban goto out; 24334864Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 24344864Sbaban return (retcode); 24354864Sbaban } 24364864Sbaban 24374864Sbaban /* Lookup name@domain to sid in cache */ 24384520Snw141292 retcode = lookup_cache_name2sid(cache, name, domain, sidprefix, 24394520Snw141292 rid, &type); 24404520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 24414520Snw141292 /* Lookup Windows NT/AD to map name@domain to sid */ 24424520Snw141292 retcode = lookup_win_name2sid(name, domain, sidprefix, rid, 24434520Snw141292 &type); 24444520Snw141292 if (retcode != IDMAP_SUCCESS) 24454520Snw141292 return (retcode); 24464520Snw141292 req->direction |= _IDMAP_F_S2N_AD; 24474520Snw141292 } else if (retcode != IDMAP_SUCCESS) { 24484520Snw141292 return (retcode); 24494520Snw141292 } else { 24504520Snw141292 /* Set flag */ 24514520Snw141292 req->direction |= _IDMAP_F_S2N_CACHE; 24524520Snw141292 } 24534520Snw141292 24544864Sbaban out: 24554520Snw141292 /* 24564520Snw141292 * Entry found (cache or Windows lookup) 24574520Snw141292 * is_user is both input as well as output parameter 24584520Snw141292 */ 24594520Snw141292 if (*is_user == 1) { 24604520Snw141292 if (type != _IDMAP_T_USER) 24614520Snw141292 return (IDMAP_ERR_NOTUSER); 24624520Snw141292 } else if (*is_user == 0) { 24634520Snw141292 if (type != _IDMAP_T_GROUP) 24644520Snw141292 return (IDMAP_ERR_NOTGROUP); 24654520Snw141292 } else if (*is_user == -1) { 24664520Snw141292 /* Caller wants to know if its user or group */ 24674520Snw141292 if (type == _IDMAP_T_USER) 24684520Snw141292 *is_user = 1; 24694520Snw141292 else if (type == _IDMAP_T_GROUP) 24704520Snw141292 *is_user = 0; 24714520Snw141292 else 24724520Snw141292 return (IDMAP_ERR_SID); 24734520Snw141292 } 24744520Snw141292 24754520Snw141292 return (retcode); 24764520Snw141292 } 24774520Snw141292 24784520Snw141292 static idmap_retcode 24794520Snw141292 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 24804520Snw141292 int is_user, idmap_mapping *req, idmap_id_res *res) { 24814520Snw141292 const char *winname, *windomain; 2482*5317Sjp151216 char *default_domain = NULL; 24834520Snw141292 char *sql = NULL, *errmsg = NULL; 24844520Snw141292 idmap_retcode retcode; 24854520Snw141292 char *end; 24864520Snw141292 const char **values; 24874520Snw141292 sqlite_vm *vm = NULL; 24884884Sjp151216 int ncol, r; 24894520Snw141292 const char *me = "name_based_mapping_pid2sid"; 24904520Snw141292 24914520Snw141292 RDLOCK_CONFIG(); 2492*5317Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2493*5317Sjp151216 default_domain = 2494*5317Sjp151216 strdup(_idmapdstate.cfg->pgcfg.default_domain); 2495*5317Sjp151216 if (default_domain == NULL) { 24964520Snw141292 UNLOCK_CONFIG(); 24974520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 24984520Snw141292 retcode = IDMAP_ERR_MEMORY; 24994520Snw141292 goto out; 25004520Snw141292 } 25014520Snw141292 } 25024520Snw141292 UNLOCK_CONFIG(); 25034520Snw141292 25044520Snw141292 sql = sqlite_mprintf( 25054520Snw141292 "SELECT winname, windomain, w2u_order FROM namerules WHERE " 25064520Snw141292 "u2w_order > 0 AND is_user = %d AND " 25074520Snw141292 "(unixname = %Q OR unixname = '*') " 25084520Snw141292 "ORDER BY u2w_order ASC;", 25094520Snw141292 is_user, unixname); 25104520Snw141292 if (sql == NULL) { 25114520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 25124520Snw141292 retcode = IDMAP_ERR_MEMORY; 25134520Snw141292 goto out; 25144520Snw141292 } 25154520Snw141292 25164520Snw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 25174520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25184520Snw141292 idmapdlog(LOG_ERR, 25194520Snw141292 "%s: database error (%s)", 25204520Snw141292 me, CHECK_NULL(errmsg)); 25214520Snw141292 sqlite_freemem(errmsg); 25224520Snw141292 goto out; 25234520Snw141292 } 25244520Snw141292 25254884Sjp151216 for (;;) { 25264520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 25274884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 25284884Sjp151216 if (r == SQLITE_ROW) { 25294520Snw141292 if (ncol < 3) { 25304520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25314520Snw141292 goto out; 25324520Snw141292 } 25334520Snw141292 if (values[0] == NULL) { 25344520Snw141292 /* values [1] and [2] can be null */ 25354520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25364520Snw141292 goto out; 25374520Snw141292 } 25384520Snw141292 if (EMPTY_NAME(values[0])) { 25394520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 25404520Snw141292 goto out; 25414520Snw141292 } 25424520Snw141292 winname = (values[0][0] == '*')?unixname:values[0]; 25434864Sbaban if (values[1] != NULL) 25444520Snw141292 windomain = values[1]; 2545*5317Sjp151216 else if (default_domain != NULL) 2546*5317Sjp151216 windomain = default_domain; 25474520Snw141292 else { 25484520Snw141292 idmapdlog(LOG_ERR, 25494520Snw141292 "%s: no domain", me); 25504520Snw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 25514520Snw141292 goto out; 25524520Snw141292 } 25534520Snw141292 /* Lookup winname@domain to sid */ 25544520Snw141292 retcode = lookup_name2sid(cache, winname, windomain, 25554520Snw141292 &is_user, &res->id.idmap_id_u.sid.prefix, 25564520Snw141292 &res->id.idmap_id_u.sid.rid, req); 25574520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 25584520Snw141292 if (winname == unixname) 25594520Snw141292 continue; 25604520Snw141292 else 25614520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 25624520Snw141292 } 25634520Snw141292 goto out; 25644520Snw141292 } else if (r == SQLITE_DONE) { 25654520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 25664520Snw141292 goto out; 25674520Snw141292 } else { 25684520Snw141292 (void) sqlite_finalize(vm, &errmsg); 25694520Snw141292 vm = NULL; 25704520Snw141292 idmapdlog(LOG_ERR, 25714520Snw141292 "%s: database error (%s)", 25724520Snw141292 me, CHECK_NULL(errmsg)); 25734520Snw141292 sqlite_freemem(errmsg); 25744520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25754520Snw141292 goto out; 25764520Snw141292 } 25774520Snw141292 } 25784520Snw141292 25794520Snw141292 out: 25804864Sbaban if (sql != NULL) 25814520Snw141292 sqlite_freemem(sql); 25824520Snw141292 if (retcode == IDMAP_SUCCESS) { 25834864Sbaban if (values[2] != NULL) 25844520Snw141292 res->direction = 25854644Sbaban (strtol(values[2], &end, 10) == 0)? 25864644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 25874520Snw141292 else 25884644Sbaban res->direction = IDMAP_DIRECTION_U2W; 25895064Sdm199847 25905064Sdm199847 req->id2name = strdup(winname); 25915064Sdm199847 if (req->id2name != NULL) { 2592*5317Sjp151216 if (windomain == default_domain) { 25935064Sdm199847 req->id2domain = (char *)windomain; 2594*5317Sjp151216 default_domain = NULL; 25955064Sdm199847 } else { 25965064Sdm199847 req->id2domain = strdup(windomain); 25975064Sdm199847 } 25984520Snw141292 } 25994520Snw141292 } 26004864Sbaban if (vm != NULL) 26014520Snw141292 (void) sqlite_finalize(vm, NULL); 2602*5317Sjp151216 if (default_domain != NULL) 2603*5317Sjp151216 free(default_domain); 26044520Snw141292 return (retcode); 26054520Snw141292 } 26064520Snw141292 26074520Snw141292 idmap_retcode 26084520Snw141292 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 26094520Snw141292 idmap_mapping *req, idmap_id_res *res, int is_user, 26104520Snw141292 int getname) { 26114520Snw141292 char *unixname = NULL; 26124520Snw141292 struct passwd pwd; 26134520Snw141292 struct group grp; 26144520Snw141292 char buf[1024]; 26154520Snw141292 int errnum; 26164520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 26174520Snw141292 const char *me = "pid2sid"; 26184520Snw141292 26194520Snw141292 req->direction = _IDMAP_F_DONE; 26204520Snw141292 res->id.idtype = req->id2.idtype; 26214520Snw141292 26224520Snw141292 /* Lookup well-known SIDs */ 26234520Snw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 26244520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 26254520Snw141292 goto out; 26264520Snw141292 26274520Snw141292 /* Lookup pid to sid in cache */ 26284520Snw141292 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 26294520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 26304520Snw141292 goto out; 26314520Snw141292 26324520Snw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 26334520Snw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 26344864Sbaban retcode = IDMAP_ERR_NOMAPPING; 26354520Snw141292 goto out; 26364520Snw141292 } 26374520Snw141292 26384520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 26394864Sbaban retcode = IDMAP_ERR_NOMAPPING; 26404520Snw141292 goto out; 26414520Snw141292 } 26424520Snw141292 26434520Snw141292 /* uid/gid to name */ 26445127Sdm199847 if (!EMPTY_STRING(req->id1name)) { 26455064Sdm199847 unixname = req->id1name; 26465064Sdm199847 } else if (is_user) { 26474520Snw141292 errno = 0; 26484520Snw141292 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 26494520Snw141292 sizeof (buf)) == NULL) { 26504520Snw141292 errnum = errno; 26514520Snw141292 idmapdlog(LOG_WARNING, 26524520Snw141292 "%s: getpwuid_r(%u) failed (%s).", 26534520Snw141292 me, req->id1.idmap_id_u.uid, 26544520Snw141292 errnum?strerror(errnum):"not found"); 26554520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 26564520Snw141292 IDMAP_ERR_INTERNAL; 26574520Snw141292 goto fallback_localsid; 26584520Snw141292 } 26594520Snw141292 unixname = pwd.pw_name; 26604520Snw141292 } else { 26614520Snw141292 errno = 0; 26624520Snw141292 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 26634520Snw141292 sizeof (buf)) == NULL) { 26644520Snw141292 errnum = errno; 26654520Snw141292 idmapdlog(LOG_WARNING, 26664520Snw141292 "%s: getgrgid_r(%u) failed (%s).", 26674520Snw141292 me, req->id1.idmap_id_u.gid, 26684520Snw141292 errnum?strerror(errnum):"not found"); 26694520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 26704520Snw141292 IDMAP_ERR_INTERNAL; 26714520Snw141292 goto fallback_localsid; 26724520Snw141292 } 26734520Snw141292 unixname = grp.gr_name; 26744520Snw141292 } 26754520Snw141292 26764520Snw141292 /* Name-based mapping */ 26774520Snw141292 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 26784520Snw141292 req, res); 26794520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 26804520Snw141292 retcode = generate_localsid(req, res, is_user); 26814520Snw141292 goto out; 26824520Snw141292 } else if (retcode == IDMAP_SUCCESS) 26834520Snw141292 goto out; 26844520Snw141292 26854520Snw141292 fallback_localsid: 26864520Snw141292 /* 26874520Snw141292 * Here we generate localsid as fallback id on errors. Our 26884520Snw141292 * return status is the error that's been previously assigned. 26894520Snw141292 */ 26904520Snw141292 (void) generate_localsid(req, res, is_user); 26914520Snw141292 26924520Snw141292 out: 26935127Sdm199847 if (retcode == IDMAP_SUCCESS && EMPTY_STRING(req->id1name) && 26945064Sdm199847 unixname != NULL) { 26955127Sdm199847 if (req->id1name != NULL) 26965127Sdm199847 free(req->id1name); 26975064Sdm199847 req->id1name = strdup(unixname); 26985127Sdm199847 if (req->id1name == NULL) 26995127Sdm199847 retcode = IDMAP_ERR_MEMORY; 27004520Snw141292 } 27014520Snw141292 if (req->direction != _IDMAP_F_DONE) 27024520Snw141292 state->pid2sid_done = FALSE; 27034520Snw141292 res->retcode = idmap_stat4prot(retcode); 27044520Snw141292 return (retcode); 27054520Snw141292 } 27064520Snw141292 27074520Snw141292 static idmap_retcode 27084520Snw141292 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 27094520Snw141292 char **domain, int *type) { 27104520Snw141292 int ret; 27114520Snw141292 idmap_query_state_t *qs = NULL; 27124520Snw141292 idmap_retcode rc, retcode; 27134520Snw141292 27144520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 27154520Snw141292 27164520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 27174520Snw141292 if (ret != 0) { 2718*5317Sjp151216 degrade_svc(); 27194520Snw141292 idmapdlog(LOG_ERR, 27204520Snw141292 "Failed to create sid2name batch for AD lookup"); 27214520Snw141292 retcode = IDMAP_ERR_INTERNAL; 27224520Snw141292 goto out; 27234520Snw141292 } 27244520Snw141292 2725*5317Sjp151216 restore_svc(); 2726*5317Sjp151216 27274520Snw141292 ret = idmap_sid2name_batch_add1( 27284520Snw141292 qs, sidprefix, &rid, name, domain, type, &rc); 27294520Snw141292 if (ret != 0) { 27304520Snw141292 idmapdlog(LOG_ERR, 27314520Snw141292 "Failed to batch sid2name for AD lookup"); 27324520Snw141292 retcode = IDMAP_ERR_INTERNAL; 27334520Snw141292 goto out; 27344520Snw141292 } 27354520Snw141292 27364520Snw141292 out: 27374864Sbaban if (qs != NULL) { 27384520Snw141292 ret = idmap_lookup_batch_end(&qs, NULL); 2739*5317Sjp151216 if (ret == IDMAP_ERR_RETRIABLE_NET_ERR) 2740*5317Sjp151216 degrade_svc(); 27414520Snw141292 if (ret != 0) { 27424520Snw141292 idmapdlog(LOG_ERR, 27434520Snw141292 "Failed to execute sid2name AD lookup"); 27444520Snw141292 retcode = IDMAP_ERR_INTERNAL; 27454520Snw141292 } else 27464520Snw141292 retcode = rc; 27474520Snw141292 } 27484520Snw141292 27494520Snw141292 return (retcode); 27504520Snw141292 } 27514520Snw141292 27524644Sbaban static int 27534644Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 27544520Snw141292 { 27554644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 27564644Sbaban 27574520Snw141292 mapping->flag = request->flag; 27584520Snw141292 mapping->direction = request->direction; 27594644Sbaban mapping->id2.idtype = request->id2.idtype; 27604520Snw141292 27614520Snw141292 mapping->id1.idtype = request->id1.idtype; 27624520Snw141292 if (request->id1.idtype == IDMAP_SID) { 27634520Snw141292 mapping->id1.idmap_id_u.sid.rid = 27644520Snw141292 request->id1.idmap_id_u.sid.rid; 27654644Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 27664520Snw141292 mapping->id1.idmap_id_u.sid.prefix = 27674520Snw141292 strdup(request->id1.idmap_id_u.sid.prefix); 27684644Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 27695064Sdm199847 goto errout; 27704644Sbaban } 27714520Snw141292 } else { 27724520Snw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 27734520Snw141292 } 27744520Snw141292 27755064Sdm199847 mapping->id1domain = strdup(request->id1domain); 27765064Sdm199847 if (mapping->id1domain == NULL) 27775064Sdm199847 goto errout; 27784520Snw141292 27795064Sdm199847 mapping->id1name = strdup(request->id1name); 27805064Sdm199847 if (mapping->id1name == NULL) 27815064Sdm199847 goto errout; 27824520Snw141292 27834644Sbaban /* We don't need the rest of the request i.e request->id2 */ 27844644Sbaban return (0); 27854644Sbaban 27864644Sbaban errout: 27875064Sdm199847 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 27884644Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 27895064Sdm199847 if (mapping->id1domain != NULL) 27905064Sdm199847 free(mapping->id1domain); 27915064Sdm199847 if (mapping->id1name != NULL) 27925064Sdm199847 free(mapping->id1name); 27934644Sbaban 27944644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 27954644Sbaban return (-1); 27964520Snw141292 } 27974520Snw141292 27984520Snw141292 27994520Snw141292 idmap_retcode 28004520Snw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 28014520Snw141292 idmap_mapping *mapping) { 28024520Snw141292 idmap_id_res idres; 28034520Snw141292 lookup_state_t state; 28045043Sbaban char *cp; 28054520Snw141292 int is_user; 28064520Snw141292 idmap_retcode retcode; 28074520Snw141292 const char *winname, *windomain; 28084520Snw141292 28094520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 28104520Snw141292 (void) memset(&state, 0, sizeof (state)); 28114520Snw141292 28124520Snw141292 if (request->id2.idtype == IDMAP_UID) 28134520Snw141292 is_user = 1; 28144520Snw141292 else if (request->id2.idtype == IDMAP_GID) 28154520Snw141292 is_user = 0; 28164520Snw141292 else if (request->id2.idtype == IDMAP_POSIXID) 28174520Snw141292 is_user = -1; 28184520Snw141292 else { 28194520Snw141292 retcode = IDMAP_ERR_IDTYPE; 28204520Snw141292 goto out; 28214520Snw141292 } 28224520Snw141292 28234520Snw141292 /* Copy data from request to result */ 28244644Sbaban if (copy_mapping_request(mapping, request) < 0) { 28254644Sbaban retcode = IDMAP_ERR_MEMORY; 28264644Sbaban goto out; 28274644Sbaban } 28284520Snw141292 28295064Sdm199847 winname = mapping->id1name; 28305064Sdm199847 windomain = mapping->id1domain; 28314520Snw141292 28325127Sdm199847 if (EMPTY_STRING(winname) && !EMPTY_STRING(windomain)) { 28334520Snw141292 retcode = IDMAP_ERR_ARG; 28344520Snw141292 goto out; 28354520Snw141292 } 28364520Snw141292 28375127Sdm199847 if (!EMPTY_STRING(winname) && EMPTY_STRING(windomain)) { 28385064Sdm199847 retcode = IDMAP_SUCCESS; 28395043Sbaban if ((cp = strchr(winname, '@')) != NULL) { 28405043Sbaban /* 28415043Sbaban * if winname is qualified with a domain, use it. 28425043Sbaban */ 28435043Sbaban *cp = '\0'; 28445064Sdm199847 mapping->id1domain = strdup(cp + 1); 28455064Sdm199847 if (mapping->id1domain == NULL) 28465064Sdm199847 retcode = IDMAP_ERR_MEMORY; 28475064Sdm199847 } else { 28485064Sdm199847 RDLOCK_CONFIG(); 2849*5317Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 28505043Sbaban /* 28515043Sbaban * otherwise use the mapping domain 28525043Sbaban */ 28535064Sdm199847 mapping->id1domain = 28545064Sdm199847 strdup(_idmapdstate.cfg-> 2855*5317Sjp151216 pgcfg.default_domain); 28565064Sdm199847 if (mapping->id1domain == NULL) 28575064Sdm199847 retcode = IDMAP_ERR_MEMORY; 28585064Sdm199847 } 28595043Sbaban UNLOCK_CONFIG(); 28605064Sdm199847 } 28615043Sbaban 28625043Sbaban if (retcode != IDMAP_SUCCESS) { 28635043Sbaban idmapdlog(LOG_ERR, "Out of memory"); 28645043Sbaban goto out; 28654520Snw141292 } 28665064Sdm199847 windomain = mapping->id1domain; 28674520Snw141292 } 28684520Snw141292 28695127Sdm199847 if (!EMPTY_STRING(winname) && 28705127Sdm199847 EMPTY_STRING(mapping->id1.idmap_id_u.sid.prefix)) { 28714520Snw141292 retcode = lookup_name2sid(cache, winname, windomain, 28724520Snw141292 &is_user, &mapping->id1.idmap_id_u.sid.prefix, 28734520Snw141292 &mapping->id1.idmap_id_u.sid.rid, mapping); 28744520Snw141292 if (retcode != IDMAP_SUCCESS) 28754520Snw141292 goto out; 28764520Snw141292 if (mapping->id2.idtype == IDMAP_POSIXID) 28774520Snw141292 mapping->id2.idtype = is_user?IDMAP_UID:IDMAP_GID; 28784520Snw141292 } 28794520Snw141292 28804520Snw141292 state.sid2pid_done = TRUE; 28814520Snw141292 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 28824520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 28834520Snw141292 goto out; 28844520Snw141292 28854520Snw141292 if (state.ad_nqueries) { 28864520Snw141292 /* sid2name AD lookup */ 28874520Snw141292 retcode = lookup_win_sid2name( 28884520Snw141292 mapping->id1.idmap_id_u.sid.prefix, 28894520Snw141292 mapping->id1.idmap_id_u.sid.rid, 28905064Sdm199847 &mapping->id1name, 28915064Sdm199847 &mapping->id1domain, 28924520Snw141292 (int *)&idres.id.idtype); 28934520Snw141292 28944520Snw141292 idres.retcode = retcode; 28954520Snw141292 } 28964520Snw141292 28974520Snw141292 state.sid2pid_done = TRUE; 28984520Snw141292 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 28994520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 29004520Snw141292 goto out; 29014520Snw141292 29024520Snw141292 /* Update cache */ 29034520Snw141292 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 29044520Snw141292 29054520Snw141292 out: 29064520Snw141292 if (retcode == IDMAP_SUCCESS) { 29074520Snw141292 mapping->direction = idres.direction; 29084520Snw141292 mapping->id2 = idres.id; 29094520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 29104864Sbaban } else { 29114864Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 29124520Snw141292 } 29134520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 29144520Snw141292 return (retcode); 29154520Snw141292 } 29164520Snw141292 29174520Snw141292 idmap_retcode 29184520Snw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 29194520Snw141292 idmap_mapping *mapping, int is_user) { 29204520Snw141292 idmap_id_res idres; 29214520Snw141292 lookup_state_t state; 29224520Snw141292 struct passwd pwd; 29234520Snw141292 struct group grp; 29244520Snw141292 char buf[1024]; 29254520Snw141292 int errnum; 29264520Snw141292 idmap_retcode retcode; 29274520Snw141292 const char *unixname; 29284520Snw141292 const char *me = "get_u2w_mapping"; 29294520Snw141292 29304520Snw141292 /* 29314520Snw141292 * In order to re-use the pid2sid code, we convert 29324520Snw141292 * our input data into structs that are expected by 29334520Snw141292 * pid2sid_first_pass. 29344520Snw141292 */ 29354520Snw141292 29364520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 29374520Snw141292 (void) memset(&state, 0, sizeof (state)); 29384520Snw141292 29394520Snw141292 /* Copy data from request to result */ 29404644Sbaban if (copy_mapping_request(mapping, request) < 0) { 29414644Sbaban retcode = IDMAP_ERR_MEMORY; 29424644Sbaban goto out; 29434644Sbaban } 29444520Snw141292 29455064Sdm199847 unixname = mapping->id1name; 29464520Snw141292 29475127Sdm199847 if (EMPTY_STRING(unixname) && 29485127Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 29494520Snw141292 retcode = IDMAP_ERR_ARG; 29504520Snw141292 goto out; 29514520Snw141292 } 29524520Snw141292 29535127Sdm199847 if (!EMPTY_STRING(unixname) && 29545127Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 29554520Snw141292 /* Get uid/gid by name */ 29564520Snw141292 if (is_user) { 29574520Snw141292 errno = 0; 29584520Snw141292 if (getpwnam_r(unixname, &pwd, buf, 29594520Snw141292 sizeof (buf)) == NULL) { 29604520Snw141292 errnum = errno; 29614520Snw141292 idmapdlog(LOG_WARNING, 29624520Snw141292 "%s: getpwnam_r(%s) failed (%s).", 29634520Snw141292 me, unixname, 29644520Snw141292 errnum?strerror(errnum):"not found"); 29654520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 29664520Snw141292 IDMAP_ERR_INTERNAL; 29674520Snw141292 goto out; 29684520Snw141292 } 29694520Snw141292 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 29704520Snw141292 } else { 29714520Snw141292 errno = 0; 29724520Snw141292 if (getgrnam_r(unixname, &grp, buf, 29734520Snw141292 sizeof (buf)) == NULL) { 29744520Snw141292 errnum = errno; 29754520Snw141292 idmapdlog(LOG_WARNING, 29764520Snw141292 "%s: getgrnam_r(%s) failed (%s).", 29774520Snw141292 me, unixname, 29784520Snw141292 errnum?strerror(errnum):"not found"); 29794520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 29804520Snw141292 IDMAP_ERR_INTERNAL; 29814520Snw141292 goto out; 29824520Snw141292 } 29834520Snw141292 mapping->id1.idmap_id_u.gid = grp.gr_gid; 29844520Snw141292 } 29854520Snw141292 } 29864520Snw141292 29874520Snw141292 state.pid2sid_done = TRUE; 29884520Snw141292 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 29894520Snw141292 is_user, 1); 29904520Snw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 29914520Snw141292 goto out; 29924520Snw141292 29934520Snw141292 /* Update cache */ 29944520Snw141292 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 29954520Snw141292 29964520Snw141292 out: 29974520Snw141292 mapping->direction = idres.direction; 29984520Snw141292 mapping->id2 = idres.id; 29994520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 30004520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 30014520Snw141292 return (retcode); 30024520Snw141292 } 3003