1c5c4113dSnw141292 /* 2c5c4113dSnw141292 * CDDL HEADER START 3c5c4113dSnw141292 * 4c5c4113dSnw141292 * The contents of this file are subject to the terms of the 5c5c4113dSnw141292 * Common Development and Distribution License (the "License"). 6c5c4113dSnw141292 * You may not use this file except in compliance with the License. 7c5c4113dSnw141292 * 8c5c4113dSnw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c5c4113dSnw141292 * or http://www.opensolaris.org/os/licensing. 10c5c4113dSnw141292 * See the License for the specific language governing permissions 11c5c4113dSnw141292 * and limitations under the License. 12c5c4113dSnw141292 * 13c5c4113dSnw141292 * When distributing Covered Code, include this CDDL HEADER in each 14c5c4113dSnw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c5c4113dSnw141292 * If applicable, add the following below this CDDL HEADER, with the 16c5c4113dSnw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17c5c4113dSnw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18c5c4113dSnw141292 * 19c5c4113dSnw141292 * CDDL HEADER END 20c5c4113dSnw141292 */ 21c5c4113dSnw141292 /* 22c5c4113dSnw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23c5c4113dSnw141292 * Use is subject to license terms. 24c5c4113dSnw141292 */ 25c5c4113dSnw141292 26c5c4113dSnw141292 #pragma ident "%Z%%M% %I% %E% SMI" 27c5c4113dSnw141292 28c5c4113dSnw141292 /* 29c5c4113dSnw141292 * Database related utility routines 30c5c4113dSnw141292 */ 31c5c4113dSnw141292 32*c8e26105Sjp151216 #include <atomic.h> 33c5c4113dSnw141292 #include <stdio.h> 34c5c4113dSnw141292 #include <stdlib.h> 35c5c4113dSnw141292 #include <string.h> 36c5c4113dSnw141292 #include <errno.h> 37c5c4113dSnw141292 #include <sys/types.h> 38c5c4113dSnw141292 #include <sys/stat.h> 39c5c4113dSnw141292 #include <rpc/rpc.h> 40c5c4113dSnw141292 #include <sys/sid.h> 41c5c4113dSnw141292 #include <time.h> 42c5c4113dSnw141292 #include <pwd.h> 43c5c4113dSnw141292 #include <grp.h> 4484decf41Sjp151216 #include <pthread.h> 4584decf41Sjp151216 #include <assert.h> 46c5c4113dSnw141292 47c5c4113dSnw141292 #include "idmapd.h" 48c5c4113dSnw141292 #include "adutils.h" 49c5c4113dSnw141292 #include "string.h" 50c5c4113dSnw141292 #include "idmap_priv.h" 51c5c4113dSnw141292 5284decf41Sjp151216 53*c8e26105Sjp151216 static int degraded = 0; /* whether the FMRI has been marked degraded */ 54*c8e26105Sjp151216 55c5c4113dSnw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 56c5c4113dSnw141292 sqlite_vm **, int *, int, const char ***); 5762c60062Sbaban static idmap_retcode lookup_wksids_name2sid(const char *, char **, 5862c60062Sbaban idmap_rid_t *, int *); 59c5c4113dSnw141292 60c5c4113dSnw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 61c5c4113dSnw141292 62c5c4113dSnw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 63c5c4113dSnw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 64c5c4113dSnw141292 65c5c4113dSnw141292 #define AVOID_NAMESERVICE(req)\ 66c5c4113dSnw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 67c5c4113dSnw141292 68c5c4113dSnw141292 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 69c5c4113dSnw141292 70c5c4113dSnw141292 #define LOCALRID_MIN 1000 71c5c4113dSnw141292 72c5c4113dSnw141292 73c5c4113dSnw141292 74c5c4113dSnw141292 typedef enum init_db_option { 75c5c4113dSnw141292 FAIL_IF_CORRUPT = 0, 76c5c4113dSnw141292 REMOVE_IF_CORRUPT = 1 77c5c4113dSnw141292 } init_db_option_t; 78c5c4113dSnw141292 7984decf41Sjp151216 /* 8084decf41Sjp151216 * Thread specfic data to hold the database handles so that the 8184decf41Sjp151216 * databaes are not opened and closed for every request. It also 8284decf41Sjp151216 * contains the sqlite busy handler structure. 8384decf41Sjp151216 */ 8484decf41Sjp151216 8584decf41Sjp151216 struct idmap_busy { 8684decf41Sjp151216 const char *name; 8784decf41Sjp151216 const int *delays; 8884decf41Sjp151216 int delay_size; 8984decf41Sjp151216 int total; 9084decf41Sjp151216 int sec; 9184decf41Sjp151216 }; 9284decf41Sjp151216 9384decf41Sjp151216 9484decf41Sjp151216 typedef struct idmap_tsd { 9584decf41Sjp151216 sqlite *db_db; 9684decf41Sjp151216 sqlite *cache_db; 9784decf41Sjp151216 struct idmap_busy cache_busy; 9884decf41Sjp151216 struct idmap_busy db_busy; 9984decf41Sjp151216 } idmap_tsd_t; 10084decf41Sjp151216 10184decf41Sjp151216 10284decf41Sjp151216 10384decf41Sjp151216 static const int cache_delay_table[] = 10484decf41Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 10584decf41Sjp151216 50, 50, 60, 70, 80, 90, 100}; 10684decf41Sjp151216 10784decf41Sjp151216 static const int db_delay_table[] = 10884decf41Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 10984decf41Sjp151216 11084decf41Sjp151216 11184decf41Sjp151216 static pthread_key_t idmap_tsd_key; 11284decf41Sjp151216 11384decf41Sjp151216 void 11484decf41Sjp151216 idmap_tsd_destroy(void *key) 11584decf41Sjp151216 { 11684decf41Sjp151216 11784decf41Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 11884decf41Sjp151216 if (tsd) { 11984decf41Sjp151216 if (tsd->db_db) 12084decf41Sjp151216 (void) sqlite_close(tsd->db_db); 12184decf41Sjp151216 if (tsd->cache_db) 12284decf41Sjp151216 (void) sqlite_close(tsd->cache_db); 12384decf41Sjp151216 free(tsd); 12484decf41Sjp151216 } 12584decf41Sjp151216 } 12684decf41Sjp151216 12784decf41Sjp151216 int 12884decf41Sjp151216 idmap_init_tsd_key(void) { 12984decf41Sjp151216 13084decf41Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 13184decf41Sjp151216 } 13284decf41Sjp151216 13384decf41Sjp151216 13484decf41Sjp151216 13584decf41Sjp151216 idmap_tsd_t * 13684decf41Sjp151216 idmap_get_tsd(void) 13784decf41Sjp151216 { 13884decf41Sjp151216 idmap_tsd_t *tsd; 13984decf41Sjp151216 14084decf41Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 14184decf41Sjp151216 /* No thread specific data so create it */ 14284decf41Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 14384decf41Sjp151216 /* Initialize thread specific data */ 14484decf41Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 14584decf41Sjp151216 /* save the trhread specific data */ 14684decf41Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 14784decf41Sjp151216 /* Can't store key */ 14884decf41Sjp151216 free(tsd); 14984decf41Sjp151216 tsd = NULL; 15084decf41Sjp151216 } 15184decf41Sjp151216 } else { 15284decf41Sjp151216 tsd = NULL; 15384decf41Sjp151216 } 15484decf41Sjp151216 } 15584decf41Sjp151216 15684decf41Sjp151216 return (tsd); 15784decf41Sjp151216 } 15884decf41Sjp151216 159*c8e26105Sjp151216 /* 160*c8e26105Sjp151216 * Wrappers for smf_degrade/restore_instance() 161*c8e26105Sjp151216 * 162*c8e26105Sjp151216 * smf_restore_instance() is too heavy duty to be calling every time we 163*c8e26105Sjp151216 * have a successful AD name<->SID lookup. 164*c8e26105Sjp151216 */ 165*c8e26105Sjp151216 void 166*c8e26105Sjp151216 degrade_svc(void) 167*c8e26105Sjp151216 { 168*c8e26105Sjp151216 membar_consumer(); 169*c8e26105Sjp151216 if (degraded) 170*c8e26105Sjp151216 return; 171*c8e26105Sjp151216 (void) smf_degrade_instance(NULL, 0); 172*c8e26105Sjp151216 membar_producer(); 173*c8e26105Sjp151216 degraded = 1; 174*c8e26105Sjp151216 } 175*c8e26105Sjp151216 176*c8e26105Sjp151216 177*c8e26105Sjp151216 void 178*c8e26105Sjp151216 restore_svc(void) 179*c8e26105Sjp151216 { 180*c8e26105Sjp151216 membar_consumer(); 181*c8e26105Sjp151216 if (!degraded) 182*c8e26105Sjp151216 return; 183*c8e26105Sjp151216 (void) smf_restore_instance(NULL); 184*c8e26105Sjp151216 membar_producer(); 185*c8e26105Sjp151216 degraded = 0; 186*c8e26105Sjp151216 } 18784decf41Sjp151216 188c5c4113dSnw141292 189c5c4113dSnw141292 /* 190c5c4113dSnw141292 * Initialize 'dbname' using 'sql' 191c5c4113dSnw141292 */ 192c5c4113dSnw141292 static int 193c5c4113dSnw141292 init_db_instance(const char *dbname, const char *sql, init_db_option_t opt, 194c5c4113dSnw141292 int *new_db_created) 195c5c4113dSnw141292 { 196c5c4113dSnw141292 int rc = 0; 197c5c4113dSnw141292 int tries = 0; 198c5c4113dSnw141292 sqlite *db = NULL; 199c5c4113dSnw141292 char *str = NULL; 200c5c4113dSnw141292 201c5c4113dSnw141292 if (new_db_created != NULL) 202c5c4113dSnw141292 *new_db_created = 0; 203c5c4113dSnw141292 204c5c4113dSnw141292 db = sqlite_open(dbname, 0600, &str); 205c5c4113dSnw141292 while (db == NULL) { 206c5c4113dSnw141292 idmapdlog(LOG_ERR, 207c5c4113dSnw141292 "Error creating database %s (%s)", 208c5c4113dSnw141292 dbname, CHECK_NULL(str)); 209c5c4113dSnw141292 sqlite_freemem(str); 210c5c4113dSnw141292 if (opt == FAIL_IF_CORRUPT || opt != REMOVE_IF_CORRUPT || 211c5c4113dSnw141292 tries > 0) 212c5c4113dSnw141292 return (-1); 213c5c4113dSnw141292 214c5c4113dSnw141292 tries++; 215c5c4113dSnw141292 (void) unlink(dbname); 216c5c4113dSnw141292 db = sqlite_open(dbname, 0600, &str); 217c5c4113dSnw141292 } 218c5c4113dSnw141292 219c5c4113dSnw141292 sqlite_busy_timeout(db, 3000); 220c5c4113dSnw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &str); 221c5c4113dSnw141292 if (SQLITE_OK != rc) { 222c5c4113dSnw141292 idmapdlog(LOG_ERR, "Cannot begin database transaction (%s)", 223c5c4113dSnw141292 str); 224c5c4113dSnw141292 sqlite_freemem(str); 225c5c4113dSnw141292 sqlite_close(db); 226c5c4113dSnw141292 return (1); 227c5c4113dSnw141292 } 228c5c4113dSnw141292 229c5c4113dSnw141292 switch (sqlite_exec(db, sql, NULL, NULL, &str)) { 230c5c4113dSnw141292 case SQLITE_ERROR: 231c5c4113dSnw141292 /* 232c5c4113dSnw141292 * This is the normal situation: CREATE probably failed because tables 233c5c4113dSnw141292 * already exist. It may indicate an error in SQL as well, but we cannot 234c5c4113dSnw141292 * tell. 235c5c4113dSnw141292 */ 236c5c4113dSnw141292 sqlite_freemem(str); 237c5c4113dSnw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 238c5c4113dSnw141292 NULL, NULL, &str); 239c5c4113dSnw141292 break; 240c5c4113dSnw141292 case SQLITE_OK: 241c5c4113dSnw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", 242c5c4113dSnw141292 NULL, NULL, &str); 243c5c4113dSnw141292 idmapdlog(LOG_INFO, 244c5c4113dSnw141292 "Database created at %s", dbname); 245c5c4113dSnw141292 246c5c4113dSnw141292 if (new_db_created != NULL) 247c5c4113dSnw141292 *new_db_created = 1; 248c5c4113dSnw141292 break; 249c5c4113dSnw141292 default: 250c5c4113dSnw141292 idmapdlog(LOG_ERR, 251c5c4113dSnw141292 "Error initializing database %s (%s)", 252c5c4113dSnw141292 dbname, str); 253c5c4113dSnw141292 sqlite_freemem(str); 254c5c4113dSnw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 255c5c4113dSnw141292 NULL, NULL, &str); 256c5c4113dSnw141292 break; 257c5c4113dSnw141292 } 258c5c4113dSnw141292 259c5c4113dSnw141292 if (SQLITE_OK != rc) { 260c5c4113dSnw141292 /* this is bad - database may be left in a locked state */ 261c5c4113dSnw141292 idmapdlog(LOG_ERR, 262c5c4113dSnw141292 "Error closing transaction (%s)", str); 263c5c4113dSnw141292 sqlite_freemem(str); 264c5c4113dSnw141292 } 265c5c4113dSnw141292 266c5c4113dSnw141292 (void) sqlite_close(db); 267c5c4113dSnw141292 return (rc); 268c5c4113dSnw141292 } 269c5c4113dSnw141292 27084decf41Sjp151216 27184decf41Sjp151216 /* 27284decf41Sjp151216 * This is the SQLite database busy handler that retries the SQL 27384decf41Sjp151216 * operation until it is successful. 27484decf41Sjp151216 */ 27584decf41Sjp151216 int 27684decf41Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 27784decf41Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 27884decf41Sjp151216 { 27984decf41Sjp151216 struct idmap_busy *busy = arg; 28084decf41Sjp151216 int delay; 28184decf41Sjp151216 struct timespec rqtp; 28284decf41Sjp151216 28384decf41Sjp151216 if (count == 1) { 28484decf41Sjp151216 busy->total = 0; 28584decf41Sjp151216 busy->sec = 2; 28684decf41Sjp151216 } 28784decf41Sjp151216 if (busy->total > 1000 * busy->sec) { 28884decf41Sjp151216 idmapdlog(LOG_ERR, 28984decf41Sjp151216 "Thread %d waited %d sec for the %s database", 29084decf41Sjp151216 pthread_self(), busy->sec, busy->name); 29184decf41Sjp151216 busy->sec++; 29284decf41Sjp151216 } 29384decf41Sjp151216 29484decf41Sjp151216 if (count <= busy->delay_size) { 29584decf41Sjp151216 delay = busy->delays[count-1]; 29684decf41Sjp151216 } else { 29784decf41Sjp151216 delay = busy->delays[busy->delay_size - 1]; 29884decf41Sjp151216 } 29984decf41Sjp151216 busy->total += delay; 30084decf41Sjp151216 rqtp.tv_sec = 0; 30184decf41Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 30284decf41Sjp151216 (void) nanosleep(&rqtp, NULL); 30384decf41Sjp151216 return (1); 30484decf41Sjp151216 } 30584decf41Sjp151216 30684decf41Sjp151216 307c5c4113dSnw141292 /* 308c5c4113dSnw141292 * Get the database handle 309c5c4113dSnw141292 */ 310c5c4113dSnw141292 idmap_retcode 311c5c4113dSnw141292 get_db_handle(sqlite **db) { 312c5c4113dSnw141292 char *errmsg; 31384decf41Sjp151216 idmap_tsd_t *tsd; 314c5c4113dSnw141292 315c5c4113dSnw141292 /* 31684decf41Sjp151216 * Retrieve the db handle from thread-specific storage 317c5c4113dSnw141292 * If none exists, open and store in thread-specific storage. 318c5c4113dSnw141292 */ 31984decf41Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 32084decf41Sjp151216 idmapdlog(LOG_ERR, 32184decf41Sjp151216 "Error getting thread specific data for %s", 32284decf41Sjp151216 IDMAP_DBNAME); 32384decf41Sjp151216 return (IDMAP_ERR_MEMORY); 32484decf41Sjp151216 } 325c5c4113dSnw141292 32684decf41Sjp151216 if (tsd->db_db == NULL) { 32784decf41Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 32884decf41Sjp151216 if (tsd->db_db == NULL) { 329c5c4113dSnw141292 idmapdlog(LOG_ERR, 330c5c4113dSnw141292 "Error opening database %s (%s)", 331c5c4113dSnw141292 IDMAP_DBNAME, CHECK_NULL(errmsg)); 332c5c4113dSnw141292 sqlite_freemem(errmsg); 333c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 334c5c4113dSnw141292 } 33584decf41Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 33684decf41Sjp151216 tsd->db_busy.delays = db_delay_table; 33784decf41Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 33884decf41Sjp151216 sizeof (int); 33984decf41Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 34084decf41Sjp151216 &tsd->db_busy); 34184decf41Sjp151216 } 34284decf41Sjp151216 *db = tsd->db_db; 343c5c4113dSnw141292 return (IDMAP_SUCCESS); 344c5c4113dSnw141292 } 345c5c4113dSnw141292 346c5c4113dSnw141292 /* 347c5c4113dSnw141292 * Get the cache handle 348c5c4113dSnw141292 */ 349c5c4113dSnw141292 idmap_retcode 35084decf41Sjp151216 get_cache_handle(sqlite **cache) { 351c5c4113dSnw141292 char *errmsg; 35284decf41Sjp151216 idmap_tsd_t *tsd; 353c5c4113dSnw141292 354c5c4113dSnw141292 /* 35584decf41Sjp151216 * Retrieve the db handle from thread-specific storage 356c5c4113dSnw141292 * If none exists, open and store in thread-specific storage. 357c5c4113dSnw141292 */ 35884decf41Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 35984decf41Sjp151216 idmapdlog(LOG_ERR, 36084decf41Sjp151216 "Error getting thread specific data for %s", 36184decf41Sjp151216 IDMAP_DBNAME); 36284decf41Sjp151216 return (IDMAP_ERR_MEMORY); 36384decf41Sjp151216 } 364c5c4113dSnw141292 36584decf41Sjp151216 if (tsd->cache_db == NULL) { 36684decf41Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 36784decf41Sjp151216 if (tsd->cache_db == NULL) { 368c5c4113dSnw141292 idmapdlog(LOG_ERR, 369c5c4113dSnw141292 "Error opening database %s (%s)", 370c5c4113dSnw141292 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 371c5c4113dSnw141292 sqlite_freemem(errmsg); 372c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 373c5c4113dSnw141292 } 37484decf41Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 37584decf41Sjp151216 tsd->cache_busy.delays = cache_delay_table; 37684decf41Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 37784decf41Sjp151216 sizeof (int); 37884decf41Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 37984decf41Sjp151216 &tsd->cache_busy); 38084decf41Sjp151216 } 38184decf41Sjp151216 *cache = tsd->cache_db; 382c5c4113dSnw141292 return (IDMAP_SUCCESS); 383c5c4113dSnw141292 } 384c5c4113dSnw141292 385c5c4113dSnw141292 #define CACHE_SQL\ 386c5c4113dSnw141292 "CREATE TABLE idmap_cache ("\ 387c5c4113dSnw141292 " sidprefix TEXT,"\ 388c5c4113dSnw141292 " rid INTEGER,"\ 389c5c4113dSnw141292 " windomain TEXT,"\ 390c5c4113dSnw141292 " winname TEXT,"\ 391c5c4113dSnw141292 " pid INTEGER,"\ 392c5c4113dSnw141292 " unixname TEXT,"\ 393c5c4113dSnw141292 " is_user INTEGER,"\ 394c5c4113dSnw141292 " w2u INTEGER,"\ 395c5c4113dSnw141292 " u2w INTEGER,"\ 396c5c4113dSnw141292 " expiration INTEGER"\ 397c5c4113dSnw141292 ");"\ 398c5c4113dSnw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache"\ 399c5c4113dSnw141292 " (sidprefix, rid, w2u);"\ 400c5c4113dSnw141292 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache"\ 401c5c4113dSnw141292 " (pid, is_user, u2w);"\ 402c5c4113dSnw141292 "CREATE TABLE name_cache ("\ 403c5c4113dSnw141292 " sidprefix TEXT,"\ 404c5c4113dSnw141292 " rid INTEGER,"\ 405c5c4113dSnw141292 " name TEXT,"\ 406c5c4113dSnw141292 " domain TEXT,"\ 407c5c4113dSnw141292 " type INTEGER,"\ 408c5c4113dSnw141292 " expiration INTEGER"\ 409c5c4113dSnw141292 ");"\ 410c5c4113dSnw141292 "CREATE UNIQUE INDEX name_cache_sid ON name_cache"\ 411c5c4113dSnw141292 " (sidprefix, rid);" 412c5c4113dSnw141292 413c5c4113dSnw141292 #define DB_SQL\ 414c5c4113dSnw141292 "CREATE TABLE namerules ("\ 415c5c4113dSnw141292 " is_user INTEGER NOT NULL,"\ 416c5c4113dSnw141292 " windomain TEXT,"\ 417c5c4113dSnw141292 " winname TEXT NOT NULL,"\ 418c5c4113dSnw141292 " is_nt4 INTEGER NOT NULL,"\ 419c5c4113dSnw141292 " unixname NOT NULL,"\ 420c5c4113dSnw141292 " w2u_order INTEGER,"\ 421c5c4113dSnw141292 " u2w_order INTEGER"\ 422c5c4113dSnw141292 ");"\ 423c5c4113dSnw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules"\ 424c5c4113dSnw141292 " (winname, windomain, is_user, w2u_order);"\ 425c5c4113dSnw141292 "CREATE UNIQUE INDEX namerules_u2w ON namerules"\ 426c5c4113dSnw141292 " (unixname, is_user, u2w_order);" 427c5c4113dSnw141292 428c5c4113dSnw141292 /* 429c5c4113dSnw141292 * Initialize cache and db 430c5c4113dSnw141292 */ 431c5c4113dSnw141292 int 432c5c4113dSnw141292 init_dbs() { 433c5c4113dSnw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 434c5c4113dSnw141292 if (init_db_instance(IDMAP_DBNAME, DB_SQL, FAIL_IF_CORRUPT, NULL) < 0) 435c5c4113dSnw141292 return (-1); 436c5c4113dSnw141292 437c5c4113dSnw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 438c5c4113dSnw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_SQL, REMOVE_IF_CORRUPT, 439c5c4113dSnw141292 &_idmapdstate.new_eph_db) < 0) 440c5c4113dSnw141292 return (-1); 441c5c4113dSnw141292 442c5c4113dSnw141292 return (0); 443c5c4113dSnw141292 } 444c5c4113dSnw141292 445c5c4113dSnw141292 /* 446c5c4113dSnw141292 * Finalize databases 447c5c4113dSnw141292 */ 448c5c4113dSnw141292 void 449c5c4113dSnw141292 fini_dbs() { 450c5c4113dSnw141292 } 451c5c4113dSnw141292 452c5c4113dSnw141292 /* 453c5c4113dSnw141292 * This table is a listing of status codes that will returned to the 454c5c4113dSnw141292 * client when a SQL command fails with the corresponding error message. 455c5c4113dSnw141292 */ 456c5c4113dSnw141292 static msg_table_t sqlmsgtable[] = { 45762c60062Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 458c5c4113dSnw141292 "columns unixname, is_user, u2w_order are not unique"}, 45962c60062Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 460c5c4113dSnw141292 "columns winname, windomain, is_user, w2u_order are not unique"}, 461c5c4113dSnw141292 {-1, NULL} 462c5c4113dSnw141292 }; 463c5c4113dSnw141292 464c5c4113dSnw141292 /* 465c5c4113dSnw141292 * idmapd's version of string2stat to map SQLite messages to 466c5c4113dSnw141292 * status codes 467c5c4113dSnw141292 */ 468c5c4113dSnw141292 idmap_retcode 469c5c4113dSnw141292 idmapd_string2stat(const char *msg) { 470c5c4113dSnw141292 int i; 471c5c4113dSnw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 472c5c4113dSnw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 473c5c4113dSnw141292 return (sqlmsgtable[i].retcode); 474c5c4113dSnw141292 } 475c5c4113dSnw141292 return (IDMAP_ERR_OTHER); 476c5c4113dSnw141292 } 477c5c4113dSnw141292 478c5c4113dSnw141292 /* 479c5c4113dSnw141292 * Execute the given SQL statment without using any callbacks 480c5c4113dSnw141292 */ 481c5c4113dSnw141292 idmap_retcode 482c5c4113dSnw141292 sql_exec_no_cb(sqlite *db, char *sql) { 483c5c4113dSnw141292 char *errmsg = NULL; 48484decf41Sjp151216 int r; 485c5c4113dSnw141292 idmap_retcode retcode; 486c5c4113dSnw141292 487c5c4113dSnw141292 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 48884decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 489c5c4113dSnw141292 490c5c4113dSnw141292 if (r != SQLITE_OK) { 491c5c4113dSnw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 492c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 493c5c4113dSnw141292 retcode = idmapd_string2stat(errmsg); 49462c60062Sbaban if (errmsg != NULL) 495c5c4113dSnw141292 sqlite_freemem(errmsg); 496c5c4113dSnw141292 return (retcode); 497c5c4113dSnw141292 } 498c5c4113dSnw141292 499c5c4113dSnw141292 return (IDMAP_SUCCESS); 500c5c4113dSnw141292 } 501c5c4113dSnw141292 502c5c4113dSnw141292 /* 503c5c4113dSnw141292 * Generate expression that can be used in WHERE statements. 504c5c4113dSnw141292 * Examples: 505c5c4113dSnw141292 * <prefix> <col> <op> <value> <suffix> 506c5c4113dSnw141292 * "" "unixuser" "=" "foo" "AND" 507c5c4113dSnw141292 */ 508c5c4113dSnw141292 idmap_retcode 509c5c4113dSnw141292 gen_sql_expr_from_utf8str(const char *prefix, const char *col, 5108e228215Sdm199847 const char *op, char *value, 511c5c4113dSnw141292 const char *suffix, char **out) { 512c5c4113dSnw141292 if (out == NULL) 513c5c4113dSnw141292 return (IDMAP_ERR_ARG); 514c5c4113dSnw141292 515c5c4113dSnw141292 if (value == NULL) 516c5c4113dSnw141292 return (IDMAP_SUCCESS); 517c5c4113dSnw141292 518c5c4113dSnw141292 if (prefix == NULL) 519c5c4113dSnw141292 prefix = ""; 520c5c4113dSnw141292 if (suffix == NULL) 521c5c4113dSnw141292 suffix = ""; 522c5c4113dSnw141292 523c5c4113dSnw141292 *out = sqlite_mprintf("%s %s %s %Q %s", 5248e228215Sdm199847 prefix, col, op, value, suffix); 525c5c4113dSnw141292 if (*out == NULL) 526c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 527c5c4113dSnw141292 return (IDMAP_SUCCESS); 528c5c4113dSnw141292 } 529c5c4113dSnw141292 530c5c4113dSnw141292 /* 531c5c4113dSnw141292 * Generate and execute SQL statement for LIST RPC calls 532c5c4113dSnw141292 */ 533c5c4113dSnw141292 idmap_retcode 534c5c4113dSnw141292 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 535c5c4113dSnw141292 list_svc_cb cb, void *result) { 536c5c4113dSnw141292 list_cb_data_t cb_data; 537c5c4113dSnw141292 char *errmsg = NULL; 53884decf41Sjp151216 int r; 539c5c4113dSnw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 540c5c4113dSnw141292 541c5c4113dSnw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 542c5c4113dSnw141292 cb_data.result = result; 543c5c4113dSnw141292 cb_data.limit = limit; 544c5c4113dSnw141292 54584decf41Sjp151216 546c5c4113dSnw141292 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 54784decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 548c5c4113dSnw141292 switch (r) { 549c5c4113dSnw141292 case SQLITE_OK: 550c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 55184decf41Sjp151216 break; 55284decf41Sjp151216 553c5c4113dSnw141292 default: 554c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 555c5c4113dSnw141292 idmapdlog(LOG_ERR, 556c5c4113dSnw141292 "Database error during %s (%s)", 557c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 55884decf41Sjp151216 break; 559c5c4113dSnw141292 } 56062c60062Sbaban if (errmsg != NULL) 561c5c4113dSnw141292 sqlite_freemem(errmsg); 562c5c4113dSnw141292 return (retcode); 563c5c4113dSnw141292 } 564c5c4113dSnw141292 565c5c4113dSnw141292 /* 566c5c4113dSnw141292 * This routine is called by callbacks that process the results of 567c5c4113dSnw141292 * LIST RPC calls to validate data and to allocate memory for 568c5c4113dSnw141292 * the result array. 569c5c4113dSnw141292 */ 570c5c4113dSnw141292 idmap_retcode 571c5c4113dSnw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 572c5c4113dSnw141292 int ncol, uchar_t **list, size_t valsize) { 573c5c4113dSnw141292 size_t nsize; 574c5c4113dSnw141292 void *tmplist; 575c5c4113dSnw141292 576c5c4113dSnw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 577c5c4113dSnw141292 return (IDMAP_NEXT); 578c5c4113dSnw141292 579c5c4113dSnw141292 if (argc < ncol || argv == NULL) { 580c5c4113dSnw141292 idmapdlog(LOG_ERR, "Invalid data"); 581c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 582c5c4113dSnw141292 } 583c5c4113dSnw141292 584c5c4113dSnw141292 /* alloc in bulk to reduce number of reallocs */ 585c5c4113dSnw141292 if (cb_data->next >= cb_data->len) { 586c5c4113dSnw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 587c5c4113dSnw141292 tmplist = realloc(*list, nsize); 588c5c4113dSnw141292 if (tmplist == NULL) { 589c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 590c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 591c5c4113dSnw141292 } 592c5c4113dSnw141292 *list = tmplist; 593c5c4113dSnw141292 (void) memset(*list + (cb_data->len * valsize), 0, 594c5c4113dSnw141292 SIZE_INCR * valsize); 595c5c4113dSnw141292 cb_data->len += SIZE_INCR; 596c5c4113dSnw141292 } 597c5c4113dSnw141292 return (IDMAP_SUCCESS); 598c5c4113dSnw141292 } 599c5c4113dSnw141292 600c5c4113dSnw141292 static idmap_retcode 601c5c4113dSnw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 602c5c4113dSnw141292 int direction, int *w2u_order, int *u2w_order) { 603c5c4113dSnw141292 604c5c4113dSnw141292 *w2u_order = 0; 605c5c4113dSnw141292 *u2w_order = 0; 606c5c4113dSnw141292 607c5c4113dSnw141292 /* 608c5c4113dSnw141292 * Windows to UNIX lookup order: 609c5c4113dSnw141292 * 1. winname@domain (or winname) to "" 610c5c4113dSnw141292 * 2. winname@domain (or winname) to unixname 611c5c4113dSnw141292 * 3. winname@* to "" 612c5c4113dSnw141292 * 4. winname@* to unixname 613c5c4113dSnw141292 * 5. *@domain (or *) to * 614c5c4113dSnw141292 * 6. *@domain (or *) to "" 615c5c4113dSnw141292 * 7. *@domain (or *) to unixname 616c5c4113dSnw141292 * 8. *@* to * 617c5c4113dSnw141292 * 9. *@* to "" 618c5c4113dSnw141292 * 10. *@* to unixname 619c5c4113dSnw141292 * 620c5c4113dSnw141292 * winname is a special case of winname@domain when domain is the 621c5c4113dSnw141292 * default domain. Similarly * is a special case of *@domain when 622c5c4113dSnw141292 * domain is the default domain. 623c5c4113dSnw141292 * 624c5c4113dSnw141292 * Note that "" has priority over specific names because "" inhibits 625c5c4113dSnw141292 * mappings and traditionally deny rules always had higher priority. 626c5c4113dSnw141292 */ 627651c0131Sbaban if (direction != IDMAP_DIRECTION_U2W) { 628651c0131Sbaban /* bi-directional or from windows to unix */ 629c5c4113dSnw141292 if (winname == NULL) 630c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 631c5c4113dSnw141292 else if (unixname == NULL) 632c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 633c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 634c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 635c5c4113dSnw141292 else if (*winname == '*' && windomain && *windomain == '*') { 636c5c4113dSnw141292 if (*unixname == '*') 637c5c4113dSnw141292 *w2u_order = 8; 638c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 639c5c4113dSnw141292 *w2u_order = 9; 640c5c4113dSnw141292 else /* unixname == name */ 641c5c4113dSnw141292 *w2u_order = 10; 642c5c4113dSnw141292 } else if (*winname == '*') { 643c5c4113dSnw141292 if (*unixname == '*') 644c5c4113dSnw141292 *w2u_order = 5; 645c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 646c5c4113dSnw141292 *w2u_order = 6; 647c5c4113dSnw141292 else /* name */ 648c5c4113dSnw141292 *w2u_order = 7; 64962c60062Sbaban } else if (windomain != NULL && *windomain == '*') { 650c5c4113dSnw141292 /* winname == name */ 651c5c4113dSnw141292 if (*unixname == '*') 652c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 653c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 654c5c4113dSnw141292 *w2u_order = 3; 655c5c4113dSnw141292 else /* name */ 656c5c4113dSnw141292 *w2u_order = 4; 657c5c4113dSnw141292 } else { 658c5c4113dSnw141292 /* winname == name && windomain == null or name */ 659c5c4113dSnw141292 if (*unixname == '*') 660c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 661c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 662c5c4113dSnw141292 *w2u_order = 1; 663c5c4113dSnw141292 else /* name */ 664c5c4113dSnw141292 *w2u_order = 2; 665c5c4113dSnw141292 } 666c5c4113dSnw141292 } 667c5c4113dSnw141292 668c5c4113dSnw141292 /* 669c5c4113dSnw141292 * 1. unixname to "" 670c5c4113dSnw141292 * 2. unixname to winname@domain (or winname) 671c5c4113dSnw141292 * 3. * to *@domain (or *) 672c5c4113dSnw141292 * 4. * to "" 673c5c4113dSnw141292 * 5. * to winname@domain (or winname) 674c5c4113dSnw141292 */ 675651c0131Sbaban if (direction != IDMAP_DIRECTION_W2U) { 676651c0131Sbaban /* bi-directional or from unix to windows */ 677c5c4113dSnw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 678c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 679c5c4113dSnw141292 else if (winname == NULL) 680c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 68162c60062Sbaban else if (windomain != NULL && *windomain == '*') 682651c0131Sbaban return (IDMAP_ERR_U2W_NAMERULE); 683c5c4113dSnw141292 else if (*unixname == '*') { 684c5c4113dSnw141292 if (*winname == '*') 685c5c4113dSnw141292 *u2w_order = 3; 686c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 687c5c4113dSnw141292 *u2w_order = 4; 688c5c4113dSnw141292 else 689c5c4113dSnw141292 *u2w_order = 5; 690c5c4113dSnw141292 } else { 691c5c4113dSnw141292 if (*winname == '*') 692c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 693c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 694c5c4113dSnw141292 *u2w_order = 1; 695c5c4113dSnw141292 else 696c5c4113dSnw141292 *u2w_order = 2; 697c5c4113dSnw141292 } 698c5c4113dSnw141292 } 699c5c4113dSnw141292 return (IDMAP_SUCCESS); 700c5c4113dSnw141292 } 701c5c4113dSnw141292 702c5c4113dSnw141292 /* 703c5c4113dSnw141292 * Generate and execute SQL statement to add name-based mapping rule 704c5c4113dSnw141292 */ 705c5c4113dSnw141292 idmap_retcode 706c5c4113dSnw141292 add_namerule(sqlite *db, idmap_namerule *rule) { 707c5c4113dSnw141292 char *sql = NULL; 708c5c4113dSnw141292 idmap_stat retcode; 7098e228215Sdm199847 char *dom = NULL; 710c5c4113dSnw141292 int w2u_order, u2w_order; 711c5c4113dSnw141292 char w2ubuf[11], u2wbuf[11]; 712c5c4113dSnw141292 7138e228215Sdm199847 retcode = get_namerule_order(rule->winname, rule->windomain, 7148e228215Sdm199847 rule->unixname, rule->direction, &w2u_order, &u2w_order); 715c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 716c5c4113dSnw141292 goto out; 717c5c4113dSnw141292 718c5c4113dSnw141292 if (w2u_order) 719c5c4113dSnw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 720c5c4113dSnw141292 if (u2w_order) 721c5c4113dSnw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 722c5c4113dSnw141292 72362c60062Sbaban /* 72462c60062Sbaban * For the triggers on namerules table to work correctly: 72562c60062Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 72662c60062Sbaban * 2) Use "" instead of NULL for "no domain" 72762c60062Sbaban */ 72862c60062Sbaban 7298e228215Sdm199847 if (rule->windomain != NULL) 7308e228215Sdm199847 dom = rule->windomain; 7318e228215Sdm199847 else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL) 73262c60062Sbaban == IDMAP_SUCCESS) { 73362c60062Sbaban /* well-known SIDs don't need domain */ 73462c60062Sbaban dom = ""; 73562c60062Sbaban } 736c5c4113dSnw141292 737c5c4113dSnw141292 RDLOCK_CONFIG(); 73862c60062Sbaban if (dom == NULL) { 739*c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain) 740*c8e26105Sjp151216 dom = _idmapdstate.cfg->pgcfg.default_domain; 741c5c4113dSnw141292 else 742c5c4113dSnw141292 dom = ""; 74362c60062Sbaban } 74484decf41Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 745c5c4113dSnw141292 "(is_user, windomain, winname, is_nt4, " 746c5c4113dSnw141292 "unixname, w2u_order, u2w_order) " 747c5c4113dSnw141292 "VALUES(%d, %Q, %Q, %d, %Q, %q, %q);", 748c5c4113dSnw141292 rule->is_user?1:0, 749c5c4113dSnw141292 dom, 7508e228215Sdm199847 rule->winname, rule->is_nt4?1:0, 7518e228215Sdm199847 rule->unixname, 752c5c4113dSnw141292 w2u_order?w2ubuf:NULL, 753c5c4113dSnw141292 u2w_order?u2wbuf:NULL); 754c5c4113dSnw141292 UNLOCK_CONFIG(); 755c5c4113dSnw141292 756c5c4113dSnw141292 if (sql == NULL) { 757c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 758c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 759c5c4113dSnw141292 goto out; 760c5c4113dSnw141292 } 761c5c4113dSnw141292 762c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 763c5c4113dSnw141292 764c5c4113dSnw141292 if (retcode == IDMAP_ERR_OTHER) 765c5c4113dSnw141292 retcode = IDMAP_ERR_CFG; 766c5c4113dSnw141292 767c5c4113dSnw141292 out: 76862c60062Sbaban if (sql != NULL) 769c5c4113dSnw141292 sqlite_freemem(sql); 770c5c4113dSnw141292 return (retcode); 771c5c4113dSnw141292 } 772c5c4113dSnw141292 773c5c4113dSnw141292 /* 774c5c4113dSnw141292 * Flush name-based mapping rules 775c5c4113dSnw141292 */ 776c5c4113dSnw141292 idmap_retcode 777c5c4113dSnw141292 flush_namerules(sqlite *db, bool_t is_user) { 778c5c4113dSnw141292 char *sql = NULL; 779c5c4113dSnw141292 idmap_stat retcode; 780c5c4113dSnw141292 781c5c4113dSnw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 782c5c4113dSnw141292 "is_user = %d;", is_user?1:0); 783c5c4113dSnw141292 784c5c4113dSnw141292 if (sql == NULL) { 785c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 786c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 787c5c4113dSnw141292 } 788c5c4113dSnw141292 789c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 790c5c4113dSnw141292 791c5c4113dSnw141292 sqlite_freemem(sql); 792c5c4113dSnw141292 return (retcode); 793c5c4113dSnw141292 } 794c5c4113dSnw141292 795c5c4113dSnw141292 /* 796c5c4113dSnw141292 * Generate and execute SQL statement to remove a name-based mapping rule 797c5c4113dSnw141292 */ 798c5c4113dSnw141292 idmap_retcode 799c5c4113dSnw141292 rm_namerule(sqlite *db, idmap_namerule *rule) { 800c5c4113dSnw141292 char *sql = NULL; 801c5c4113dSnw141292 idmap_stat retcode; 802c5c4113dSnw141292 char *s_windomain = NULL, *s_winname = NULL; 803c5c4113dSnw141292 char *s_unixname = NULL; 804c5c4113dSnw141292 char buf[80]; 805c5c4113dSnw141292 8068e228215Sdm199847 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 8078e228215Sdm199847 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 808c5c4113dSnw141292 return (IDMAP_SUCCESS); 809c5c4113dSnw141292 810c5c4113dSnw141292 if (rule->direction < 0) { 811c5c4113dSnw141292 buf[0] = 0; 812651c0131Sbaban } else if (rule->direction == IDMAP_DIRECTION_BI) { 813c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 814c5c4113dSnw141292 " AND u2w_order > 0"); 815651c0131Sbaban } else if (rule->direction == IDMAP_DIRECTION_W2U) { 816c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 817c5c4113dSnw141292 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 818651c0131Sbaban } else if (rule->direction == IDMAP_DIRECTION_U2W) { 819c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 820c5c4113dSnw141292 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 821c5c4113dSnw141292 } 822c5c4113dSnw141292 823c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 8248e228215Sdm199847 if (!EMPTY_STRING(rule->windomain)) { 825c5c4113dSnw141292 if (gen_sql_expr_from_utf8str("AND", "windomain", "=", 8268e228215Sdm199847 rule->windomain, "", &s_windomain) != IDMAP_SUCCESS) 827c5c4113dSnw141292 goto out; 828c5c4113dSnw141292 } 829c5c4113dSnw141292 8308e228215Sdm199847 if (!EMPTY_STRING(rule->winname)) { 831c5c4113dSnw141292 if (gen_sql_expr_from_utf8str("AND", "winname", "=", 8328e228215Sdm199847 rule->winname, "", &s_winname) != IDMAP_SUCCESS) 833c5c4113dSnw141292 goto out; 834c5c4113dSnw141292 } 835c5c4113dSnw141292 8368e228215Sdm199847 if (!EMPTY_STRING(rule->unixname)) { 837c5c4113dSnw141292 if (gen_sql_expr_from_utf8str("AND", "unixname", "=", 8388e228215Sdm199847 rule->unixname, "", &s_unixname) != IDMAP_SUCCESS) 839c5c4113dSnw141292 goto out; 840c5c4113dSnw141292 } 841c5c4113dSnw141292 842c5c4113dSnw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 843c5c4113dSnw141292 "is_user = %d %s %s %s %s;", 844c5c4113dSnw141292 rule->is_user?1:0, 845c5c4113dSnw141292 s_windomain?s_windomain:"", 846c5c4113dSnw141292 s_winname?s_winname:"", 847c5c4113dSnw141292 s_unixname?s_unixname:"", 848c5c4113dSnw141292 buf); 849c5c4113dSnw141292 850c5c4113dSnw141292 if (sql == NULL) { 851c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 852c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 853c5c4113dSnw141292 goto out; 854c5c4113dSnw141292 } 855c5c4113dSnw141292 856c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 857c5c4113dSnw141292 858c5c4113dSnw141292 out: 85962c60062Sbaban if (s_windomain != NULL) 860c5c4113dSnw141292 sqlite_freemem(s_windomain); 86162c60062Sbaban if (s_winname != NULL) 862c5c4113dSnw141292 sqlite_freemem(s_winname); 86362c60062Sbaban if (s_unixname != NULL) 864c5c4113dSnw141292 sqlite_freemem(s_unixname); 86562c60062Sbaban if (sql != NULL) 866c5c4113dSnw141292 sqlite_freemem(sql); 867c5c4113dSnw141292 return (retcode); 868c5c4113dSnw141292 } 869c5c4113dSnw141292 870c5c4113dSnw141292 /* 871c5c4113dSnw141292 * Compile the given SQL query and step just once. 872c5c4113dSnw141292 * 873c5c4113dSnw141292 * Input: 874c5c4113dSnw141292 * db - db handle 875c5c4113dSnw141292 * sql - SQL statement 876c5c4113dSnw141292 * 877c5c4113dSnw141292 * Output: 878c5c4113dSnw141292 * vm - virtual SQL machine 879c5c4113dSnw141292 * ncol - number of columns in the result 880c5c4113dSnw141292 * values - column values 881c5c4113dSnw141292 * 882c5c4113dSnw141292 * Return values: 883c5c4113dSnw141292 * IDMAP_SUCCESS 884c5c4113dSnw141292 * IDMAP_ERR_NOTFOUND 885c5c4113dSnw141292 * IDMAP_ERR_INTERNAL 886c5c4113dSnw141292 */ 887c5c4113dSnw141292 888c5c4113dSnw141292 static idmap_retcode 889c5c4113dSnw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 890c5c4113dSnw141292 int reqcol, const char ***values) { 891c5c4113dSnw141292 char *errmsg = NULL; 89284decf41Sjp151216 int r; 893c5c4113dSnw141292 89484decf41Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 895c5c4113dSnw141292 idmapdlog(LOG_ERR, 896c5c4113dSnw141292 "Database error during %s (%s)", 897c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 898c5c4113dSnw141292 sqlite_freemem(errmsg); 899c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 900c5c4113dSnw141292 } 901c5c4113dSnw141292 902c5c4113dSnw141292 r = sqlite_step(*vm, ncol, values, NULL); 90384decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 904c5c4113dSnw141292 90584decf41Sjp151216 if (r == SQLITE_ROW) { 90662c60062Sbaban if (ncol != NULL && *ncol < reqcol) { 907c5c4113dSnw141292 (void) sqlite_finalize(*vm, NULL); 908c5c4113dSnw141292 *vm = NULL; 909c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 910c5c4113dSnw141292 } 911c5c4113dSnw141292 /* Caller will call finalize after using the results */ 912c5c4113dSnw141292 return (IDMAP_SUCCESS); 913c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 914c5c4113dSnw141292 (void) sqlite_finalize(*vm, NULL); 915c5c4113dSnw141292 *vm = NULL; 916c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 917c5c4113dSnw141292 } 918c5c4113dSnw141292 919c5c4113dSnw141292 (void) sqlite_finalize(*vm, &errmsg); 920c5c4113dSnw141292 *vm = NULL; 921c5c4113dSnw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 922c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 923c5c4113dSnw141292 sqlite_freemem(errmsg); 924c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 925c5c4113dSnw141292 } 926c5c4113dSnw141292 92762c60062Sbaban /* 92862c60062Sbaban * Table for well-known SIDs. 92962c60062Sbaban * 93062c60062Sbaban * Background: 93162c60062Sbaban * 93276b27f93Sbaban * Some of the well-known principals are stored under: 93362c60062Sbaban * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 93462c60062Sbaban * They belong to objectClass "foreignSecurityPrincipal". They don't have 93562c60062Sbaban * "samAccountName" nor "userPrincipalName" attributes. Their names are 93662c60062Sbaban * available in "cn" and "name" attributes. Some of these principals have a 93762c60062Sbaban * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 93862c60062Sbaban * these duplicate entries have the stringified SID in the "name" and "cn" 93962c60062Sbaban * attributes instead of the actual name. 94062c60062Sbaban * 94176b27f93Sbaban * Those of the form S-1-5-32-X are Builtin groups and are stored in the 94276b27f93Sbaban * cn=builtin container (except, Power Users which is not stored in AD) 94362c60062Sbaban * 94476b27f93Sbaban * These principals are and will remain constant. Therefore doing AD lookups 94576b27f93Sbaban * provides no benefit. Also, using hard-coded table (and thus avoiding AD 94676b27f93Sbaban * lookup) improves performance and avoids additional complexity in the 94776b27f93Sbaban * adutils.c code. Moreover these SIDs can be used when no Active Directory 94876b27f93Sbaban * is available (such as the CIFS server's "workgroup" mode). 94976b27f93Sbaban * 95076b27f93Sbaban * Notes: 95176b27f93Sbaban * 1. Currently we don't support localization of well-known SID names, 95262c60062Sbaban * unlike Windows. 95362c60062Sbaban * 95476b27f93Sbaban * 2. Other well-known SIDs i.e. S-1-5-<domain>-<w-k RID> are not stored 95576b27f93Sbaban * here. AD does have normal user/group objects for these objects and 95676b27f93Sbaban * can be looked up using the existing AD lookup code. 95762c60062Sbaban */ 95862c60062Sbaban static wksids_table_t wksids[] = { 95962c60062Sbaban {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 96062c60062Sbaban {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 96162c60062Sbaban {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 96262c60062Sbaban {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 96362c60062Sbaban {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 96476b27f93Sbaban {"S-1-3", 4, "Owner Rights", 0, SENTINEL_PID, -1}, 96562c60062Sbaban {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 96662c60062Sbaban {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 96762c60062Sbaban {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 96862c60062Sbaban {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 96962c60062Sbaban {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 97062c60062Sbaban {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 97162c60062Sbaban {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 97262c60062Sbaban {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 97362c60062Sbaban {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 97462c60062Sbaban {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 97562c60062Sbaban {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 97662c60062Sbaban {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 97762c60062Sbaban {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 97862c60062Sbaban {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 97976b27f93Sbaban {"S-1-5", 17, "IUSR", 0, SENTINEL_PID, -1}, 98062c60062Sbaban {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 98162c60062Sbaban {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 98262c60062Sbaban {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 98362c60062Sbaban {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 98476b27f93Sbaban {"S-1-5-32", 544, "Administrators", 0, SENTINEL_PID, -1}, 98576b27f93Sbaban {"S-1-5-32", 545, "Users", 0, SENTINEL_PID, -1}, 98676b27f93Sbaban {"S-1-5-32", 546, "Guests", 0, SENTINEL_PID, -1}, 98776b27f93Sbaban {"S-1-5-32", 547, "Power Users", 0, SENTINEL_PID, -1}, 98876b27f93Sbaban {"S-1-5-32", 548, "Account Operators", 0, SENTINEL_PID, -1}, 98976b27f93Sbaban {"S-1-5-32", 549, "Server Operators", 0, SENTINEL_PID, -1}, 99076b27f93Sbaban {"S-1-5-32", 550, "Print Operators", 0, SENTINEL_PID, -1}, 99176b27f93Sbaban {"S-1-5-32", 551, "Backup Operators", 0, SENTINEL_PID, -1}, 99276b27f93Sbaban {"S-1-5-32", 552, "Replicator", 0, SENTINEL_PID, -1}, 99376b27f93Sbaban {"S-1-5-32", 554, "Pre-Windows 2000 Compatible Access", 0, 99476b27f93Sbaban SENTINEL_PID, -1}, 99576b27f93Sbaban {"S-1-5-32", 555, "Remote Desktop Users", 0, SENTINEL_PID, -1}, 99676b27f93Sbaban {"S-1-5-32", 556, "Network Configuration Operators", 0, 99776b27f93Sbaban SENTINEL_PID, -1}, 99876b27f93Sbaban {"S-1-5-32", 557, "Incoming Forest Trust Builders", 0, 99976b27f93Sbaban SENTINEL_PID, -1}, 100076b27f93Sbaban {"S-1-5-32", 558, "Performance Monitor Users", 0, SENTINEL_PID, -1}, 100176b27f93Sbaban {"S-1-5-32", 559, "Performance Log Users", 0, SENTINEL_PID, -1}, 100276b27f93Sbaban {"S-1-5-32", 560, "Windows Authorization Access Group", 0, 100376b27f93Sbaban SENTINEL_PID, -1}, 100476b27f93Sbaban {"S-1-5-32", 561, "Terminal Server License Servers", 0, 100576b27f93Sbaban SENTINEL_PID, -1}, 100676b27f93Sbaban {"S-1-5-32", 561, "Distributed COM Users", 0, SENTINEL_PID, -1}, 100776b27f93Sbaban {"S-1-5-32", 568, "IIS_IUSRS", 0, SENTINEL_PID, -1}, 100876b27f93Sbaban {"S-1-5-32", 569, "Cryptograhic Operators", 0, SENTINEL_PID, -1}, 100976b27f93Sbaban {"S-1-5-32", 573, "Event Log Readers", 0, SENTINEL_PID, -1}, 101076b27f93Sbaban {"S-1-5-32", 574, "Certificate Service DCOM Access", 0, 101176b27f93Sbaban SENTINEL_PID, -1}, 101262c60062Sbaban {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 101362c60062Sbaban {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 101462c60062Sbaban {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 101562c60062Sbaban {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 1016c5c4113dSnw141292 }; 1017c5c4113dSnw141292 1018c5c4113dSnw141292 static idmap_retcode 1019c5c4113dSnw141292 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) { 1020c5c4113dSnw141292 int i; 102162c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 102262c60062Sbaban if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 102362c60062Sbaban (strcasecmp(wksids[i].sidprefix, 102462c60062Sbaban req->id1.idmap_id_u.sid.prefix) == 0)) { 102562c60062Sbaban 102662c60062Sbaban if (wksids[i].pid == SENTINEL_PID) 102762c60062Sbaban /* Not mapped, break */ 102862c60062Sbaban break; 102962c60062Sbaban else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 103062c60062Sbaban continue; 103162c60062Sbaban 1032c5c4113dSnw141292 switch (req->id2.idtype) { 1033c5c4113dSnw141292 case IDMAP_UID: 103462c60062Sbaban if (wksids[i].is_user == 0) 103562c60062Sbaban continue; 103662c60062Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 103762c60062Sbaban res->direction = wksids[i].direction; 1038c5c4113dSnw141292 return (IDMAP_SUCCESS); 1039c5c4113dSnw141292 case IDMAP_GID: 104062c60062Sbaban if (wksids[i].is_user == 1) 104162c60062Sbaban continue; 104262c60062Sbaban res->id.idmap_id_u.gid = wksids[i].pid; 104362c60062Sbaban res->direction = wksids[i].direction; 1044c5c4113dSnw141292 return (IDMAP_SUCCESS); 1045c5c4113dSnw141292 case IDMAP_POSIXID: 104662c60062Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 104762c60062Sbaban res->id.idtype = (!wksids[i].is_user)? 1048c5c4113dSnw141292 IDMAP_GID:IDMAP_UID; 104962c60062Sbaban res->direction = wksids[i].direction; 1050c5c4113dSnw141292 return (IDMAP_SUCCESS); 1051c5c4113dSnw141292 default: 1052c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1053c5c4113dSnw141292 } 1054c5c4113dSnw141292 } 1055c5c4113dSnw141292 } 1056c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1057c5c4113dSnw141292 } 1058c5c4113dSnw141292 1059c5c4113dSnw141292 static idmap_retcode 1060c5c4113dSnw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) { 1061c5c4113dSnw141292 int i; 106262c60062Sbaban if (req->id2.idtype != IDMAP_SID) 106362c60062Sbaban return (IDMAP_ERR_NOTSUPPORTED); 106462c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 106562c60062Sbaban if (wksids[i].pid == req->id1.idmap_id_u.uid && 106662c60062Sbaban wksids[i].is_user == is_user && 106762c60062Sbaban wksids[i].direction != IDMAP_DIRECTION_W2U) { 106862c60062Sbaban res->id.idmap_id_u.sid.rid = wksids[i].rid; 1069c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = 107062c60062Sbaban strdup(wksids[i].sidprefix); 1071c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 1072c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1073c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 1074c5c4113dSnw141292 } 107562c60062Sbaban res->direction = wksids[i].direction; 1076c5c4113dSnw141292 return (IDMAP_SUCCESS); 1077c5c4113dSnw141292 } 1078c5c4113dSnw141292 } 107962c60062Sbaban return (IDMAP_ERR_NOTFOUND); 108062c60062Sbaban } 108162c60062Sbaban 108262c60062Sbaban static idmap_retcode 108362c60062Sbaban lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 108462c60062Sbaban int *type) { 108562c60062Sbaban int i; 108662c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 108762c60062Sbaban if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 108862c60062Sbaban wksids[i].rid == rid) { 108962c60062Sbaban if ((*name = strdup(wksids[i].winname)) == NULL) { 109062c60062Sbaban idmapdlog(LOG_ERR, "Out of memory"); 109162c60062Sbaban return (IDMAP_ERR_MEMORY); 109262c60062Sbaban } 109362c60062Sbaban *type = (wksids[i].is_user)? 109462c60062Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 109562c60062Sbaban return (IDMAP_SUCCESS); 109662c60062Sbaban } 109762c60062Sbaban } 109862c60062Sbaban return (IDMAP_ERR_NOTFOUND); 109962c60062Sbaban } 110062c60062Sbaban 110162c60062Sbaban static idmap_retcode 110262c60062Sbaban lookup_wksids_name2sid(const char *name, char **sidprefix, idmap_rid_t *rid, 110362c60062Sbaban int *type) { 110462c60062Sbaban int i; 110562c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 110662c60062Sbaban if (strcasecmp(wksids[i].winname, name) == 0) { 110762c60062Sbaban if (sidprefix != NULL && (*sidprefix = 110862c60062Sbaban strdup(wksids[i].sidprefix)) == NULL) { 110962c60062Sbaban idmapdlog(LOG_ERR, "Out of memory"); 111062c60062Sbaban return (IDMAP_ERR_MEMORY); 111162c60062Sbaban } 111262c60062Sbaban if (type != NULL) 111362c60062Sbaban *type = (wksids[i].is_user)? 111462c60062Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 111562c60062Sbaban if (rid != NULL) 111662c60062Sbaban *rid = wksids[i].rid; 111762c60062Sbaban return (IDMAP_SUCCESS); 111862c60062Sbaban } 1119c5c4113dSnw141292 } 1120c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1121c5c4113dSnw141292 } 1122c5c4113dSnw141292 1123c5c4113dSnw141292 static idmap_retcode 1124c5c4113dSnw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 1125c5c4113dSnw141292 char *end; 1126c5c4113dSnw141292 char *sql = NULL; 1127c5c4113dSnw141292 const char **values; 1128c5c4113dSnw141292 sqlite_vm *vm = NULL; 1129c5c4113dSnw141292 int ncol, is_user; 1130c5c4113dSnw141292 uid_t pid; 1131c5c4113dSnw141292 time_t curtime, exp; 1132c5c4113dSnw141292 idmap_retcode retcode; 1133c5c4113dSnw141292 1134c5c4113dSnw141292 /* Current time */ 1135c5c4113dSnw141292 errno = 0; 1136c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 1137c5c4113dSnw141292 idmapdlog(LOG_ERR, 1138c5c4113dSnw141292 "Failed to get current time (%s)", 1139c5c4113dSnw141292 strerror(errno)); 1140c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1141c5c4113dSnw141292 goto out; 1142c5c4113dSnw141292 } 1143c5c4113dSnw141292 1144c5c4113dSnw141292 /* SQL to lookup the cache */ 1145c5c4113dSnw141292 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 1146c5c4113dSnw141292 "FROM idmap_cache WHERE " 1147c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 1148c5c4113dSnw141292 "(pid >= 2147483648 OR " 1149c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 1150c5c4113dSnw141292 "expiration > %d));", 1151c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 1152c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 1153c5c4113dSnw141292 curtime); 1154c5c4113dSnw141292 if (sql == NULL) { 1155c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1156c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1157c5c4113dSnw141292 goto out; 1158c5c4113dSnw141292 } 1159c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 1160c5c4113dSnw141292 sqlite_freemem(sql); 1161c5c4113dSnw141292 1162c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 1163c5c4113dSnw141292 goto out; 1164c5c4113dSnw141292 } else if (retcode == IDMAP_SUCCESS) { 1165c5c4113dSnw141292 /* sanity checks */ 1166c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 1167c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 1168c5c4113dSnw141292 goto out; 1169c5c4113dSnw141292 } 1170c5c4113dSnw141292 1171c5c4113dSnw141292 pid = strtoul(values[0], &end, 10); 1172c5c4113dSnw141292 is_user = strncmp(values[1], "0", 2)?1:0; 1173c5c4113dSnw141292 1174c5c4113dSnw141292 /* 1175c5c4113dSnw141292 * We may have an expired ephemeral mapping. Consider 1176c5c4113dSnw141292 * the expired entry as valid if we are not going to 1177c5c4113dSnw141292 * perform name-based mapping. But do not renew the 1178c5c4113dSnw141292 * expiration. 1179c5c4113dSnw141292 * If we will be doing name-based mapping then store the 1180c5c4113dSnw141292 * ephemeral pid in the result so that we can use it 1181c5c4113dSnw141292 * if we end up doing dynamic mapping again. 1182c5c4113dSnw141292 */ 1183c5c4113dSnw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 1184c5c4113dSnw141292 !AVOID_NAMESERVICE(req)) { 118562c60062Sbaban if (IS_EPHEMERAL(pid) && values[2] != NULL) { 1186c5c4113dSnw141292 exp = strtoll(values[2], &end, 10); 1187c5c4113dSnw141292 if (exp && exp <= curtime) { 1188c5c4113dSnw141292 /* Store the ephemeral pid */ 1189c5c4113dSnw141292 res->id.idmap_id_u.uid = pid; 1190c5c4113dSnw141292 res->id.idtype = is_user? 1191c5c4113dSnw141292 IDMAP_UID:IDMAP_GID; 1192651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 1193c5c4113dSnw141292 req->direction |= is_user? 1194c5c4113dSnw141292 _IDMAP_F_EXP_EPH_UID: 1195c5c4113dSnw141292 _IDMAP_F_EXP_EPH_GID; 1196c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 1197c5c4113dSnw141292 goto out; 1198c5c4113dSnw141292 } 1199c5c4113dSnw141292 } 1200c5c4113dSnw141292 } 1201c5c4113dSnw141292 1202c5c4113dSnw141292 switch (req->id2.idtype) { 1203c5c4113dSnw141292 case IDMAP_UID: 1204c5c4113dSnw141292 if (!is_user) 1205c5c4113dSnw141292 retcode = IDMAP_ERR_NOTUSER; 1206c5c4113dSnw141292 else 1207c5c4113dSnw141292 res->id.idmap_id_u.uid = pid; 1208c5c4113dSnw141292 break; 1209c5c4113dSnw141292 case IDMAP_GID: 1210c5c4113dSnw141292 if (is_user) 1211c5c4113dSnw141292 retcode = IDMAP_ERR_NOTGROUP; 1212c5c4113dSnw141292 else 1213c5c4113dSnw141292 res->id.idmap_id_u.gid = pid; 1214c5c4113dSnw141292 break; 1215c5c4113dSnw141292 case IDMAP_POSIXID: 1216c5c4113dSnw141292 res->id.idmap_id_u.uid = pid; 1217c5c4113dSnw141292 res->id.idtype = (is_user)?IDMAP_UID:IDMAP_GID; 1218c5c4113dSnw141292 break; 1219c5c4113dSnw141292 default: 1220c5c4113dSnw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 1221c5c4113dSnw141292 break; 1222c5c4113dSnw141292 } 1223c5c4113dSnw141292 } 1224c5c4113dSnw141292 1225c5c4113dSnw141292 out: 1226c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 122762c60062Sbaban if (values[4] != NULL) 1228c5c4113dSnw141292 res->direction = 1229651c0131Sbaban (strtol(values[4], &end, 10) == 0)? 1230651c0131Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 1231c5c4113dSnw141292 else 1232651c0131Sbaban res->direction = IDMAP_DIRECTION_W2U; 1233c5c4113dSnw141292 123462c60062Sbaban if (values[3] != NULL) { 12358e228215Sdm199847 req->id2name = strdup(values[3]); 12368e228215Sdm199847 if (req->id2name == NULL) { 1237c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1238c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1239c5c4113dSnw141292 } 1240c5c4113dSnw141292 } 1241c5c4113dSnw141292 } 124262c60062Sbaban if (vm != NULL) 1243c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1244c5c4113dSnw141292 return (retcode); 1245c5c4113dSnw141292 } 1246c5c4113dSnw141292 1247c5c4113dSnw141292 static idmap_retcode 124862c60062Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 1249c5c4113dSnw141292 char **name, char **domain, int *type) { 1250c5c4113dSnw141292 char *end; 1251c5c4113dSnw141292 char *sql = NULL; 1252c5c4113dSnw141292 const char **values; 1253c5c4113dSnw141292 sqlite_vm *vm = NULL; 1254c5c4113dSnw141292 int ncol; 1255c5c4113dSnw141292 time_t curtime; 1256c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 1257c5c4113dSnw141292 1258c5c4113dSnw141292 /* Get current time */ 1259c5c4113dSnw141292 errno = 0; 1260c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 1261c5c4113dSnw141292 idmapdlog(LOG_ERR, 1262c5c4113dSnw141292 "Failed to get current time (%s)", 1263c5c4113dSnw141292 strerror(errno)); 1264c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1265c5c4113dSnw141292 goto out; 1266c5c4113dSnw141292 } 1267c5c4113dSnw141292 1268c5c4113dSnw141292 /* SQL to lookup the cache */ 1269c5c4113dSnw141292 sql = sqlite_mprintf("SELECT name, domain, type FROM name_cache WHERE " 1270c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND " 1271c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 1272c5c4113dSnw141292 "expiration > %d);", 1273c5c4113dSnw141292 sidprefix, rid, curtime); 1274c5c4113dSnw141292 if (sql == NULL) { 1275c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1276c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1277c5c4113dSnw141292 goto out; 1278c5c4113dSnw141292 } 1279c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 1280c5c4113dSnw141292 sqlite_freemem(sql); 1281c5c4113dSnw141292 1282c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 128362c60062Sbaban if (type != NULL) { 1284c5c4113dSnw141292 if (values[2] == NULL) { 1285c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 1286c5c4113dSnw141292 goto out; 1287c5c4113dSnw141292 } 1288c5c4113dSnw141292 *type = strtol(values[2], &end, 10); 1289c5c4113dSnw141292 } 1290c5c4113dSnw141292 129162c60062Sbaban if (name != NULL && values[0] != NULL) { 1292c5c4113dSnw141292 if ((*name = strdup(values[0])) == NULL) { 1293c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1294c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1295c5c4113dSnw141292 goto out; 1296c5c4113dSnw141292 } 1297c5c4113dSnw141292 } 1298c5c4113dSnw141292 129962c60062Sbaban if (domain != NULL && values[1] != NULL) { 1300c5c4113dSnw141292 if ((*domain = strdup(values[1])) == NULL) { 130162c60062Sbaban if (name != NULL && *name) { 1302c5c4113dSnw141292 free(*name); 1303c5c4113dSnw141292 *name = NULL; 1304c5c4113dSnw141292 } 1305c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1306c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1307c5c4113dSnw141292 goto out; 1308c5c4113dSnw141292 } 1309c5c4113dSnw141292 } 1310c5c4113dSnw141292 } 1311c5c4113dSnw141292 1312c5c4113dSnw141292 out: 131362c60062Sbaban if (vm != NULL) 1314c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1315c5c4113dSnw141292 return (retcode); 1316c5c4113dSnw141292 } 1317c5c4113dSnw141292 1318c5c4113dSnw141292 static idmap_retcode 1319c5c4113dSnw141292 verify_type(idmap_id_type idtype, int type, idmap_id_res *res) { 1320c5c4113dSnw141292 switch (idtype) { 1321c5c4113dSnw141292 case IDMAP_UID: 1322c5c4113dSnw141292 if (type != _IDMAP_T_USER) 1323c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 1324c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1325c5c4113dSnw141292 break; 1326c5c4113dSnw141292 case IDMAP_GID: 1327c5c4113dSnw141292 if (type != _IDMAP_T_GROUP) 1328c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 1329c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1330c5c4113dSnw141292 break; 1331c5c4113dSnw141292 case IDMAP_POSIXID: 1332c5c4113dSnw141292 if (type == _IDMAP_T_USER) 1333c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1334c5c4113dSnw141292 else if (type == _IDMAP_T_GROUP) 1335c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1336c5c4113dSnw141292 else 1337c5c4113dSnw141292 return (IDMAP_ERR_SID); 1338c5c4113dSnw141292 break; 1339c5c4113dSnw141292 default: 1340c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1341c5c4113dSnw141292 } 1342c5c4113dSnw141292 return (IDMAP_SUCCESS); 1343c5c4113dSnw141292 } 1344c5c4113dSnw141292 1345c5c4113dSnw141292 /* 134662c60062Sbaban * Lookup sid to name locally 1347c5c4113dSnw141292 */ 1348c5c4113dSnw141292 static idmap_retcode 134962c60062Sbaban lookup_local_sid2name(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 1350c5c4113dSnw141292 int type = -1; 1351c5c4113dSnw141292 idmap_retcode retcode; 1352c5c4113dSnw141292 char *sidprefix; 1353c5c4113dSnw141292 idmap_rid_t rid; 1354c5c4113dSnw141292 char *name = NULL, *domain = NULL; 1355c5c4113dSnw141292 1356c5c4113dSnw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 1357c5c4113dSnw141292 rid = req->id1.idmap_id_u.sid.rid; 1358c5c4113dSnw141292 135962c60062Sbaban /* Lookup sids to name in well-known sids table */ 136062c60062Sbaban retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 136162c60062Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 136262c60062Sbaban goto out; 136362c60062Sbaban 1364c5c4113dSnw141292 /* Lookup sid to name in cache */ 136562c60062Sbaban retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 1366c5c4113dSnw141292 &domain, &type); 1367c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 1368c5c4113dSnw141292 goto out; 1369c5c4113dSnw141292 137062c60062Sbaban out: 137162c60062Sbaban if (retcode == IDMAP_SUCCESS) { 1372c5c4113dSnw141292 /* Verify that the sid type matches the request */ 1373c5c4113dSnw141292 retcode = verify_type(req->id2.idtype, type, res); 1374c5c4113dSnw141292 1375c5c4113dSnw141292 /* update state in 'req' */ 13768e228215Sdm199847 if (name != NULL) 13778e228215Sdm199847 req->id1name = name; 13788e228215Sdm199847 if (domain != NULL) 13798e228215Sdm199847 req->id1domain = domain; 1380c5c4113dSnw141292 } else { 138162c60062Sbaban if (name != NULL) 1382c5c4113dSnw141292 free(name); 138362c60062Sbaban if (domain != NULL) 1384c5c4113dSnw141292 free(domain); 1385c5c4113dSnw141292 } 1386c5c4113dSnw141292 return (retcode); 1387c5c4113dSnw141292 } 1388c5c4113dSnw141292 1389c5c4113dSnw141292 idmap_retcode 1390c5c4113dSnw141292 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 1391c5c4113dSnw141292 idmap_ids_res *result) { 1392c5c4113dSnw141292 idmap_retcode retcode; 1393c5c4113dSnw141292 int ret, i; 1394c5c4113dSnw141292 int retries = 0; 1395c5c4113dSnw141292 idmap_mapping *req; 1396c5c4113dSnw141292 idmap_id_res *res; 1397c5c4113dSnw141292 1398c5c4113dSnw141292 if (state->ad_nqueries == 0) 1399c5c4113dSnw141292 return (IDMAP_SUCCESS); 1400c5c4113dSnw141292 1401c5c4113dSnw141292 retry: 1402c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 1403c5c4113dSnw141292 &state->ad_lookup); 1404c5c4113dSnw141292 if (ret != 0) { 1405*c8e26105Sjp151216 degrade_svc(); 1406c5c4113dSnw141292 idmapdlog(LOG_ERR, 1407c5c4113dSnw141292 "Failed to create sid2name batch for AD lookup"); 1408c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1409c5c4113dSnw141292 } 1410c5c4113dSnw141292 1411*c8e26105Sjp151216 restore_svc(); 1412*c8e26105Sjp151216 1413c5c4113dSnw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 1414c5c4113dSnw141292 req = &batch->idmap_mapping_batch_val[i]; 1415c5c4113dSnw141292 res = &result->ids.ids_val[i]; 1416c5c4113dSnw141292 141762c60062Sbaban if (req->id1.idtype == IDMAP_SID && 141862c60062Sbaban req->direction & _IDMAP_F_S2N_AD) { 1419c5c4113dSnw141292 if (retries == 0) 1420c5c4113dSnw141292 res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 1421c5c4113dSnw141292 else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 1422c5c4113dSnw141292 continue; 1423c5c4113dSnw141292 retcode = idmap_sid2name_batch_add1( 1424c5c4113dSnw141292 state->ad_lookup, 1425c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 1426c5c4113dSnw141292 &req->id1.idmap_id_u.sid.rid, 14278e228215Sdm199847 &req->id1name, 14288e228215Sdm199847 &req->id1domain, 1429c5c4113dSnw141292 (int *)&res->id.idtype, 1430c5c4113dSnw141292 &res->retcode); 1431c5c4113dSnw141292 1432c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1433c5c4113dSnw141292 break; 1434c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 1435c5c4113dSnw141292 goto out; 1436c5c4113dSnw141292 } 1437c5c4113dSnw141292 } 1438c5c4113dSnw141292 1439c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 144084decf41Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 1441c5c4113dSnw141292 else 1442c5c4113dSnw141292 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 1443c5c4113dSnw141292 1444c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 1445c5c4113dSnw141292 goto retry; 1446*c8e26105Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1447*c8e26105Sjp151216 degrade_svc(); 1448c5c4113dSnw141292 1449c5c4113dSnw141292 return (retcode); 1450c5c4113dSnw141292 1451c5c4113dSnw141292 out: 1452c5c4113dSnw141292 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 145384decf41Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 1454c5c4113dSnw141292 return (retcode); 1455c5c4113dSnw141292 } 1456c5c4113dSnw141292 1457c5c4113dSnw141292 idmap_retcode 1458c5c4113dSnw141292 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 1459c5c4113dSnw141292 idmap_id_res *res) { 1460c5c4113dSnw141292 idmap_retcode retcode; 1461c5c4113dSnw141292 1462c5c4113dSnw141292 /* 1463c5c4113dSnw141292 * The req->direction field is used to maintain state of the 1464c5c4113dSnw141292 * sid2pid request. 1465c5c4113dSnw141292 */ 1466c5c4113dSnw141292 req->direction = _IDMAP_F_DONE; 1467c5c4113dSnw141292 1468cf5b5989Sdm199847 if (EMPTY_STRING(req->id1.idmap_id_u.sid.prefix)) { 1469c5c4113dSnw141292 retcode = IDMAP_ERR_SID; 1470c5c4113dSnw141292 goto out; 1471c5c4113dSnw141292 } 1472c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 1473c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 1474c5c4113dSnw141292 147562c60062Sbaban /* Lookup well-known sid to pid mapping */ 1476c5c4113dSnw141292 retcode = lookup_wksids_sid2pid(req, res); 1477c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 1478c5c4113dSnw141292 goto out; 1479c5c4113dSnw141292 1480c5c4113dSnw141292 /* Lookup sid to pid in cache */ 1481c5c4113dSnw141292 retcode = lookup_cache_sid2pid(cache, req, res); 1482c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 1483c5c4113dSnw141292 goto out; 1484c5c4113dSnw141292 1485c5c4113dSnw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 1486c5c4113dSnw141292 res->id.idmap_id_u.uid = SENTINEL_PID; 1487c5c4113dSnw141292 goto out; 1488c5c4113dSnw141292 } 1489c5c4113dSnw141292 1490c5c4113dSnw141292 /* 1491c5c4113dSnw141292 * Failed to find non-expired entry in cache. Tell the caller 1492c5c4113dSnw141292 * that we are not done yet. 1493c5c4113dSnw141292 */ 1494c5c4113dSnw141292 state->sid2pid_done = FALSE; 1495c5c4113dSnw141292 1496c5c4113dSnw141292 /* 1497c5c4113dSnw141292 * Our next step is name-based mapping. To lookup name-based 1498c5c4113dSnw141292 * mapping rules, we need the windows name and domain-name 1499c5c4113dSnw141292 * associated with the SID. 1500c5c4113dSnw141292 */ 1501c5c4113dSnw141292 1502c5c4113dSnw141292 /* 1503c5c4113dSnw141292 * Check if we already have the name (i.e name2pid lookups) 1504c5c4113dSnw141292 */ 1505cf5b5989Sdm199847 if (!EMPTY_STRING(req->id1name) && 1506cf5b5989Sdm199847 !EMPTY_STRING(req->id1domain)) { 1507c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 1508c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_CACHE; 1509c5c4113dSnw141292 goto out; 1510c5c4113dSnw141292 } 1511c5c4113dSnw141292 151262c60062Sbaban /* Lookup sid to winname@domain locally first */ 151362c60062Sbaban retcode = lookup_local_sid2name(cache, req, res); 151462c60062Sbaban if (retcode == IDMAP_SUCCESS) { 151562c60062Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 151662c60062Sbaban } else if (retcode == IDMAP_ERR_NOTFOUND) { 1517c5c4113dSnw141292 /* Batch sid to name AD lookup request */ 1518c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 1519c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_AD; 1520c5c4113dSnw141292 state->ad_nqueries++; 1521c5c4113dSnw141292 goto out; 1522c5c4113dSnw141292 } 1523c5c4113dSnw141292 1524c5c4113dSnw141292 1525c5c4113dSnw141292 out: 1526c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 1527c5c4113dSnw141292 return (retcode); 1528c5c4113dSnw141292 } 1529c5c4113dSnw141292 1530c5c4113dSnw141292 /* 1531c5c4113dSnw141292 * Generate SID using the following convention 1532c5c4113dSnw141292 * <machine-sid-prefix>-<1000 + uid> 1533c5c4113dSnw141292 * <machine-sid-prefix>-<2^31 + gid> 1534c5c4113dSnw141292 */ 1535c5c4113dSnw141292 static idmap_retcode 1536c5c4113dSnw141292 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) { 1537c5c4113dSnw141292 153862c60062Sbaban if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 1539c5c4113dSnw141292 /* Skip 1000 UIDs */ 1540c5c4113dSnw141292 if (is_user && req->id1.idmap_id_u.uid > 1541c5c4113dSnw141292 (INT32_MAX - LOCALRID_MIN)) 154262c60062Sbaban return (IDMAP_ERR_NOMAPPING); 1543c5c4113dSnw141292 1544c5c4113dSnw141292 RDLOCK_CONFIG(); 1545c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = 1546c5c4113dSnw141292 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 1547c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 1548c5c4113dSnw141292 UNLOCK_CONFIG(); 1549c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1550c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 1551c5c4113dSnw141292 } 1552c5c4113dSnw141292 UNLOCK_CONFIG(); 1553c5c4113dSnw141292 res->id.idmap_id_u.sid.rid = 1554c5c4113dSnw141292 (is_user)?req->id1.idmap_id_u.uid + LOCALRID_MIN: 1555c5c4113dSnw141292 req->id1.idmap_id_u.gid + INT32_MAX + 1; 1556651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 1557c5c4113dSnw141292 1558c5c4113dSnw141292 /* 1559c5c4113dSnw141292 * Don't update name_cache because local sids don't have 1560c5c4113dSnw141292 * valid windows names. 1561c5c4113dSnw141292 * We mark the entry as being found in the namecache so that 1562c5c4113dSnw141292 * the cache update routine doesn't update namecache. 1563c5c4113dSnw141292 */ 1564c5c4113dSnw141292 req->direction = _IDMAP_F_S2N_CACHE; 1565947c7bc0Sbaban return (IDMAP_SUCCESS); 1566c5c4113dSnw141292 } 1567c5c4113dSnw141292 156862c60062Sbaban return (IDMAP_ERR_NOMAPPING); 1569c5c4113dSnw141292 } 1570c5c4113dSnw141292 1571c5c4113dSnw141292 static idmap_retcode 1572c5c4113dSnw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) { 1573c5c4113dSnw141292 char *sidprefix; 1574c5c4113dSnw141292 uint32_t rid; 1575c5c4113dSnw141292 int s; 1576c5c4113dSnw141292 1577c5c4113dSnw141292 /* 1578c5c4113dSnw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 1579c5c4113dSnw141292 * GID = last RID - 2^31. 1580c5c4113dSnw141292 */ 1581c5c4113dSnw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 1582c5c4113dSnw141292 rid = req->id1.idmap_id_u.sid.rid; 1583c5c4113dSnw141292 1584c5c4113dSnw141292 RDLOCK_CONFIG(); 1585c5c4113dSnw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid)? 1586c5c4113dSnw141292 strcasecmp(sidprefix, 1587c5c4113dSnw141292 _idmapdstate.cfg->pgcfg.machine_sid):1; 1588c5c4113dSnw141292 UNLOCK_CONFIG(); 1589c5c4113dSnw141292 1590c5c4113dSnw141292 if (s == 0) { 1591c5c4113dSnw141292 switch (req->id2.idtype) { 1592c5c4113dSnw141292 case IDMAP_UID: 1593c5c4113dSnw141292 if (rid > INT32_MAX) { 1594c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 1595c5c4113dSnw141292 } else if (rid < LOCALRID_MIN) { 1596c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1597c5c4113dSnw141292 } 1598c5c4113dSnw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1599c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1600c5c4113dSnw141292 break; 1601c5c4113dSnw141292 case IDMAP_GID: 1602c5c4113dSnw141292 if (rid <= INT32_MAX) { 1603c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 1604c5c4113dSnw141292 } 1605c5c4113dSnw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 1606c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1607c5c4113dSnw141292 break; 1608c5c4113dSnw141292 case IDMAP_POSIXID: 1609c5c4113dSnw141292 if (rid > INT32_MAX) { 1610c5c4113dSnw141292 res->id.idmap_id_u.gid = 1611c5c4113dSnw141292 rid - INT32_MAX - 1; 1612c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1613c5c4113dSnw141292 } else if (rid < LOCALRID_MIN) { 1614c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1615c5c4113dSnw141292 } else { 1616c5c4113dSnw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1617c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1618c5c4113dSnw141292 } 1619c5c4113dSnw141292 break; 1620c5c4113dSnw141292 default: 1621c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1622c5c4113dSnw141292 } 1623c5c4113dSnw141292 return (IDMAP_SUCCESS); 1624c5c4113dSnw141292 } 1625c5c4113dSnw141292 1626c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1627c5c4113dSnw141292 } 1628c5c4113dSnw141292 1629c5c4113dSnw141292 static idmap_retcode 1630c5c4113dSnw141292 ns_lookup_byname(int is_user, const char *name, idmap_id_res *res) { 1631c5c4113dSnw141292 struct passwd pwd; 1632c5c4113dSnw141292 struct group grp; 1633c5c4113dSnw141292 char buf[1024]; 1634c5c4113dSnw141292 int errnum; 1635c5c4113dSnw141292 const char *me = "ns_lookup_byname"; 1636c5c4113dSnw141292 1637c5c4113dSnw141292 if (is_user) { 1638c5c4113dSnw141292 if (getpwnam_r(name, &pwd, buf, sizeof (buf)) == NULL) { 1639c5c4113dSnw141292 errnum = errno; 1640c5c4113dSnw141292 idmapdlog(LOG_WARNING, 1641c5c4113dSnw141292 "%s: getpwnam_r(%s) failed (%s).", 1642c5c4113dSnw141292 me, name, 1643c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 1644c5c4113dSnw141292 if (errnum == 0) 1645c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1646c5c4113dSnw141292 else 1647c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1648c5c4113dSnw141292 } 1649c5c4113dSnw141292 res->id.idmap_id_u.uid = pwd.pw_uid; 1650c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1651c5c4113dSnw141292 } else { 1652c5c4113dSnw141292 if (getgrnam_r(name, &grp, buf, sizeof (buf)) == NULL) { 1653c5c4113dSnw141292 errnum = errno; 1654c5c4113dSnw141292 idmapdlog(LOG_WARNING, 1655c5c4113dSnw141292 "%s: getgrnam_r(%s) failed (%s).", 1656c5c4113dSnw141292 me, name, 1657c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 1658c5c4113dSnw141292 if (errnum == 0) 1659c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1660c5c4113dSnw141292 else 1661c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1662c5c4113dSnw141292 } 1663c5c4113dSnw141292 res->id.idmap_id_u.gid = grp.gr_gid; 1664c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1665c5c4113dSnw141292 } 1666c5c4113dSnw141292 return (IDMAP_SUCCESS); 1667c5c4113dSnw141292 } 1668c5c4113dSnw141292 1669c5c4113dSnw141292 /* 1670c5c4113dSnw141292 * Name-based mapping 1671c5c4113dSnw141292 * 1672c5c4113dSnw141292 * Case 1: If no rule matches do ephemeral 1673c5c4113dSnw141292 * 1674c5c4113dSnw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 1675c5c4113dSnw141292 * 1676c5c4113dSnw141292 * Case 3: If rule matches and unixname is specified then lookup name 1677c5c4113dSnw141292 * service using the unixname. If unixname not found then return no mapping. 1678c5c4113dSnw141292 * 1679c5c4113dSnw141292 * Case 4: If rule matches and unixname is * then lookup name service 1680c5c4113dSnw141292 * using winname as the unixname. If unixname not found then process 1681c5c4113dSnw141292 * other rules using the lookup order. If no other rule matches then do 1682c5c4113dSnw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 1683c5c4113dSnw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 1684c5c4113dSnw141292 * instead of the default behaviour of doing ephemeral mapping. 1685c5c4113dSnw141292 * 1686c5c4113dSnw141292 * Example 1: 1687c5c4113dSnw141292 * *@sfbay == * 1688c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1689c5c4113dSnw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 1690c5c4113dSnw141292 * 1691c5c4113dSnw141292 * Example 2: 1692c5c4113dSnw141292 * *@sfbay == * 1693c5c4113dSnw141292 * *@sfbay => guest 1694c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1695c5c4113dSnw141292 * the name service then foo@sfbay will be mapped to guest. 1696c5c4113dSnw141292 * 1697c5c4113dSnw141292 * Example 3: 1698c5c4113dSnw141292 * *@sfbay == * 1699c5c4113dSnw141292 * *@sfbay => "" 1700c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1701c5c4113dSnw141292 * the name service then we will return no mapping for foo@sfbay. 1702c5c4113dSnw141292 * 1703c5c4113dSnw141292 */ 1704c5c4113dSnw141292 static idmap_retcode 1705c5c4113dSnw141292 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) { 1706c5c4113dSnw141292 const char *unixname, *winname, *windomain; 1707c5c4113dSnw141292 char *sql = NULL, *errmsg = NULL; 1708c5c4113dSnw141292 idmap_retcode retcode; 1709c5c4113dSnw141292 char *end; 1710c5c4113dSnw141292 const char **values; 1711c5c4113dSnw141292 sqlite_vm *vm = NULL; 171284decf41Sjp151216 int ncol, r, i, is_user; 1713c5c4113dSnw141292 const char *me = "name_based_mapping_sid2pid"; 1714c5c4113dSnw141292 17158e228215Sdm199847 winname = req->id1name; 17168e228215Sdm199847 windomain = req->id1domain; 1717c5c4113dSnw141292 is_user = (res->id.idtype == IDMAP_UID)?1:0; 1718c5c4113dSnw141292 1719c5c4113dSnw141292 i = 0; 172062c60062Sbaban if (windomain == NULL) { 172162c60062Sbaban windomain = ""; 172262c60062Sbaban } else { 172362c60062Sbaban RDLOCK_CONFIG(); 1724*c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 1725*c8e26105Sjp151216 if (strcasecmp(_idmapdstate.cfg->pgcfg.default_domain, 1726c5c4113dSnw141292 windomain) == 0) 1727c5c4113dSnw141292 i = 1; 1728c5c4113dSnw141292 } 1729c5c4113dSnw141292 UNLOCK_CONFIG(); 173062c60062Sbaban } 1731c5c4113dSnw141292 1732c5c4113dSnw141292 sql = sqlite_mprintf( 1733c5c4113dSnw141292 "SELECT unixname, u2w_order FROM namerules WHERE " 1734c5c4113dSnw141292 "w2u_order > 0 AND is_user = %d AND " 1735c5c4113dSnw141292 "(winname = %Q OR winname = '*') AND " 1736c5c4113dSnw141292 "(windomain = %Q OR windomain = '*' %s) " 1737c5c4113dSnw141292 "ORDER BY w2u_order ASC;", 173862c60062Sbaban is_user, winname, 173962c60062Sbaban windomain, 174062c60062Sbaban i?"OR windomain ISNULL OR windomain = ''":""); 1741c5c4113dSnw141292 if (sql == NULL) { 1742c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1743c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1744c5c4113dSnw141292 goto out; 1745c5c4113dSnw141292 } 1746c5c4113dSnw141292 1747c5c4113dSnw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 1748c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1749c5c4113dSnw141292 idmapdlog(LOG_ERR, 1750c5c4113dSnw141292 "%s: database error (%s)", 1751c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 1752c5c4113dSnw141292 sqlite_freemem(errmsg); 1753c5c4113dSnw141292 goto out; 1754c5c4113dSnw141292 } 1755c5c4113dSnw141292 175684decf41Sjp151216 for (; ; ) { 1757c5c4113dSnw141292 r = sqlite_step(vm, &ncol, &values, NULL); 175884decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 1759c5c4113dSnw141292 176084decf41Sjp151216 if (r == SQLITE_ROW) { 1761c5c4113dSnw141292 if (ncol < 2) { 1762c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1763c5c4113dSnw141292 goto out; 1764c5c4113dSnw141292 } 1765c5c4113dSnw141292 if (values[0] == NULL) { 1766c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1767c5c4113dSnw141292 goto out; 1768c5c4113dSnw141292 } 1769c5c4113dSnw141292 1770c5c4113dSnw141292 if (EMPTY_NAME(values[0])) { 1771c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 1772c5c4113dSnw141292 goto out; 1773c5c4113dSnw141292 } 1774c5c4113dSnw141292 unixname = (values[0][0] == '*')?winname:values[0]; 1775c5c4113dSnw141292 retcode = ns_lookup_byname(is_user, unixname, res); 1776c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 1777c5c4113dSnw141292 if (unixname == winname) 1778c5c4113dSnw141292 /* Case 4 */ 1779c5c4113dSnw141292 continue; 1780c5c4113dSnw141292 else 1781c5c4113dSnw141292 /* Case 3 */ 1782c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 1783c5c4113dSnw141292 } 1784c5c4113dSnw141292 goto out; 1785c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 1786c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 1787c5c4113dSnw141292 goto out; 1788c5c4113dSnw141292 } else { 1789c5c4113dSnw141292 (void) sqlite_finalize(vm, &errmsg); 1790c5c4113dSnw141292 vm = NULL; 1791c5c4113dSnw141292 idmapdlog(LOG_ERR, 1792c5c4113dSnw141292 "%s: database error (%s)", 1793c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 1794c5c4113dSnw141292 sqlite_freemem(errmsg); 1795c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1796c5c4113dSnw141292 goto out; 1797c5c4113dSnw141292 } 1798c5c4113dSnw141292 } 1799c5c4113dSnw141292 1800c5c4113dSnw141292 out: 180162c60062Sbaban if (sql != NULL) 1802c5c4113dSnw141292 sqlite_freemem(sql); 1803c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 180462c60062Sbaban if (values[1] != NULL) 1805c5c4113dSnw141292 res->direction = 1806651c0131Sbaban (strtol(values[1], &end, 10) == 0)? 1807651c0131Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 1808c5c4113dSnw141292 else 1809651c0131Sbaban res->direction = IDMAP_DIRECTION_W2U; 18108e228215Sdm199847 req->id2name = strdup(unixname); 1811c5c4113dSnw141292 } 181262c60062Sbaban if (vm != NULL) 1813c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1814c5c4113dSnw141292 return (retcode); 1815c5c4113dSnw141292 } 1816c5c4113dSnw141292 1817c5c4113dSnw141292 static 1818c5c4113dSnw141292 int 1819c5c4113dSnw141292 get_next_eph_uid(uid_t *next_uid) 1820c5c4113dSnw141292 { 1821c5c4113dSnw141292 uid_t uid; 1822c5c4113dSnw141292 gid_t gid; 1823c5c4113dSnw141292 int err; 1824c5c4113dSnw141292 1825c5c4113dSnw141292 *next_uid = (uid_t)-1; 1826c5c4113dSnw141292 uid = _idmapdstate.next_uid++; 1827c5c4113dSnw141292 if (uid >= _idmapdstate.limit_uid) { 1828c5c4113dSnw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 1829c5c4113dSnw141292 return (err); 1830c5c4113dSnw141292 1831c5c4113dSnw141292 _idmapdstate.limit_uid = uid + 8192; 1832c5c4113dSnw141292 _idmapdstate.next_uid = uid; 1833c5c4113dSnw141292 } 1834c5c4113dSnw141292 *next_uid = uid; 1835c5c4113dSnw141292 1836c5c4113dSnw141292 return (0); 1837c5c4113dSnw141292 } 1838c5c4113dSnw141292 1839c5c4113dSnw141292 static 1840c5c4113dSnw141292 int 1841c5c4113dSnw141292 get_next_eph_gid(gid_t *next_gid) 1842c5c4113dSnw141292 { 1843c5c4113dSnw141292 uid_t uid; 1844c5c4113dSnw141292 gid_t gid; 1845c5c4113dSnw141292 int err; 1846c5c4113dSnw141292 1847c5c4113dSnw141292 *next_gid = (uid_t)-1; 1848c5c4113dSnw141292 gid = _idmapdstate.next_gid++; 1849c5c4113dSnw141292 if (gid >= _idmapdstate.limit_gid) { 1850c5c4113dSnw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 1851c5c4113dSnw141292 return (err); 1852c5c4113dSnw141292 1853c5c4113dSnw141292 _idmapdstate.limit_gid = gid + 8192; 1854c5c4113dSnw141292 _idmapdstate.next_gid = gid; 1855c5c4113dSnw141292 } 1856c5c4113dSnw141292 *next_gid = gid; 1857c5c4113dSnw141292 1858c5c4113dSnw141292 return (0); 1859c5c4113dSnw141292 } 1860c5c4113dSnw141292 186162c60062Sbaban static 186262c60062Sbaban int 186362c60062Sbaban gethash(const char *str, uint32_t num, uint_t htsize) { 186462c60062Sbaban uint_t hval, i, len; 186562c60062Sbaban 186662c60062Sbaban if (str == NULL) 186762c60062Sbaban return (0); 186862c60062Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 186962c60062Sbaban hval += str[i]; 187062c60062Sbaban hval += (hval << 10); 187162c60062Sbaban hval ^= (hval >> 6); 187262c60062Sbaban } 187362c60062Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 187462c60062Sbaban hval += str[i]; 187562c60062Sbaban hval += (hval << 10); 187662c60062Sbaban hval ^= (hval >> 6); 187762c60062Sbaban } 187862c60062Sbaban hval += (hval << 3); 187962c60062Sbaban hval ^= (hval >> 11); 188062c60062Sbaban hval += (hval << 15); 188162c60062Sbaban return (hval % htsize); 188262c60062Sbaban } 188362c60062Sbaban 188462c60062Sbaban static 188562c60062Sbaban int 188662c60062Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 188762c60062Sbaban uid_t *pid) { 188862c60062Sbaban uint_t next, key; 188962c60062Sbaban uint_t htsize = state->sid_history_size; 189062c60062Sbaban idmap_sid *sid; 189162c60062Sbaban 189262c60062Sbaban next = gethash(prefix, rid, htsize); 189362c60062Sbaban while (next != htsize) { 189462c60062Sbaban key = state->sid_history[next].key; 189562c60062Sbaban if (key == htsize) 189662c60062Sbaban return (0); 189762c60062Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 189862c60062Sbaban idmap_id_u.sid; 189962c60062Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 190062c60062Sbaban *pid = state->result->ids.ids_val[key].id. 190162c60062Sbaban idmap_id_u.uid; 190262c60062Sbaban return (1); 190362c60062Sbaban } 190462c60062Sbaban next = state->sid_history[next].next; 190562c60062Sbaban } 190662c60062Sbaban return (0); 190762c60062Sbaban } 190862c60062Sbaban 190962c60062Sbaban static 191062c60062Sbaban void 191162c60062Sbaban add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) { 191262c60062Sbaban uint_t hash, next; 191362c60062Sbaban uint_t htsize = state->sid_history_size; 191462c60062Sbaban 191562c60062Sbaban hash = next = gethash(prefix, rid, htsize); 191662c60062Sbaban while (state->sid_history[next].key != htsize) { 191762c60062Sbaban next++; 191862c60062Sbaban next %= htsize; 191962c60062Sbaban } 192062c60062Sbaban state->sid_history[next].key = state->curpos; 192162c60062Sbaban if (hash == next) 192262c60062Sbaban return; 192362c60062Sbaban state->sid_history[next].next = state->sid_history[hash].next; 192462c60062Sbaban state->sid_history[hash].next = next; 192562c60062Sbaban } 1926c5c4113dSnw141292 1927c5c4113dSnw141292 /* ARGSUSED */ 1928c5c4113dSnw141292 static 1929c5c4113dSnw141292 idmap_retcode 193062c60062Sbaban dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 193162c60062Sbaban idmap_mapping *req, idmap_id_res *res) { 1932c5c4113dSnw141292 1933c5c4113dSnw141292 uid_t next_pid; 1934c5c4113dSnw141292 1935651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 193662c60062Sbaban 193762c60062Sbaban if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 193862c60062Sbaban return (IDMAP_SUCCESS); 193962c60062Sbaban 194062c60062Sbaban if (state->sid_history != NULL && 194162c60062Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 194262c60062Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 194362c60062Sbaban res->id.idmap_id_u.uid = next_pid; 194462c60062Sbaban return (IDMAP_SUCCESS); 194562c60062Sbaban } 194662c60062Sbaban 194762c60062Sbaban if (res->id.idtype == IDMAP_UID) { 1948c5c4113dSnw141292 if (get_next_eph_uid(&next_pid) != 0) 1949c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1950c5c4113dSnw141292 res->id.idmap_id_u.uid = next_pid; 1951c5c4113dSnw141292 } else { 1952c5c4113dSnw141292 if (get_next_eph_gid(&next_pid) != 0) 1953c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1954c5c4113dSnw141292 res->id.idmap_id_u.gid = next_pid; 1955c5c4113dSnw141292 } 1956c5c4113dSnw141292 195762c60062Sbaban if (state->sid_history != NULL) 195862c60062Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 195962c60062Sbaban req->id1.idmap_id_u.sid.rid); 196062c60062Sbaban 1961c5c4113dSnw141292 return (IDMAP_SUCCESS); 1962c5c4113dSnw141292 } 1963c5c4113dSnw141292 1964c5c4113dSnw141292 idmap_retcode 1965c5c4113dSnw141292 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 1966c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res) { 1967c5c4113dSnw141292 idmap_retcode retcode; 1968c5c4113dSnw141292 1969c5c4113dSnw141292 /* 1970c5c4113dSnw141292 * The req->direction field is used to maintain state of the 1971c5c4113dSnw141292 * sid2pid request. 1972c5c4113dSnw141292 */ 1973c5c4113dSnw141292 1974c5c4113dSnw141292 /* Check if second pass is needed */ 1975c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 1976c5c4113dSnw141292 return (res->retcode); 1977c5c4113dSnw141292 1978c5c4113dSnw141292 /* Get status from previous pass */ 1979c5c4113dSnw141292 retcode = (res->retcode == IDMAP_NEXT)?IDMAP_SUCCESS:res->retcode; 1980c5c4113dSnw141292 1981c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 1982c5c4113dSnw141292 /* Reset return type */ 1983c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 1984c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 1985c5c4113dSnw141292 1986c5c4113dSnw141292 /* Check if this is a localsid */ 1987c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND && 1988c5c4113dSnw141292 _idmapdstate.cfg->pgcfg.machine_sid) { 1989c5c4113dSnw141292 retcode = lookup_localsid2pid(req, res); 1990c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 1991c5c4113dSnw141292 state->sid2pid_done = FALSE; 1992c5c4113dSnw141292 req->direction = _IDMAP_F_S2N_CACHE; 1993c5c4113dSnw141292 } 1994c5c4113dSnw141292 } 1995c5c4113dSnw141292 goto out; 1996c5c4113dSnw141292 } 1997c5c4113dSnw141292 1998c5c4113dSnw141292 /* 1999c5c4113dSnw141292 * Verify that the sid type matches the request if the 2000c5c4113dSnw141292 * SID was validated by an AD lookup. 2001c5c4113dSnw141292 */ 2002c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_AD) { 2003c5c4113dSnw141292 retcode = verify_type(req->id2.idtype, 2004c5c4113dSnw141292 (int)res->id.idtype, res); 2005c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2006c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 2007c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 2008c5c4113dSnw141292 goto out; 2009c5c4113dSnw141292 } 2010c5c4113dSnw141292 } 2011c5c4113dSnw141292 2012c5c4113dSnw141292 /* Name-based mapping */ 2013c5c4113dSnw141292 retcode = name_based_mapping_sid2pid(db, req, res); 2014c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) 2015c5c4113dSnw141292 /* If not found, do ephemeral mapping */ 2016c5c4113dSnw141292 goto ephemeral; 2017c5c4113dSnw141292 else if (retcode != IDMAP_SUCCESS) 2018c5c4113dSnw141292 goto out; 2019c5c4113dSnw141292 2020c5c4113dSnw141292 state->sid2pid_done = FALSE; 2021c5c4113dSnw141292 goto out; 2022c5c4113dSnw141292 2023c5c4113dSnw141292 2024c5c4113dSnw141292 ephemeral: 202562c60062Sbaban retcode = dynamic_ephemeral_mapping(state, cache, req, res); 2026c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) 2027c5c4113dSnw141292 state->sid2pid_done = FALSE; 2028c5c4113dSnw141292 2029c5c4113dSnw141292 out: 2030c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 2031c5c4113dSnw141292 return (retcode); 2032c5c4113dSnw141292 } 2033c5c4113dSnw141292 2034c5c4113dSnw141292 idmap_retcode 2035c5c4113dSnw141292 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 2036c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res) { 2037c5c4113dSnw141292 char *sql = NULL; 2038c5c4113dSnw141292 idmap_retcode retcode; 2039c5c4113dSnw141292 2040c5c4113dSnw141292 /* Check if we need to cache anything */ 2041c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 2042c5c4113dSnw141292 return (IDMAP_SUCCESS); 2043c5c4113dSnw141292 2044c5c4113dSnw141292 /* We don't cache negative entries */ 2045c5c4113dSnw141292 if (res->retcode != IDMAP_SUCCESS) 2046c5c4113dSnw141292 return (IDMAP_SUCCESS); 2047c5c4113dSnw141292 2048c5c4113dSnw141292 /* 2049c5c4113dSnw141292 * Using NULL for u2w instead of 0 so that our trigger allows 2050c5c4113dSnw141292 * the same pid to be the destination in multiple entries 2051c5c4113dSnw141292 */ 2052c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2053c5c4113dSnw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 2054c5c4113dSnw141292 "is_user, expiration, w2u, u2w) " 2055c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 2056c5c4113dSnw141292 "strftime('%%s','now') + 600, %q, 1); ", 2057c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix, 2058c5c4113dSnw141292 res->id.idmap_id_u.sid.rid, 20598e228215Sdm199847 req->id2domain, 20608e228215Sdm199847 req->id2name, 2061c5c4113dSnw141292 req->id1.idmap_id_u.uid, 20628e228215Sdm199847 req->id1name, 2063c5c4113dSnw141292 (req->id1.idtype == IDMAP_UID)?1:0, 2064c5c4113dSnw141292 (res->direction == 0)?"1":NULL); 2065c5c4113dSnw141292 2066c5c4113dSnw141292 if (sql == NULL) { 2067c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2068c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2069c5c4113dSnw141292 goto out; 2070c5c4113dSnw141292 } 2071c5c4113dSnw141292 2072c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2073c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2074c5c4113dSnw141292 goto out; 2075c5c4113dSnw141292 2076c5c4113dSnw141292 state->pid2sid_done = FALSE; 2077c5c4113dSnw141292 sqlite_freemem(sql); 2078c5c4113dSnw141292 sql = NULL; 2079c5c4113dSnw141292 2080c5c4113dSnw141292 /* If sid2name was found in the cache, no need to update namecache */ 2081c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 2082c5c4113dSnw141292 goto out; 2083c5c4113dSnw141292 20848e228215Sdm199847 if (req->id2name == NULL) 2085c5c4113dSnw141292 goto out; 2086c5c4113dSnw141292 2087c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2088c5c4113dSnw141292 "(sidprefix, rid, name, domain, type, expiration) " 2089c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2090c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix, 2091c5c4113dSnw141292 res->id.idmap_id_u.sid.rid, 20928e228215Sdm199847 req->id2name, 20938e228215Sdm199847 req->id2domain, 2094c5c4113dSnw141292 (req->id1.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 2095c5c4113dSnw141292 2096c5c4113dSnw141292 if (sql == NULL) { 2097c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2098c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2099c5c4113dSnw141292 goto out; 2100c5c4113dSnw141292 } 2101c5c4113dSnw141292 2102c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2103c5c4113dSnw141292 2104c5c4113dSnw141292 out: 210562c60062Sbaban if (sql != NULL) 2106c5c4113dSnw141292 sqlite_freemem(sql); 2107c5c4113dSnw141292 return (retcode); 2108c5c4113dSnw141292 } 2109c5c4113dSnw141292 2110c5c4113dSnw141292 idmap_retcode 2111c5c4113dSnw141292 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 2112c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res) { 2113c5c4113dSnw141292 char *sql = NULL; 2114c5c4113dSnw141292 idmap_retcode retcode; 2115c5c4113dSnw141292 int is_eph_user; 2116c5c4113dSnw141292 2117c5c4113dSnw141292 /* Check if we need to cache anything */ 2118c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 2119c5c4113dSnw141292 return (IDMAP_SUCCESS); 2120c5c4113dSnw141292 2121c5c4113dSnw141292 /* We don't cache negative entries */ 2122c5c4113dSnw141292 if (res->retcode != IDMAP_SUCCESS) 2123c5c4113dSnw141292 return (IDMAP_SUCCESS); 2124c5c4113dSnw141292 2125c5c4113dSnw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 2126c5c4113dSnw141292 is_eph_user = 1; 2127c5c4113dSnw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 2128c5c4113dSnw141292 is_eph_user = 0; 2129c5c4113dSnw141292 else 2130c5c4113dSnw141292 is_eph_user = -1; 2131c5c4113dSnw141292 2132c5c4113dSnw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 2133c5c4113dSnw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 2134c5c4113dSnw141292 "SET w2u = 0 WHERE " 2135c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 2136c5c4113dSnw141292 "pid >= 2147483648 AND is_user = %d;", 2137c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2138c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 2139c5c4113dSnw141292 is_eph_user); 2140c5c4113dSnw141292 if (sql == NULL) { 2141c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2142c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2143c5c4113dSnw141292 goto out; 2144c5c4113dSnw141292 } 2145c5c4113dSnw141292 2146c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2147c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2148c5c4113dSnw141292 goto out; 2149c5c4113dSnw141292 2150c5c4113dSnw141292 sqlite_freemem(sql); 2151c5c4113dSnw141292 sql = NULL; 2152c5c4113dSnw141292 } 2153c5c4113dSnw141292 2154c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2155c5c4113dSnw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 2156c5c4113dSnw141292 "is_user, expiration, w2u, u2w) " 2157c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 2158c5c4113dSnw141292 "strftime('%%s','now') + 600, 1, %q); ", 2159c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2160c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 21618e228215Sdm199847 req->id1domain, 21628e228215Sdm199847 req->id1name, 2163c5c4113dSnw141292 res->id.idmap_id_u.uid, 21648e228215Sdm199847 req->id2name, 2165c5c4113dSnw141292 (res->id.idtype == IDMAP_UID)?1:0, 2166c5c4113dSnw141292 (res->direction == 0)?"1":NULL); 2167c5c4113dSnw141292 2168c5c4113dSnw141292 if (sql == NULL) { 2169c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2170c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2171c5c4113dSnw141292 goto out; 2172c5c4113dSnw141292 } 2173c5c4113dSnw141292 2174c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2175c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2176c5c4113dSnw141292 goto out; 2177c5c4113dSnw141292 2178c5c4113dSnw141292 state->sid2pid_done = FALSE; 2179c5c4113dSnw141292 sqlite_freemem(sql); 2180c5c4113dSnw141292 sql = NULL; 2181c5c4113dSnw141292 2182c5c4113dSnw141292 /* If name2sid was found in the cache, no need to update namecache */ 2183c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 2184c5c4113dSnw141292 goto out; 2185c5c4113dSnw141292 2186cf5b5989Sdm199847 if (EMPTY_STRING(req->id1name)) 2187c5c4113dSnw141292 goto out; 2188c5c4113dSnw141292 2189c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2190c5c4113dSnw141292 "(sidprefix, rid, name, domain, type, expiration) " 2191c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2192c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2193c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 21948e228215Sdm199847 req->id1name, 21958e228215Sdm199847 req->id1domain, 2196c5c4113dSnw141292 (res->id.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 2197c5c4113dSnw141292 2198c5c4113dSnw141292 if (sql == NULL) { 2199c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2200c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2201c5c4113dSnw141292 goto out; 2202c5c4113dSnw141292 } 2203c5c4113dSnw141292 2204c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2205c5c4113dSnw141292 2206c5c4113dSnw141292 out: 220762c60062Sbaban if (sql != NULL) 2208c5c4113dSnw141292 sqlite_freemem(sql); 2209c5c4113dSnw141292 return (retcode); 2210c5c4113dSnw141292 } 2211c5c4113dSnw141292 2212c5c4113dSnw141292 static idmap_retcode 2213c5c4113dSnw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 2214c5c4113dSnw141292 int is_user, int getname) { 2215c5c4113dSnw141292 char *end; 2216c5c4113dSnw141292 char *sql = NULL; 2217c5c4113dSnw141292 const char **values; 2218c5c4113dSnw141292 sqlite_vm *vm = NULL; 2219c5c4113dSnw141292 int ncol; 2220c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2221c5c4113dSnw141292 time_t curtime; 2222c5c4113dSnw141292 2223c5c4113dSnw141292 /* Current time */ 2224c5c4113dSnw141292 errno = 0; 2225c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 2226c5c4113dSnw141292 idmapdlog(LOG_ERR, 2227c5c4113dSnw141292 "Failed to get current time (%s)", 2228c5c4113dSnw141292 strerror(errno)); 2229c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2230c5c4113dSnw141292 goto out; 2231c5c4113dSnw141292 } 2232c5c4113dSnw141292 2233c5c4113dSnw141292 /* SQL to lookup the cache */ 2234c5c4113dSnw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, winname, windomain, w2u " 2235c5c4113dSnw141292 "FROM idmap_cache WHERE " 2236c5c4113dSnw141292 "pid = %u AND u2w = 1 AND is_user = %d AND " 2237c5c4113dSnw141292 "(pid >= 2147483648 OR " 2238c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 2239c5c4113dSnw141292 "expiration > %d));", 2240c5c4113dSnw141292 req->id1.idmap_id_u.uid, is_user, curtime); 2241c5c4113dSnw141292 if (sql == NULL) { 2242c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2243c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2244c5c4113dSnw141292 goto out; 2245c5c4113dSnw141292 } 2246c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 2247c5c4113dSnw141292 sqlite_freemem(sql); 2248c5c4113dSnw141292 2249c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) 2250c5c4113dSnw141292 goto out; 2251c5c4113dSnw141292 else if (retcode == IDMAP_SUCCESS) { 2252c5c4113dSnw141292 /* sanity checks */ 2253c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 2254c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2255c5c4113dSnw141292 goto out; 2256c5c4113dSnw141292 } 2257c5c4113dSnw141292 2258c5c4113dSnw141292 switch (req->id2.idtype) { 2259c5c4113dSnw141292 case IDMAP_SID: 2260c5c4113dSnw141292 res->id.idmap_id_u.sid.rid = 2261c5c4113dSnw141292 strtoul(values[1], &end, 10); 2262c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 2263c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 2264c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2265c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2266c5c4113dSnw141292 goto out; 2267c5c4113dSnw141292 } 2268c5c4113dSnw141292 226962c60062Sbaban if (values[4] != NULL) 2270c5c4113dSnw141292 res->direction = 2271651c0131Sbaban (strtol(values[4], &end, 10) == 0)? 2272651c0131Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2273c5c4113dSnw141292 else 2274651c0131Sbaban res->direction = IDMAP_DIRECTION_U2W; 2275c5c4113dSnw141292 2276c5c4113dSnw141292 if (getname == 0 || values[2] == NULL) 2277c5c4113dSnw141292 break; 22788e228215Sdm199847 req->id2name = strdup(values[2]); 22798e228215Sdm199847 if (req->id2name == NULL) { 2280c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2281c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2282c5c4113dSnw141292 goto out; 2283c5c4113dSnw141292 } 2284c5c4113dSnw141292 2285c5c4113dSnw141292 if (values[3] == NULL) 2286c5c4113dSnw141292 break; 22878e228215Sdm199847 req->id2domain = strdup(values[3]); 22888e228215Sdm199847 if (req->id2domain == NULL) { 2289c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2290c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2291c5c4113dSnw141292 goto out; 2292c5c4113dSnw141292 } 2293c5c4113dSnw141292 break; 2294c5c4113dSnw141292 default: 2295c5c4113dSnw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 2296c5c4113dSnw141292 break; 2297c5c4113dSnw141292 } 2298c5c4113dSnw141292 } 2299c5c4113dSnw141292 2300c5c4113dSnw141292 out: 230162c60062Sbaban if (vm != NULL) 2302c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2303c5c4113dSnw141292 return (retcode); 2304c5c4113dSnw141292 } 2305c5c4113dSnw141292 2306c5c4113dSnw141292 static idmap_retcode 2307c5c4113dSnw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 2308c5c4113dSnw141292 char **sidprefix, idmap_rid_t *rid, int *type) { 2309c5c4113dSnw141292 char *end; 2310c5c4113dSnw141292 char *sql = NULL; 2311c5c4113dSnw141292 const char **values; 2312c5c4113dSnw141292 sqlite_vm *vm = NULL; 2313c5c4113dSnw141292 int ncol; 2314c5c4113dSnw141292 time_t curtime; 2315c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2316c5c4113dSnw141292 2317c5c4113dSnw141292 /* Get current time */ 2318c5c4113dSnw141292 errno = 0; 2319c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 2320c5c4113dSnw141292 idmapdlog(LOG_ERR, 2321c5c4113dSnw141292 "Failed to get current time (%s)", 2322c5c4113dSnw141292 strerror(errno)); 2323c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2324c5c4113dSnw141292 goto out; 2325c5c4113dSnw141292 } 2326c5c4113dSnw141292 2327c5c4113dSnw141292 /* SQL to lookup the cache */ 2328c5c4113dSnw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type FROM name_cache " 2329c5c4113dSnw141292 "WHERE name = %Q AND domain = %Q AND " 2330c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 2331c5c4113dSnw141292 "expiration > %d);", 2332c5c4113dSnw141292 name, domain, curtime); 2333c5c4113dSnw141292 if (sql == NULL) { 2334c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2335c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2336c5c4113dSnw141292 goto out; 2337c5c4113dSnw141292 } 2338c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 2339c5c4113dSnw141292 sqlite_freemem(sql); 2340c5c4113dSnw141292 2341c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 234262c60062Sbaban if (type != NULL) { 2343c5c4113dSnw141292 if (values[2] == NULL) { 2344c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2345c5c4113dSnw141292 goto out; 2346c5c4113dSnw141292 } 2347c5c4113dSnw141292 *type = strtol(values[2], &end, 10); 2348c5c4113dSnw141292 } 2349c5c4113dSnw141292 2350c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 2351c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2352c5c4113dSnw141292 goto out; 2353c5c4113dSnw141292 } 2354c5c4113dSnw141292 if ((*sidprefix = strdup(values[0])) == NULL) { 2355c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2356c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2357c5c4113dSnw141292 goto out; 2358c5c4113dSnw141292 } 2359c5c4113dSnw141292 *rid = strtoul(values[1], &end, 10); 2360c5c4113dSnw141292 } 2361c5c4113dSnw141292 2362c5c4113dSnw141292 out: 236362c60062Sbaban if (vm != NULL) 2364c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2365c5c4113dSnw141292 return (retcode); 2366c5c4113dSnw141292 } 2367c5c4113dSnw141292 2368c5c4113dSnw141292 static idmap_retcode 2369c5c4113dSnw141292 lookup_win_name2sid(const char *name, const char *domain, char **sidprefix, 2370c5c4113dSnw141292 idmap_rid_t *rid, int *type) { 2371c5c4113dSnw141292 int ret; 2372c5c4113dSnw141292 int retries = 0; 2373c5c4113dSnw141292 idmap_query_state_t *qs = NULL; 2374c5c4113dSnw141292 idmap_retcode rc, retcode; 2375c5c4113dSnw141292 2376c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2377c5c4113dSnw141292 2378c5c4113dSnw141292 retry: 2379c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 2380c5c4113dSnw141292 if (ret != 0) { 2381*c8e26105Sjp151216 degrade_svc(); 2382c5c4113dSnw141292 idmapdlog(LOG_ERR, 2383c5c4113dSnw141292 "Failed to create name2sid batch for AD lookup"); 2384c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2385c5c4113dSnw141292 } 2386c5c4113dSnw141292 2387*c8e26105Sjp151216 restore_svc(); 2388*c8e26105Sjp151216 2389c5c4113dSnw141292 retcode = idmap_name2sid_batch_add1(qs, name, domain, sidprefix, 2390c5c4113dSnw141292 rid, type, &rc); 2391c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2392c5c4113dSnw141292 goto out; 2393c5c4113dSnw141292 2394c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2395c5c4113dSnw141292 idmapdlog(LOG_ERR, 2396c5c4113dSnw141292 "Failed to batch name2sid for AD lookup"); 239784decf41Sjp151216 idmap_lookup_release_batch(&qs); 2398c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2399c5c4113dSnw141292 } 2400c5c4113dSnw141292 2401c5c4113dSnw141292 out: 2402c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 240384decf41Sjp151216 idmap_lookup_release_batch(&qs); 2404c5c4113dSnw141292 else 2405c5c4113dSnw141292 retcode = idmap_lookup_batch_end(&qs, NULL); 2406c5c4113dSnw141292 2407c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 2408c5c4113dSnw141292 goto retry; 2409*c8e26105Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2410*c8e26105Sjp151216 degrade_svc(); 2411c5c4113dSnw141292 2412c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2413c5c4113dSnw141292 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 2414c5c4113dSnw141292 "failed"); 2415c5c4113dSnw141292 return (retcode); 2416c5c4113dSnw141292 } else 2417c5c4113dSnw141292 return (rc); 2418c5c4113dSnw141292 /* NOTREACHED */ 2419c5c4113dSnw141292 } 2420c5c4113dSnw141292 2421c5c4113dSnw141292 static idmap_retcode 2422c5c4113dSnw141292 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 2423c5c4113dSnw141292 int *is_user, char **sidprefix, idmap_rid_t *rid, 2424c5c4113dSnw141292 idmap_mapping *req) { 2425c5c4113dSnw141292 int type; 2426c5c4113dSnw141292 idmap_retcode retcode; 2427c5c4113dSnw141292 242862c60062Sbaban /* Lookup name@domain to sid in the well-known sids table */ 242962c60062Sbaban retcode = lookup_wksids_name2sid(name, sidprefix, rid, &type); 243062c60062Sbaban if (retcode == IDMAP_SUCCESS) { 243162c60062Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 243262c60062Sbaban goto out; 243362c60062Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 243462c60062Sbaban return (retcode); 243562c60062Sbaban } 243662c60062Sbaban 243762c60062Sbaban /* Lookup name@domain to sid in cache */ 2438c5c4113dSnw141292 retcode = lookup_cache_name2sid(cache, name, domain, sidprefix, 2439c5c4113dSnw141292 rid, &type); 2440c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2441c5c4113dSnw141292 /* Lookup Windows NT/AD to map name@domain to sid */ 2442c5c4113dSnw141292 retcode = lookup_win_name2sid(name, domain, sidprefix, rid, 2443c5c4113dSnw141292 &type); 2444c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2445c5c4113dSnw141292 return (retcode); 2446c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_AD; 2447c5c4113dSnw141292 } else if (retcode != IDMAP_SUCCESS) { 2448c5c4113dSnw141292 return (retcode); 2449c5c4113dSnw141292 } else { 2450c5c4113dSnw141292 /* Set flag */ 2451c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_CACHE; 2452c5c4113dSnw141292 } 2453c5c4113dSnw141292 245462c60062Sbaban out: 2455c5c4113dSnw141292 /* 2456c5c4113dSnw141292 * Entry found (cache or Windows lookup) 2457c5c4113dSnw141292 * is_user is both input as well as output parameter 2458c5c4113dSnw141292 */ 2459c5c4113dSnw141292 if (*is_user == 1) { 2460c5c4113dSnw141292 if (type != _IDMAP_T_USER) 2461c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 2462c5c4113dSnw141292 } else if (*is_user == 0) { 2463c5c4113dSnw141292 if (type != _IDMAP_T_GROUP) 2464c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 2465c5c4113dSnw141292 } else if (*is_user == -1) { 2466c5c4113dSnw141292 /* Caller wants to know if its user or group */ 2467c5c4113dSnw141292 if (type == _IDMAP_T_USER) 2468c5c4113dSnw141292 *is_user = 1; 2469c5c4113dSnw141292 else if (type == _IDMAP_T_GROUP) 2470c5c4113dSnw141292 *is_user = 0; 2471c5c4113dSnw141292 else 2472c5c4113dSnw141292 return (IDMAP_ERR_SID); 2473c5c4113dSnw141292 } 2474c5c4113dSnw141292 2475c5c4113dSnw141292 return (retcode); 2476c5c4113dSnw141292 } 2477c5c4113dSnw141292 2478c5c4113dSnw141292 static idmap_retcode 2479c5c4113dSnw141292 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 2480c5c4113dSnw141292 int is_user, idmap_mapping *req, idmap_id_res *res) { 2481c5c4113dSnw141292 const char *winname, *windomain; 2482*c8e26105Sjp151216 char *default_domain = NULL; 2483c5c4113dSnw141292 char *sql = NULL, *errmsg = NULL; 2484c5c4113dSnw141292 idmap_retcode retcode; 2485c5c4113dSnw141292 char *end; 2486c5c4113dSnw141292 const char **values; 2487c5c4113dSnw141292 sqlite_vm *vm = NULL; 248884decf41Sjp151216 int ncol, r; 2489c5c4113dSnw141292 const char *me = "name_based_mapping_pid2sid"; 2490c5c4113dSnw141292 2491c5c4113dSnw141292 RDLOCK_CONFIG(); 2492*c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2493*c8e26105Sjp151216 default_domain = 2494*c8e26105Sjp151216 strdup(_idmapdstate.cfg->pgcfg.default_domain); 2495*c8e26105Sjp151216 if (default_domain == NULL) { 2496c5c4113dSnw141292 UNLOCK_CONFIG(); 2497c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2498c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2499c5c4113dSnw141292 goto out; 2500c5c4113dSnw141292 } 2501c5c4113dSnw141292 } 2502c5c4113dSnw141292 UNLOCK_CONFIG(); 2503c5c4113dSnw141292 2504c5c4113dSnw141292 sql = sqlite_mprintf( 2505c5c4113dSnw141292 "SELECT winname, windomain, w2u_order FROM namerules WHERE " 2506c5c4113dSnw141292 "u2w_order > 0 AND is_user = %d AND " 2507c5c4113dSnw141292 "(unixname = %Q OR unixname = '*') " 2508c5c4113dSnw141292 "ORDER BY u2w_order ASC;", 2509c5c4113dSnw141292 is_user, unixname); 2510c5c4113dSnw141292 if (sql == NULL) { 2511c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2512c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2513c5c4113dSnw141292 goto out; 2514c5c4113dSnw141292 } 2515c5c4113dSnw141292 2516c5c4113dSnw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 2517c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2518c5c4113dSnw141292 idmapdlog(LOG_ERR, 2519c5c4113dSnw141292 "%s: database error (%s)", 2520c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 2521c5c4113dSnw141292 sqlite_freemem(errmsg); 2522c5c4113dSnw141292 goto out; 2523c5c4113dSnw141292 } 2524c5c4113dSnw141292 252584decf41Sjp151216 for (;;) { 2526c5c4113dSnw141292 r = sqlite_step(vm, &ncol, &values, NULL); 252784decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 252884decf41Sjp151216 if (r == SQLITE_ROW) { 2529c5c4113dSnw141292 if (ncol < 3) { 2530c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2531c5c4113dSnw141292 goto out; 2532c5c4113dSnw141292 } 2533c5c4113dSnw141292 if (values[0] == NULL) { 2534c5c4113dSnw141292 /* values [1] and [2] can be null */ 2535c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2536c5c4113dSnw141292 goto out; 2537c5c4113dSnw141292 } 2538c5c4113dSnw141292 if (EMPTY_NAME(values[0])) { 2539c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2540c5c4113dSnw141292 goto out; 2541c5c4113dSnw141292 } 2542c5c4113dSnw141292 winname = (values[0][0] == '*')?unixname:values[0]; 254362c60062Sbaban if (values[1] != NULL) 2544c5c4113dSnw141292 windomain = values[1]; 2545*c8e26105Sjp151216 else if (default_domain != NULL) 2546*c8e26105Sjp151216 windomain = default_domain; 2547c5c4113dSnw141292 else { 2548c5c4113dSnw141292 idmapdlog(LOG_ERR, 2549c5c4113dSnw141292 "%s: no domain", me); 2550c5c4113dSnw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 2551c5c4113dSnw141292 goto out; 2552c5c4113dSnw141292 } 2553c5c4113dSnw141292 /* Lookup winname@domain to sid */ 2554c5c4113dSnw141292 retcode = lookup_name2sid(cache, winname, windomain, 2555c5c4113dSnw141292 &is_user, &res->id.idmap_id_u.sid.prefix, 2556c5c4113dSnw141292 &res->id.idmap_id_u.sid.rid, req); 2557c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2558c5c4113dSnw141292 if (winname == unixname) 2559c5c4113dSnw141292 continue; 2560c5c4113dSnw141292 else 2561c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2562c5c4113dSnw141292 } 2563c5c4113dSnw141292 goto out; 2564c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 2565c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2566c5c4113dSnw141292 goto out; 2567c5c4113dSnw141292 } else { 2568c5c4113dSnw141292 (void) sqlite_finalize(vm, &errmsg); 2569c5c4113dSnw141292 vm = NULL; 2570c5c4113dSnw141292 idmapdlog(LOG_ERR, 2571c5c4113dSnw141292 "%s: database error (%s)", 2572c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 2573c5c4113dSnw141292 sqlite_freemem(errmsg); 2574c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2575c5c4113dSnw141292 goto out; 2576c5c4113dSnw141292 } 2577c5c4113dSnw141292 } 2578c5c4113dSnw141292 2579c5c4113dSnw141292 out: 258062c60062Sbaban if (sql != NULL) 2581c5c4113dSnw141292 sqlite_freemem(sql); 2582c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 258362c60062Sbaban if (values[2] != NULL) 2584c5c4113dSnw141292 res->direction = 2585651c0131Sbaban (strtol(values[2], &end, 10) == 0)? 2586651c0131Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2587c5c4113dSnw141292 else 2588651c0131Sbaban res->direction = IDMAP_DIRECTION_U2W; 25898e228215Sdm199847 25908e228215Sdm199847 req->id2name = strdup(winname); 25918e228215Sdm199847 if (req->id2name != NULL) { 2592*c8e26105Sjp151216 if (windomain == default_domain) { 25938e228215Sdm199847 req->id2domain = (char *)windomain; 2594*c8e26105Sjp151216 default_domain = NULL; 25958e228215Sdm199847 } else { 25968e228215Sdm199847 req->id2domain = strdup(windomain); 25978e228215Sdm199847 } 2598c5c4113dSnw141292 } 2599c5c4113dSnw141292 } 260062c60062Sbaban if (vm != NULL) 2601c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2602*c8e26105Sjp151216 if (default_domain != NULL) 2603*c8e26105Sjp151216 free(default_domain); 2604c5c4113dSnw141292 return (retcode); 2605c5c4113dSnw141292 } 2606c5c4113dSnw141292 2607c5c4113dSnw141292 idmap_retcode 2608c5c4113dSnw141292 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 2609c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res, int is_user, 2610c5c4113dSnw141292 int getname) { 2611c5c4113dSnw141292 char *unixname = NULL; 2612c5c4113dSnw141292 struct passwd pwd; 2613c5c4113dSnw141292 struct group grp; 2614c5c4113dSnw141292 char buf[1024]; 2615c5c4113dSnw141292 int errnum; 2616c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2617c5c4113dSnw141292 const char *me = "pid2sid"; 2618c5c4113dSnw141292 2619c5c4113dSnw141292 req->direction = _IDMAP_F_DONE; 2620c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 2621c5c4113dSnw141292 2622c5c4113dSnw141292 /* Lookup well-known SIDs */ 2623c5c4113dSnw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 2624c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 2625c5c4113dSnw141292 goto out; 2626c5c4113dSnw141292 2627c5c4113dSnw141292 /* Lookup pid to sid in cache */ 2628c5c4113dSnw141292 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 2629c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 2630c5c4113dSnw141292 goto out; 2631c5c4113dSnw141292 2632c5c4113dSnw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 2633c5c4113dSnw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 263462c60062Sbaban retcode = IDMAP_ERR_NOMAPPING; 2635c5c4113dSnw141292 goto out; 2636c5c4113dSnw141292 } 2637c5c4113dSnw141292 2638c5c4113dSnw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 263962c60062Sbaban retcode = IDMAP_ERR_NOMAPPING; 2640c5c4113dSnw141292 goto out; 2641c5c4113dSnw141292 } 2642c5c4113dSnw141292 2643c5c4113dSnw141292 /* uid/gid to name */ 2644cf5b5989Sdm199847 if (!EMPTY_STRING(req->id1name)) { 26458e228215Sdm199847 unixname = req->id1name; 26468e228215Sdm199847 } else if (is_user) { 2647c5c4113dSnw141292 errno = 0; 2648c5c4113dSnw141292 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 2649c5c4113dSnw141292 sizeof (buf)) == NULL) { 2650c5c4113dSnw141292 errnum = errno; 2651c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2652c5c4113dSnw141292 "%s: getpwuid_r(%u) failed (%s).", 2653c5c4113dSnw141292 me, req->id1.idmap_id_u.uid, 2654c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2655c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2656c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2657c5c4113dSnw141292 goto fallback_localsid; 2658c5c4113dSnw141292 } 2659c5c4113dSnw141292 unixname = pwd.pw_name; 2660c5c4113dSnw141292 } else { 2661c5c4113dSnw141292 errno = 0; 2662c5c4113dSnw141292 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 2663c5c4113dSnw141292 sizeof (buf)) == NULL) { 2664c5c4113dSnw141292 errnum = errno; 2665c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2666c5c4113dSnw141292 "%s: getgrgid_r(%u) failed (%s).", 2667c5c4113dSnw141292 me, req->id1.idmap_id_u.gid, 2668c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2669c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2670c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2671c5c4113dSnw141292 goto fallback_localsid; 2672c5c4113dSnw141292 } 2673c5c4113dSnw141292 unixname = grp.gr_name; 2674c5c4113dSnw141292 } 2675c5c4113dSnw141292 2676c5c4113dSnw141292 /* Name-based mapping */ 2677c5c4113dSnw141292 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 2678c5c4113dSnw141292 req, res); 2679c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2680c5c4113dSnw141292 retcode = generate_localsid(req, res, is_user); 2681c5c4113dSnw141292 goto out; 2682c5c4113dSnw141292 } else if (retcode == IDMAP_SUCCESS) 2683c5c4113dSnw141292 goto out; 2684c5c4113dSnw141292 2685c5c4113dSnw141292 fallback_localsid: 2686c5c4113dSnw141292 /* 2687c5c4113dSnw141292 * Here we generate localsid as fallback id on errors. Our 2688c5c4113dSnw141292 * return status is the error that's been previously assigned. 2689c5c4113dSnw141292 */ 2690c5c4113dSnw141292 (void) generate_localsid(req, res, is_user); 2691c5c4113dSnw141292 2692c5c4113dSnw141292 out: 2693cf5b5989Sdm199847 if (retcode == IDMAP_SUCCESS && EMPTY_STRING(req->id1name) && 269462c60062Sbaban unixname != NULL) { 2695cf5b5989Sdm199847 if (req->id1name != NULL) 2696cf5b5989Sdm199847 free(req->id1name); 26978e228215Sdm199847 req->id1name = strdup(unixname); 2698cf5b5989Sdm199847 if (req->id1name == NULL) 2699cf5b5989Sdm199847 retcode = IDMAP_ERR_MEMORY; 2700c5c4113dSnw141292 } 2701c5c4113dSnw141292 if (req->direction != _IDMAP_F_DONE) 2702c5c4113dSnw141292 state->pid2sid_done = FALSE; 2703c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 2704c5c4113dSnw141292 return (retcode); 2705c5c4113dSnw141292 } 2706c5c4113dSnw141292 2707c5c4113dSnw141292 static idmap_retcode 2708c5c4113dSnw141292 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 2709c5c4113dSnw141292 char **domain, int *type) { 2710c5c4113dSnw141292 int ret; 2711c5c4113dSnw141292 idmap_query_state_t *qs = NULL; 2712c5c4113dSnw141292 idmap_retcode rc, retcode; 2713c5c4113dSnw141292 2714c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2715c5c4113dSnw141292 2716c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 2717c5c4113dSnw141292 if (ret != 0) { 2718*c8e26105Sjp151216 degrade_svc(); 2719c5c4113dSnw141292 idmapdlog(LOG_ERR, 2720c5c4113dSnw141292 "Failed to create sid2name batch for AD lookup"); 2721c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2722c5c4113dSnw141292 goto out; 2723c5c4113dSnw141292 } 2724c5c4113dSnw141292 2725*c8e26105Sjp151216 restore_svc(); 2726*c8e26105Sjp151216 2727c5c4113dSnw141292 ret = idmap_sid2name_batch_add1( 2728c5c4113dSnw141292 qs, sidprefix, &rid, name, domain, type, &rc); 2729c5c4113dSnw141292 if (ret != 0) { 2730c5c4113dSnw141292 idmapdlog(LOG_ERR, 2731c5c4113dSnw141292 "Failed to batch sid2name for AD lookup"); 2732c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2733c5c4113dSnw141292 goto out; 2734c5c4113dSnw141292 } 2735c5c4113dSnw141292 2736c5c4113dSnw141292 out: 273762c60062Sbaban if (qs != NULL) { 2738c5c4113dSnw141292 ret = idmap_lookup_batch_end(&qs, NULL); 2739*c8e26105Sjp151216 if (ret == IDMAP_ERR_RETRIABLE_NET_ERR) 2740*c8e26105Sjp151216 degrade_svc(); 2741c5c4113dSnw141292 if (ret != 0) { 2742c5c4113dSnw141292 idmapdlog(LOG_ERR, 2743c5c4113dSnw141292 "Failed to execute sid2name AD lookup"); 2744c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2745c5c4113dSnw141292 } else 2746c5c4113dSnw141292 retcode = rc; 2747c5c4113dSnw141292 } 2748c5c4113dSnw141292 2749c5c4113dSnw141292 return (retcode); 2750c5c4113dSnw141292 } 2751c5c4113dSnw141292 2752651c0131Sbaban static int 2753651c0131Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 2754c5c4113dSnw141292 { 2755651c0131Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 2756651c0131Sbaban 2757c5c4113dSnw141292 mapping->flag = request->flag; 2758c5c4113dSnw141292 mapping->direction = request->direction; 2759651c0131Sbaban mapping->id2.idtype = request->id2.idtype; 2760c5c4113dSnw141292 2761c5c4113dSnw141292 mapping->id1.idtype = request->id1.idtype; 2762c5c4113dSnw141292 if (request->id1.idtype == IDMAP_SID) { 2763c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.rid = 2764c5c4113dSnw141292 request->id1.idmap_id_u.sid.rid; 2765651c0131Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 2766c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.prefix = 2767c5c4113dSnw141292 strdup(request->id1.idmap_id_u.sid.prefix); 2768651c0131Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 27698e228215Sdm199847 goto errout; 2770651c0131Sbaban } 2771c5c4113dSnw141292 } else { 2772c5c4113dSnw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 2773c5c4113dSnw141292 } 2774c5c4113dSnw141292 27758e228215Sdm199847 mapping->id1domain = strdup(request->id1domain); 27768e228215Sdm199847 if (mapping->id1domain == NULL) 27778e228215Sdm199847 goto errout; 2778c5c4113dSnw141292 27798e228215Sdm199847 mapping->id1name = strdup(request->id1name); 27808e228215Sdm199847 if (mapping->id1name == NULL) 27818e228215Sdm199847 goto errout; 2782c5c4113dSnw141292 2783651c0131Sbaban /* We don't need the rest of the request i.e request->id2 */ 2784651c0131Sbaban return (0); 2785c5c4113dSnw141292 2786651c0131Sbaban errout: 27878e228215Sdm199847 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 2788651c0131Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 27898e228215Sdm199847 if (mapping->id1domain != NULL) 27908e228215Sdm199847 free(mapping->id1domain); 27918e228215Sdm199847 if (mapping->id1name != NULL) 27928e228215Sdm199847 free(mapping->id1name); 2793651c0131Sbaban 2794651c0131Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 2795651c0131Sbaban return (-1); 2796c5c4113dSnw141292 } 2797c5c4113dSnw141292 2798c5c4113dSnw141292 2799c5c4113dSnw141292 idmap_retcode 2800c5c4113dSnw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 2801c5c4113dSnw141292 idmap_mapping *mapping) { 2802c5c4113dSnw141292 idmap_id_res idres; 2803c5c4113dSnw141292 lookup_state_t state; 2804dd5829d1Sbaban char *cp; 2805c5c4113dSnw141292 int is_user; 2806c5c4113dSnw141292 idmap_retcode retcode; 2807c5c4113dSnw141292 const char *winname, *windomain; 2808c5c4113dSnw141292 2809c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 2810c5c4113dSnw141292 (void) memset(&state, 0, sizeof (state)); 2811c5c4113dSnw141292 2812c5c4113dSnw141292 if (request->id2.idtype == IDMAP_UID) 2813c5c4113dSnw141292 is_user = 1; 2814c5c4113dSnw141292 else if (request->id2.idtype == IDMAP_GID) 2815c5c4113dSnw141292 is_user = 0; 2816c5c4113dSnw141292 else if (request->id2.idtype == IDMAP_POSIXID) 2817c5c4113dSnw141292 is_user = -1; 2818c5c4113dSnw141292 else { 2819c5c4113dSnw141292 retcode = IDMAP_ERR_IDTYPE; 2820c5c4113dSnw141292 goto out; 2821c5c4113dSnw141292 } 2822c5c4113dSnw141292 2823c5c4113dSnw141292 /* Copy data from request to result */ 2824651c0131Sbaban if (copy_mapping_request(mapping, request) < 0) { 2825651c0131Sbaban retcode = IDMAP_ERR_MEMORY; 2826651c0131Sbaban goto out; 2827651c0131Sbaban } 2828c5c4113dSnw141292 28298e228215Sdm199847 winname = mapping->id1name; 28308e228215Sdm199847 windomain = mapping->id1domain; 2831c5c4113dSnw141292 2832cf5b5989Sdm199847 if (EMPTY_STRING(winname) && !EMPTY_STRING(windomain)) { 2833c5c4113dSnw141292 retcode = IDMAP_ERR_ARG; 2834c5c4113dSnw141292 goto out; 2835c5c4113dSnw141292 } 2836c5c4113dSnw141292 2837cf5b5989Sdm199847 if (!EMPTY_STRING(winname) && EMPTY_STRING(windomain)) { 28388e228215Sdm199847 retcode = IDMAP_SUCCESS; 2839dd5829d1Sbaban if ((cp = strchr(winname, '@')) != NULL) { 2840dd5829d1Sbaban /* 2841dd5829d1Sbaban * if winname is qualified with a domain, use it. 2842dd5829d1Sbaban */ 2843dd5829d1Sbaban *cp = '\0'; 28448e228215Sdm199847 mapping->id1domain = strdup(cp + 1); 28458e228215Sdm199847 if (mapping->id1domain == NULL) 28468e228215Sdm199847 retcode = IDMAP_ERR_MEMORY; 28478e228215Sdm199847 } else { 28488e228215Sdm199847 RDLOCK_CONFIG(); 2849*c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2850dd5829d1Sbaban /* 2851dd5829d1Sbaban * otherwise use the mapping domain 2852dd5829d1Sbaban */ 28538e228215Sdm199847 mapping->id1domain = 28548e228215Sdm199847 strdup(_idmapdstate.cfg-> 2855*c8e26105Sjp151216 pgcfg.default_domain); 28568e228215Sdm199847 if (mapping->id1domain == NULL) 28578e228215Sdm199847 retcode = IDMAP_ERR_MEMORY; 28588e228215Sdm199847 } 2859c5c4113dSnw141292 UNLOCK_CONFIG(); 28608e228215Sdm199847 } 2861dd5829d1Sbaban 2862dd5829d1Sbaban if (retcode != IDMAP_SUCCESS) { 2863c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2864c5c4113dSnw141292 goto out; 2865c5c4113dSnw141292 } 28668e228215Sdm199847 windomain = mapping->id1domain; 2867c5c4113dSnw141292 } 2868c5c4113dSnw141292 2869cf5b5989Sdm199847 if (!EMPTY_STRING(winname) && 2870cf5b5989Sdm199847 EMPTY_STRING(mapping->id1.idmap_id_u.sid.prefix)) { 2871c5c4113dSnw141292 retcode = lookup_name2sid(cache, winname, windomain, 2872c5c4113dSnw141292 &is_user, &mapping->id1.idmap_id_u.sid.prefix, 2873c5c4113dSnw141292 &mapping->id1.idmap_id_u.sid.rid, mapping); 2874c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2875c5c4113dSnw141292 goto out; 2876c5c4113dSnw141292 if (mapping->id2.idtype == IDMAP_POSIXID) 2877c5c4113dSnw141292 mapping->id2.idtype = is_user?IDMAP_UID:IDMAP_GID; 2878c5c4113dSnw141292 } 2879c5c4113dSnw141292 2880c5c4113dSnw141292 state.sid2pid_done = TRUE; 2881c5c4113dSnw141292 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 2882c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 2883c5c4113dSnw141292 goto out; 2884c5c4113dSnw141292 2885c5c4113dSnw141292 if (state.ad_nqueries) { 2886c5c4113dSnw141292 /* sid2name AD lookup */ 2887c5c4113dSnw141292 retcode = lookup_win_sid2name( 2888c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.prefix, 2889c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.rid, 28908e228215Sdm199847 &mapping->id1name, 28918e228215Sdm199847 &mapping->id1domain, 2892c5c4113dSnw141292 (int *)&idres.id.idtype); 2893c5c4113dSnw141292 2894c5c4113dSnw141292 idres.retcode = retcode; 2895c5c4113dSnw141292 } 2896c5c4113dSnw141292 2897c5c4113dSnw141292 state.sid2pid_done = TRUE; 2898c5c4113dSnw141292 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 2899c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 2900c5c4113dSnw141292 goto out; 2901c5c4113dSnw141292 2902c5c4113dSnw141292 /* Update cache */ 2903c5c4113dSnw141292 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 2904c5c4113dSnw141292 2905c5c4113dSnw141292 out: 2906c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 2907c5c4113dSnw141292 mapping->direction = idres.direction; 2908c5c4113dSnw141292 mapping->id2 = idres.id; 2909c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 291062c60062Sbaban } else { 291162c60062Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 2912c5c4113dSnw141292 } 2913c5c4113dSnw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 2914c5c4113dSnw141292 return (retcode); 2915c5c4113dSnw141292 } 2916c5c4113dSnw141292 2917c5c4113dSnw141292 idmap_retcode 2918c5c4113dSnw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 2919c5c4113dSnw141292 idmap_mapping *mapping, int is_user) { 2920c5c4113dSnw141292 idmap_id_res idres; 2921c5c4113dSnw141292 lookup_state_t state; 2922c5c4113dSnw141292 struct passwd pwd; 2923c5c4113dSnw141292 struct group grp; 2924c5c4113dSnw141292 char buf[1024]; 2925c5c4113dSnw141292 int errnum; 2926c5c4113dSnw141292 idmap_retcode retcode; 2927c5c4113dSnw141292 const char *unixname; 2928c5c4113dSnw141292 const char *me = "get_u2w_mapping"; 2929c5c4113dSnw141292 2930c5c4113dSnw141292 /* 2931c5c4113dSnw141292 * In order to re-use the pid2sid code, we convert 2932c5c4113dSnw141292 * our input data into structs that are expected by 2933c5c4113dSnw141292 * pid2sid_first_pass. 2934c5c4113dSnw141292 */ 2935c5c4113dSnw141292 2936c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 2937c5c4113dSnw141292 (void) memset(&state, 0, sizeof (state)); 2938c5c4113dSnw141292 2939c5c4113dSnw141292 /* Copy data from request to result */ 2940651c0131Sbaban if (copy_mapping_request(mapping, request) < 0) { 2941651c0131Sbaban retcode = IDMAP_ERR_MEMORY; 2942651c0131Sbaban goto out; 2943651c0131Sbaban } 2944c5c4113dSnw141292 29458e228215Sdm199847 unixname = mapping->id1name; 2946c5c4113dSnw141292 2947cf5b5989Sdm199847 if (EMPTY_STRING(unixname) && 2948cf5b5989Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 2949c5c4113dSnw141292 retcode = IDMAP_ERR_ARG; 2950c5c4113dSnw141292 goto out; 2951c5c4113dSnw141292 } 2952c5c4113dSnw141292 2953cf5b5989Sdm199847 if (!EMPTY_STRING(unixname) && 2954cf5b5989Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 2955c5c4113dSnw141292 /* Get uid/gid by name */ 2956c5c4113dSnw141292 if (is_user) { 2957c5c4113dSnw141292 errno = 0; 2958c5c4113dSnw141292 if (getpwnam_r(unixname, &pwd, buf, 2959c5c4113dSnw141292 sizeof (buf)) == NULL) { 2960c5c4113dSnw141292 errnum = errno; 2961c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2962c5c4113dSnw141292 "%s: getpwnam_r(%s) failed (%s).", 2963c5c4113dSnw141292 me, unixname, 2964c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2965c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2966c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2967c5c4113dSnw141292 goto out; 2968c5c4113dSnw141292 } 2969c5c4113dSnw141292 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 2970c5c4113dSnw141292 } else { 2971c5c4113dSnw141292 errno = 0; 2972c5c4113dSnw141292 if (getgrnam_r(unixname, &grp, buf, 2973c5c4113dSnw141292 sizeof (buf)) == NULL) { 2974c5c4113dSnw141292 errnum = errno; 2975c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2976c5c4113dSnw141292 "%s: getgrnam_r(%s) failed (%s).", 2977c5c4113dSnw141292 me, unixname, 2978c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2979c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2980c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2981c5c4113dSnw141292 goto out; 2982c5c4113dSnw141292 } 2983c5c4113dSnw141292 mapping->id1.idmap_id_u.gid = grp.gr_gid; 2984c5c4113dSnw141292 } 2985c5c4113dSnw141292 } 2986c5c4113dSnw141292 2987c5c4113dSnw141292 state.pid2sid_done = TRUE; 2988c5c4113dSnw141292 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 2989c5c4113dSnw141292 is_user, 1); 2990c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 2991c5c4113dSnw141292 goto out; 2992c5c4113dSnw141292 2993c5c4113dSnw141292 /* Update cache */ 2994c5c4113dSnw141292 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 2995c5c4113dSnw141292 2996c5c4113dSnw141292 out: 2997c5c4113dSnw141292 mapping->direction = idres.direction; 2998c5c4113dSnw141292 mapping->id2 = idres.id; 2999c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 3000c5c4113dSnw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 3001c5c4113dSnw141292 return (retcode); 3002c5c4113dSnw141292 } 3003