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 32c5c4113dSnw141292 #include <stdio.h> 33c5c4113dSnw141292 #include <stdlib.h> 34c5c4113dSnw141292 #include <string.h> 35c5c4113dSnw141292 #include <errno.h> 36c5c4113dSnw141292 #include <sys/types.h> 37c5c4113dSnw141292 #include <sys/stat.h> 38c5c4113dSnw141292 #include <rpc/rpc.h> 39c5c4113dSnw141292 #include <sys/sid.h> 40c5c4113dSnw141292 #include <time.h> 41c5c4113dSnw141292 #include <pwd.h> 42c5c4113dSnw141292 #include <grp.h> 4384decf41Sjp151216 #include <pthread.h> 4484decf41Sjp151216 #include <assert.h> 45c5c4113dSnw141292 46c5c4113dSnw141292 #include "idmapd.h" 47c5c4113dSnw141292 #include "adutils.h" 48c5c4113dSnw141292 #include "string.h" 49c5c4113dSnw141292 #include "idmap_priv.h" 50c5c4113dSnw141292 5184decf41Sjp151216 52c5c4113dSnw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 53c5c4113dSnw141292 sqlite_vm **, int *, int, const char ***); 5462c60062Sbaban static idmap_retcode lookup_wksids_name2sid(const char *, char **, 5562c60062Sbaban idmap_rid_t *, int *); 56c5c4113dSnw141292 57c5c4113dSnw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 58c5c4113dSnw141292 59c5c4113dSnw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 60c5c4113dSnw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 61c5c4113dSnw141292 62c5c4113dSnw141292 #define AVOID_NAMESERVICE(req)\ 63c5c4113dSnw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 64c5c4113dSnw141292 65c5c4113dSnw141292 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 66c5c4113dSnw141292 67c5c4113dSnw141292 #define LOCALRID_MIN 1000 68c5c4113dSnw141292 69c5c4113dSnw141292 70c5c4113dSnw141292 71c5c4113dSnw141292 typedef enum init_db_option { 72c5c4113dSnw141292 FAIL_IF_CORRUPT = 0, 73c5c4113dSnw141292 REMOVE_IF_CORRUPT = 1 74c5c4113dSnw141292 } init_db_option_t; 75c5c4113dSnw141292 7684decf41Sjp151216 /* 7784decf41Sjp151216 * Thread specfic data to hold the database handles so that the 7884decf41Sjp151216 * databaes are not opened and closed for every request. It also 7984decf41Sjp151216 * contains the sqlite busy handler structure. 8084decf41Sjp151216 */ 8184decf41Sjp151216 8284decf41Sjp151216 struct idmap_busy { 8384decf41Sjp151216 const char *name; 8484decf41Sjp151216 const int *delays; 8584decf41Sjp151216 int delay_size; 8684decf41Sjp151216 int total; 8784decf41Sjp151216 int sec; 8884decf41Sjp151216 }; 8984decf41Sjp151216 9084decf41Sjp151216 9184decf41Sjp151216 typedef struct idmap_tsd { 9284decf41Sjp151216 sqlite *db_db; 9384decf41Sjp151216 sqlite *cache_db; 9484decf41Sjp151216 struct idmap_busy cache_busy; 9584decf41Sjp151216 struct idmap_busy db_busy; 9684decf41Sjp151216 } idmap_tsd_t; 9784decf41Sjp151216 9884decf41Sjp151216 9984decf41Sjp151216 10084decf41Sjp151216 static const int cache_delay_table[] = 10184decf41Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 10284decf41Sjp151216 50, 50, 60, 70, 80, 90, 100}; 10384decf41Sjp151216 10484decf41Sjp151216 static const int db_delay_table[] = 10584decf41Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 10684decf41Sjp151216 10784decf41Sjp151216 10884decf41Sjp151216 static pthread_key_t idmap_tsd_key; 10984decf41Sjp151216 11084decf41Sjp151216 void 11184decf41Sjp151216 idmap_tsd_destroy(void *key) 11284decf41Sjp151216 { 11384decf41Sjp151216 11484decf41Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 11584decf41Sjp151216 if (tsd) { 11684decf41Sjp151216 if (tsd->db_db) 11784decf41Sjp151216 (void) sqlite_close(tsd->db_db); 11884decf41Sjp151216 if (tsd->cache_db) 11984decf41Sjp151216 (void) sqlite_close(tsd->cache_db); 12084decf41Sjp151216 free(tsd); 12184decf41Sjp151216 } 12284decf41Sjp151216 } 12384decf41Sjp151216 12484decf41Sjp151216 int 12584decf41Sjp151216 idmap_init_tsd_key(void) { 12684decf41Sjp151216 12784decf41Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 12884decf41Sjp151216 } 12984decf41Sjp151216 13084decf41Sjp151216 13184decf41Sjp151216 13284decf41Sjp151216 idmap_tsd_t * 13384decf41Sjp151216 idmap_get_tsd(void) 13484decf41Sjp151216 { 13584decf41Sjp151216 idmap_tsd_t *tsd; 13684decf41Sjp151216 13784decf41Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 13884decf41Sjp151216 /* No thread specific data so create it */ 13984decf41Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 14084decf41Sjp151216 /* Initialize thread specific data */ 14184decf41Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 14284decf41Sjp151216 /* save the trhread specific data */ 14384decf41Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 14484decf41Sjp151216 /* Can't store key */ 14584decf41Sjp151216 free(tsd); 14684decf41Sjp151216 tsd = NULL; 14784decf41Sjp151216 } 14884decf41Sjp151216 } else { 14984decf41Sjp151216 tsd = NULL; 15084decf41Sjp151216 } 15184decf41Sjp151216 } 15284decf41Sjp151216 15384decf41Sjp151216 return (tsd); 15484decf41Sjp151216 } 15584decf41Sjp151216 15684decf41Sjp151216 157c5c4113dSnw141292 158c5c4113dSnw141292 /* 159c5c4113dSnw141292 * Initialize 'dbname' using 'sql' 160c5c4113dSnw141292 */ 161c5c4113dSnw141292 static int 162c5c4113dSnw141292 init_db_instance(const char *dbname, const char *sql, init_db_option_t opt, 163c5c4113dSnw141292 int *new_db_created) 164c5c4113dSnw141292 { 165c5c4113dSnw141292 int rc = 0; 166c5c4113dSnw141292 int tries = 0; 167c5c4113dSnw141292 sqlite *db = NULL; 168c5c4113dSnw141292 char *str = NULL; 169c5c4113dSnw141292 170c5c4113dSnw141292 if (new_db_created != NULL) 171c5c4113dSnw141292 *new_db_created = 0; 172c5c4113dSnw141292 173c5c4113dSnw141292 db = sqlite_open(dbname, 0600, &str); 174c5c4113dSnw141292 while (db == NULL) { 175c5c4113dSnw141292 idmapdlog(LOG_ERR, 176c5c4113dSnw141292 "Error creating database %s (%s)", 177c5c4113dSnw141292 dbname, CHECK_NULL(str)); 178c5c4113dSnw141292 sqlite_freemem(str); 179c5c4113dSnw141292 if (opt == FAIL_IF_CORRUPT || opt != REMOVE_IF_CORRUPT || 180c5c4113dSnw141292 tries > 0) 181c5c4113dSnw141292 return (-1); 182c5c4113dSnw141292 183c5c4113dSnw141292 tries++; 184c5c4113dSnw141292 (void) unlink(dbname); 185c5c4113dSnw141292 db = sqlite_open(dbname, 0600, &str); 186c5c4113dSnw141292 } 187c5c4113dSnw141292 188c5c4113dSnw141292 sqlite_busy_timeout(db, 3000); 189c5c4113dSnw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &str); 190c5c4113dSnw141292 if (SQLITE_OK != rc) { 191c5c4113dSnw141292 idmapdlog(LOG_ERR, "Cannot begin database transaction (%s)", 192c5c4113dSnw141292 str); 193c5c4113dSnw141292 sqlite_freemem(str); 194c5c4113dSnw141292 sqlite_close(db); 195c5c4113dSnw141292 return (1); 196c5c4113dSnw141292 } 197c5c4113dSnw141292 198c5c4113dSnw141292 switch (sqlite_exec(db, sql, NULL, NULL, &str)) { 199c5c4113dSnw141292 case SQLITE_ERROR: 200c5c4113dSnw141292 /* 201c5c4113dSnw141292 * This is the normal situation: CREATE probably failed because tables 202c5c4113dSnw141292 * already exist. It may indicate an error in SQL as well, but we cannot 203c5c4113dSnw141292 * tell. 204c5c4113dSnw141292 */ 205c5c4113dSnw141292 sqlite_freemem(str); 206c5c4113dSnw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 207c5c4113dSnw141292 NULL, NULL, &str); 208c5c4113dSnw141292 break; 209c5c4113dSnw141292 case SQLITE_OK: 210c5c4113dSnw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", 211c5c4113dSnw141292 NULL, NULL, &str); 212c5c4113dSnw141292 idmapdlog(LOG_INFO, 213c5c4113dSnw141292 "Database created at %s", dbname); 214c5c4113dSnw141292 215c5c4113dSnw141292 if (new_db_created != NULL) 216c5c4113dSnw141292 *new_db_created = 1; 217c5c4113dSnw141292 break; 218c5c4113dSnw141292 default: 219c5c4113dSnw141292 idmapdlog(LOG_ERR, 220c5c4113dSnw141292 "Error initializing database %s (%s)", 221c5c4113dSnw141292 dbname, str); 222c5c4113dSnw141292 sqlite_freemem(str); 223c5c4113dSnw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 224c5c4113dSnw141292 NULL, NULL, &str); 225c5c4113dSnw141292 break; 226c5c4113dSnw141292 } 227c5c4113dSnw141292 228c5c4113dSnw141292 if (SQLITE_OK != rc) { 229c5c4113dSnw141292 /* this is bad - database may be left in a locked state */ 230c5c4113dSnw141292 idmapdlog(LOG_ERR, 231c5c4113dSnw141292 "Error closing transaction (%s)", str); 232c5c4113dSnw141292 sqlite_freemem(str); 233c5c4113dSnw141292 } 234c5c4113dSnw141292 235c5c4113dSnw141292 (void) sqlite_close(db); 236c5c4113dSnw141292 return (rc); 237c5c4113dSnw141292 } 238c5c4113dSnw141292 23984decf41Sjp151216 24084decf41Sjp151216 /* 24184decf41Sjp151216 * This is the SQLite database busy handler that retries the SQL 24284decf41Sjp151216 * operation until it is successful. 24384decf41Sjp151216 */ 24484decf41Sjp151216 int 24584decf41Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 24684decf41Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 24784decf41Sjp151216 { 24884decf41Sjp151216 struct idmap_busy *busy = arg; 24984decf41Sjp151216 int delay; 25084decf41Sjp151216 struct timespec rqtp; 25184decf41Sjp151216 25284decf41Sjp151216 if (count == 1) { 25384decf41Sjp151216 busy->total = 0; 25484decf41Sjp151216 busy->sec = 2; 25584decf41Sjp151216 } 25684decf41Sjp151216 if (busy->total > 1000 * busy->sec) { 25784decf41Sjp151216 idmapdlog(LOG_ERR, 25884decf41Sjp151216 "Thread %d waited %d sec for the %s database", 25984decf41Sjp151216 pthread_self(), busy->sec, busy->name); 26084decf41Sjp151216 busy->sec++; 26184decf41Sjp151216 } 26284decf41Sjp151216 26384decf41Sjp151216 if (count <= busy->delay_size) { 26484decf41Sjp151216 delay = busy->delays[count-1]; 26584decf41Sjp151216 } else { 26684decf41Sjp151216 delay = busy->delays[busy->delay_size - 1]; 26784decf41Sjp151216 } 26884decf41Sjp151216 busy->total += delay; 26984decf41Sjp151216 rqtp.tv_sec = 0; 27084decf41Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 27184decf41Sjp151216 (void) nanosleep(&rqtp, NULL); 27284decf41Sjp151216 return (1); 27384decf41Sjp151216 } 27484decf41Sjp151216 27584decf41Sjp151216 276c5c4113dSnw141292 /* 277c5c4113dSnw141292 * Get the database handle 278c5c4113dSnw141292 */ 279c5c4113dSnw141292 idmap_retcode 280c5c4113dSnw141292 get_db_handle(sqlite **db) { 281c5c4113dSnw141292 char *errmsg; 28284decf41Sjp151216 idmap_tsd_t *tsd; 283c5c4113dSnw141292 284c5c4113dSnw141292 /* 28584decf41Sjp151216 * Retrieve the db handle from thread-specific storage 286c5c4113dSnw141292 * If none exists, open and store in thread-specific storage. 287c5c4113dSnw141292 */ 28884decf41Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 28984decf41Sjp151216 idmapdlog(LOG_ERR, 29084decf41Sjp151216 "Error getting thread specific data for %s", 29184decf41Sjp151216 IDMAP_DBNAME); 29284decf41Sjp151216 return (IDMAP_ERR_MEMORY); 29384decf41Sjp151216 } 294c5c4113dSnw141292 29584decf41Sjp151216 if (tsd->db_db == NULL) { 29684decf41Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 29784decf41Sjp151216 if (tsd->db_db == NULL) { 298c5c4113dSnw141292 idmapdlog(LOG_ERR, 299c5c4113dSnw141292 "Error opening database %s (%s)", 300c5c4113dSnw141292 IDMAP_DBNAME, CHECK_NULL(errmsg)); 301c5c4113dSnw141292 sqlite_freemem(errmsg); 302c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 303c5c4113dSnw141292 } 30484decf41Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 30584decf41Sjp151216 tsd->db_busy.delays = db_delay_table; 30684decf41Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 30784decf41Sjp151216 sizeof (int); 30884decf41Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 30984decf41Sjp151216 &tsd->db_busy); 31084decf41Sjp151216 } 31184decf41Sjp151216 *db = tsd->db_db; 312c5c4113dSnw141292 return (IDMAP_SUCCESS); 313c5c4113dSnw141292 } 314c5c4113dSnw141292 315c5c4113dSnw141292 /* 316c5c4113dSnw141292 * Get the cache handle 317c5c4113dSnw141292 */ 318c5c4113dSnw141292 idmap_retcode 31984decf41Sjp151216 get_cache_handle(sqlite **cache) { 320c5c4113dSnw141292 char *errmsg; 32184decf41Sjp151216 idmap_tsd_t *tsd; 322c5c4113dSnw141292 323c5c4113dSnw141292 /* 32484decf41Sjp151216 * Retrieve the db handle from thread-specific storage 325c5c4113dSnw141292 * If none exists, open and store in thread-specific storage. 326c5c4113dSnw141292 */ 32784decf41Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 32884decf41Sjp151216 idmapdlog(LOG_ERR, 32984decf41Sjp151216 "Error getting thread specific data for %s", 33084decf41Sjp151216 IDMAP_DBNAME); 33184decf41Sjp151216 return (IDMAP_ERR_MEMORY); 33284decf41Sjp151216 } 333c5c4113dSnw141292 33484decf41Sjp151216 if (tsd->cache_db == NULL) { 33584decf41Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 33684decf41Sjp151216 if (tsd->cache_db == NULL) { 337c5c4113dSnw141292 idmapdlog(LOG_ERR, 338c5c4113dSnw141292 "Error opening database %s (%s)", 339c5c4113dSnw141292 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 340c5c4113dSnw141292 sqlite_freemem(errmsg); 341c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 342c5c4113dSnw141292 } 34384decf41Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 34484decf41Sjp151216 tsd->cache_busy.delays = cache_delay_table; 34584decf41Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 34684decf41Sjp151216 sizeof (int); 34784decf41Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 34884decf41Sjp151216 &tsd->cache_busy); 34984decf41Sjp151216 } 35084decf41Sjp151216 *cache = tsd->cache_db; 351c5c4113dSnw141292 return (IDMAP_SUCCESS); 352c5c4113dSnw141292 } 353c5c4113dSnw141292 354c5c4113dSnw141292 #define CACHE_SQL\ 355c5c4113dSnw141292 "CREATE TABLE idmap_cache ("\ 356c5c4113dSnw141292 " sidprefix TEXT,"\ 357c5c4113dSnw141292 " rid INTEGER,"\ 358c5c4113dSnw141292 " windomain TEXT,"\ 359c5c4113dSnw141292 " winname TEXT,"\ 360c5c4113dSnw141292 " pid INTEGER,"\ 361c5c4113dSnw141292 " unixname TEXT,"\ 362c5c4113dSnw141292 " is_user INTEGER,"\ 363c5c4113dSnw141292 " w2u INTEGER,"\ 364c5c4113dSnw141292 " u2w INTEGER,"\ 365c5c4113dSnw141292 " expiration INTEGER"\ 366c5c4113dSnw141292 ");"\ 367c5c4113dSnw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache"\ 368c5c4113dSnw141292 " (sidprefix, rid, w2u);"\ 369c5c4113dSnw141292 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache"\ 370c5c4113dSnw141292 " (pid, is_user, u2w);"\ 371c5c4113dSnw141292 "CREATE TABLE name_cache ("\ 372c5c4113dSnw141292 " sidprefix TEXT,"\ 373c5c4113dSnw141292 " rid INTEGER,"\ 374c5c4113dSnw141292 " name TEXT,"\ 375c5c4113dSnw141292 " domain TEXT,"\ 376c5c4113dSnw141292 " type INTEGER,"\ 377c5c4113dSnw141292 " expiration INTEGER"\ 378c5c4113dSnw141292 ");"\ 379c5c4113dSnw141292 "CREATE UNIQUE INDEX name_cache_sid ON name_cache"\ 380c5c4113dSnw141292 " (sidprefix, rid);" 381c5c4113dSnw141292 382c5c4113dSnw141292 #define DB_SQL\ 383c5c4113dSnw141292 "CREATE TABLE namerules ("\ 384c5c4113dSnw141292 " is_user INTEGER NOT NULL,"\ 385c5c4113dSnw141292 " windomain TEXT,"\ 386c5c4113dSnw141292 " winname TEXT NOT NULL,"\ 387c5c4113dSnw141292 " is_nt4 INTEGER NOT NULL,"\ 388c5c4113dSnw141292 " unixname NOT NULL,"\ 389c5c4113dSnw141292 " w2u_order INTEGER,"\ 390c5c4113dSnw141292 " u2w_order INTEGER"\ 391c5c4113dSnw141292 ");"\ 392c5c4113dSnw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules"\ 393c5c4113dSnw141292 " (winname, windomain, is_user, w2u_order);"\ 394c5c4113dSnw141292 "CREATE UNIQUE INDEX namerules_u2w ON namerules"\ 395c5c4113dSnw141292 " (unixname, is_user, u2w_order);" 396c5c4113dSnw141292 397c5c4113dSnw141292 /* 398c5c4113dSnw141292 * Initialize cache and db 399c5c4113dSnw141292 */ 400c5c4113dSnw141292 int 401c5c4113dSnw141292 init_dbs() { 402c5c4113dSnw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 403c5c4113dSnw141292 if (init_db_instance(IDMAP_DBNAME, DB_SQL, FAIL_IF_CORRUPT, NULL) < 0) 404c5c4113dSnw141292 return (-1); 405c5c4113dSnw141292 406c5c4113dSnw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 407c5c4113dSnw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_SQL, REMOVE_IF_CORRUPT, 408c5c4113dSnw141292 &_idmapdstate.new_eph_db) < 0) 409c5c4113dSnw141292 return (-1); 410c5c4113dSnw141292 411c5c4113dSnw141292 return (0); 412c5c4113dSnw141292 } 413c5c4113dSnw141292 414c5c4113dSnw141292 /* 415c5c4113dSnw141292 * Finalize databases 416c5c4113dSnw141292 */ 417c5c4113dSnw141292 void 418c5c4113dSnw141292 fini_dbs() { 419c5c4113dSnw141292 } 420c5c4113dSnw141292 421c5c4113dSnw141292 /* 422c5c4113dSnw141292 * This table is a listing of status codes that will returned to the 423c5c4113dSnw141292 * client when a SQL command fails with the corresponding error message. 424c5c4113dSnw141292 */ 425c5c4113dSnw141292 static msg_table_t sqlmsgtable[] = { 42662c60062Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 427c5c4113dSnw141292 "columns unixname, is_user, u2w_order are not unique"}, 42862c60062Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 429c5c4113dSnw141292 "columns winname, windomain, is_user, w2u_order are not unique"}, 430c5c4113dSnw141292 {-1, NULL} 431c5c4113dSnw141292 }; 432c5c4113dSnw141292 433c5c4113dSnw141292 /* 434c5c4113dSnw141292 * idmapd's version of string2stat to map SQLite messages to 435c5c4113dSnw141292 * status codes 436c5c4113dSnw141292 */ 437c5c4113dSnw141292 idmap_retcode 438c5c4113dSnw141292 idmapd_string2stat(const char *msg) { 439c5c4113dSnw141292 int i; 440c5c4113dSnw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 441c5c4113dSnw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 442c5c4113dSnw141292 return (sqlmsgtable[i].retcode); 443c5c4113dSnw141292 } 444c5c4113dSnw141292 return (IDMAP_ERR_OTHER); 445c5c4113dSnw141292 } 446c5c4113dSnw141292 447c5c4113dSnw141292 /* 448c5c4113dSnw141292 * Execute the given SQL statment without using any callbacks 449c5c4113dSnw141292 */ 450c5c4113dSnw141292 idmap_retcode 451c5c4113dSnw141292 sql_exec_no_cb(sqlite *db, char *sql) { 452c5c4113dSnw141292 char *errmsg = NULL; 45384decf41Sjp151216 int r; 454c5c4113dSnw141292 idmap_retcode retcode; 455c5c4113dSnw141292 456c5c4113dSnw141292 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 45784decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 458c5c4113dSnw141292 459c5c4113dSnw141292 if (r != SQLITE_OK) { 460c5c4113dSnw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 461c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 462c5c4113dSnw141292 retcode = idmapd_string2stat(errmsg); 46362c60062Sbaban if (errmsg != NULL) 464c5c4113dSnw141292 sqlite_freemem(errmsg); 465c5c4113dSnw141292 return (retcode); 466c5c4113dSnw141292 } 467c5c4113dSnw141292 468c5c4113dSnw141292 return (IDMAP_SUCCESS); 469c5c4113dSnw141292 } 470c5c4113dSnw141292 471c5c4113dSnw141292 /* 472c5c4113dSnw141292 * Generate expression that can be used in WHERE statements. 473c5c4113dSnw141292 * Examples: 474c5c4113dSnw141292 * <prefix> <col> <op> <value> <suffix> 475c5c4113dSnw141292 * "" "unixuser" "=" "foo" "AND" 476c5c4113dSnw141292 */ 477c5c4113dSnw141292 idmap_retcode 478c5c4113dSnw141292 gen_sql_expr_from_utf8str(const char *prefix, const char *col, 479*8e228215Sdm199847 const char *op, char *value, 480c5c4113dSnw141292 const char *suffix, char **out) { 481c5c4113dSnw141292 if (out == NULL) 482c5c4113dSnw141292 return (IDMAP_ERR_ARG); 483c5c4113dSnw141292 484c5c4113dSnw141292 if (value == NULL) 485c5c4113dSnw141292 return (IDMAP_SUCCESS); 486c5c4113dSnw141292 487c5c4113dSnw141292 if (prefix == NULL) 488c5c4113dSnw141292 prefix = ""; 489c5c4113dSnw141292 if (suffix == NULL) 490c5c4113dSnw141292 suffix = ""; 491c5c4113dSnw141292 492c5c4113dSnw141292 *out = sqlite_mprintf("%s %s %s %Q %s", 493*8e228215Sdm199847 prefix, col, op, value, suffix); 494c5c4113dSnw141292 if (*out == NULL) 495c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 496c5c4113dSnw141292 return (IDMAP_SUCCESS); 497c5c4113dSnw141292 } 498c5c4113dSnw141292 499c5c4113dSnw141292 /* 500c5c4113dSnw141292 * Generate and execute SQL statement for LIST RPC calls 501c5c4113dSnw141292 */ 502c5c4113dSnw141292 idmap_retcode 503c5c4113dSnw141292 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 504c5c4113dSnw141292 list_svc_cb cb, void *result) { 505c5c4113dSnw141292 list_cb_data_t cb_data; 506c5c4113dSnw141292 char *errmsg = NULL; 50784decf41Sjp151216 int r; 508c5c4113dSnw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 509c5c4113dSnw141292 510c5c4113dSnw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 511c5c4113dSnw141292 cb_data.result = result; 512c5c4113dSnw141292 cb_data.limit = limit; 513c5c4113dSnw141292 51484decf41Sjp151216 515c5c4113dSnw141292 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 51684decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 517c5c4113dSnw141292 switch (r) { 518c5c4113dSnw141292 case SQLITE_OK: 519c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 52084decf41Sjp151216 break; 52184decf41Sjp151216 522c5c4113dSnw141292 default: 523c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 524c5c4113dSnw141292 idmapdlog(LOG_ERR, 525c5c4113dSnw141292 "Database error during %s (%s)", 526c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 52784decf41Sjp151216 break; 528c5c4113dSnw141292 } 52962c60062Sbaban if (errmsg != NULL) 530c5c4113dSnw141292 sqlite_freemem(errmsg); 531c5c4113dSnw141292 return (retcode); 532c5c4113dSnw141292 } 533c5c4113dSnw141292 534c5c4113dSnw141292 /* 535c5c4113dSnw141292 * This routine is called by callbacks that process the results of 536c5c4113dSnw141292 * LIST RPC calls to validate data and to allocate memory for 537c5c4113dSnw141292 * the result array. 538c5c4113dSnw141292 */ 539c5c4113dSnw141292 idmap_retcode 540c5c4113dSnw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 541c5c4113dSnw141292 int ncol, uchar_t **list, size_t valsize) { 542c5c4113dSnw141292 size_t nsize; 543c5c4113dSnw141292 void *tmplist; 544c5c4113dSnw141292 545c5c4113dSnw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 546c5c4113dSnw141292 return (IDMAP_NEXT); 547c5c4113dSnw141292 548c5c4113dSnw141292 if (argc < ncol || argv == NULL) { 549c5c4113dSnw141292 idmapdlog(LOG_ERR, "Invalid data"); 550c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 551c5c4113dSnw141292 } 552c5c4113dSnw141292 553c5c4113dSnw141292 /* alloc in bulk to reduce number of reallocs */ 554c5c4113dSnw141292 if (cb_data->next >= cb_data->len) { 555c5c4113dSnw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 556c5c4113dSnw141292 tmplist = realloc(*list, nsize); 557c5c4113dSnw141292 if (tmplist == NULL) { 558c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 559c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 560c5c4113dSnw141292 } 561c5c4113dSnw141292 *list = tmplist; 562c5c4113dSnw141292 (void) memset(*list + (cb_data->len * valsize), 0, 563c5c4113dSnw141292 SIZE_INCR * valsize); 564c5c4113dSnw141292 cb_data->len += SIZE_INCR; 565c5c4113dSnw141292 } 566c5c4113dSnw141292 return (IDMAP_SUCCESS); 567c5c4113dSnw141292 } 568c5c4113dSnw141292 569c5c4113dSnw141292 static idmap_retcode 570c5c4113dSnw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 571c5c4113dSnw141292 int direction, int *w2u_order, int *u2w_order) { 572c5c4113dSnw141292 573c5c4113dSnw141292 *w2u_order = 0; 574c5c4113dSnw141292 *u2w_order = 0; 575c5c4113dSnw141292 576c5c4113dSnw141292 /* 577c5c4113dSnw141292 * Windows to UNIX lookup order: 578c5c4113dSnw141292 * 1. winname@domain (or winname) to "" 579c5c4113dSnw141292 * 2. winname@domain (or winname) to unixname 580c5c4113dSnw141292 * 3. winname@* to "" 581c5c4113dSnw141292 * 4. winname@* to unixname 582c5c4113dSnw141292 * 5. *@domain (or *) to * 583c5c4113dSnw141292 * 6. *@domain (or *) to "" 584c5c4113dSnw141292 * 7. *@domain (or *) to unixname 585c5c4113dSnw141292 * 8. *@* to * 586c5c4113dSnw141292 * 9. *@* to "" 587c5c4113dSnw141292 * 10. *@* to unixname 588c5c4113dSnw141292 * 589c5c4113dSnw141292 * winname is a special case of winname@domain when domain is the 590c5c4113dSnw141292 * default domain. Similarly * is a special case of *@domain when 591c5c4113dSnw141292 * domain is the default domain. 592c5c4113dSnw141292 * 593c5c4113dSnw141292 * Note that "" has priority over specific names because "" inhibits 594c5c4113dSnw141292 * mappings and traditionally deny rules always had higher priority. 595c5c4113dSnw141292 */ 596651c0131Sbaban if (direction != IDMAP_DIRECTION_U2W) { 597651c0131Sbaban /* bi-directional or from windows to unix */ 598c5c4113dSnw141292 if (winname == NULL) 599c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 600c5c4113dSnw141292 else if (unixname == NULL) 601c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 602c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 603c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 604c5c4113dSnw141292 else if (*winname == '*' && windomain && *windomain == '*') { 605c5c4113dSnw141292 if (*unixname == '*') 606c5c4113dSnw141292 *w2u_order = 8; 607c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 608c5c4113dSnw141292 *w2u_order = 9; 609c5c4113dSnw141292 else /* unixname == name */ 610c5c4113dSnw141292 *w2u_order = 10; 611c5c4113dSnw141292 } else if (*winname == '*') { 612c5c4113dSnw141292 if (*unixname == '*') 613c5c4113dSnw141292 *w2u_order = 5; 614c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 615c5c4113dSnw141292 *w2u_order = 6; 616c5c4113dSnw141292 else /* name */ 617c5c4113dSnw141292 *w2u_order = 7; 61862c60062Sbaban } else if (windomain != NULL && *windomain == '*') { 619c5c4113dSnw141292 /* winname == name */ 620c5c4113dSnw141292 if (*unixname == '*') 621c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 622c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 623c5c4113dSnw141292 *w2u_order = 3; 624c5c4113dSnw141292 else /* name */ 625c5c4113dSnw141292 *w2u_order = 4; 626c5c4113dSnw141292 } else { 627c5c4113dSnw141292 /* winname == name && windomain == null or name */ 628c5c4113dSnw141292 if (*unixname == '*') 629c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 630c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 631c5c4113dSnw141292 *w2u_order = 1; 632c5c4113dSnw141292 else /* name */ 633c5c4113dSnw141292 *w2u_order = 2; 634c5c4113dSnw141292 } 635c5c4113dSnw141292 } 636c5c4113dSnw141292 637c5c4113dSnw141292 /* 638c5c4113dSnw141292 * 1. unixname to "" 639c5c4113dSnw141292 * 2. unixname to winname@domain (or winname) 640c5c4113dSnw141292 * 3. * to *@domain (or *) 641c5c4113dSnw141292 * 4. * to "" 642c5c4113dSnw141292 * 5. * to winname@domain (or winname) 643c5c4113dSnw141292 */ 644651c0131Sbaban if (direction != IDMAP_DIRECTION_W2U) { 645651c0131Sbaban /* bi-directional or from unix to windows */ 646c5c4113dSnw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 647c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 648c5c4113dSnw141292 else if (winname == NULL) 649c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 65062c60062Sbaban else if (windomain != NULL && *windomain == '*') 651651c0131Sbaban return (IDMAP_ERR_U2W_NAMERULE); 652c5c4113dSnw141292 else if (*unixname == '*') { 653c5c4113dSnw141292 if (*winname == '*') 654c5c4113dSnw141292 *u2w_order = 3; 655c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 656c5c4113dSnw141292 *u2w_order = 4; 657c5c4113dSnw141292 else 658c5c4113dSnw141292 *u2w_order = 5; 659c5c4113dSnw141292 } else { 660c5c4113dSnw141292 if (*winname == '*') 661c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 662c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 663c5c4113dSnw141292 *u2w_order = 1; 664c5c4113dSnw141292 else 665c5c4113dSnw141292 *u2w_order = 2; 666c5c4113dSnw141292 } 667c5c4113dSnw141292 } 668c5c4113dSnw141292 return (IDMAP_SUCCESS); 669c5c4113dSnw141292 } 670c5c4113dSnw141292 671c5c4113dSnw141292 /* 672c5c4113dSnw141292 * Generate and execute SQL statement to add name-based mapping rule 673c5c4113dSnw141292 */ 674c5c4113dSnw141292 idmap_retcode 675c5c4113dSnw141292 add_namerule(sqlite *db, idmap_namerule *rule) { 676c5c4113dSnw141292 char *sql = NULL; 677c5c4113dSnw141292 idmap_stat retcode; 678*8e228215Sdm199847 char *dom = NULL; 679c5c4113dSnw141292 int w2u_order, u2w_order; 680c5c4113dSnw141292 char w2ubuf[11], u2wbuf[11]; 681c5c4113dSnw141292 682*8e228215Sdm199847 retcode = get_namerule_order(rule->winname, rule->windomain, 683*8e228215Sdm199847 rule->unixname, rule->direction, &w2u_order, &u2w_order); 684c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 685c5c4113dSnw141292 goto out; 686c5c4113dSnw141292 687c5c4113dSnw141292 if (w2u_order) 688c5c4113dSnw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 689c5c4113dSnw141292 if (u2w_order) 690c5c4113dSnw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 691c5c4113dSnw141292 69262c60062Sbaban /* 69362c60062Sbaban * For the triggers on namerules table to work correctly: 69462c60062Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 69562c60062Sbaban * 2) Use "" instead of NULL for "no domain" 69662c60062Sbaban */ 69762c60062Sbaban 698*8e228215Sdm199847 if (rule->windomain != NULL) 699*8e228215Sdm199847 dom = rule->windomain; 700*8e228215Sdm199847 else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL) 70162c60062Sbaban == IDMAP_SUCCESS) { 70262c60062Sbaban /* well-known SIDs don't need domain */ 70362c60062Sbaban dom = ""; 70462c60062Sbaban } 705c5c4113dSnw141292 706c5c4113dSnw141292 RDLOCK_CONFIG(); 70762c60062Sbaban if (dom == NULL) { 70862c60062Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain) 709c5c4113dSnw141292 dom = _idmapdstate.cfg->pgcfg.mapping_domain; 710c5c4113dSnw141292 else 711c5c4113dSnw141292 dom = ""; 71262c60062Sbaban } 71384decf41Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 714c5c4113dSnw141292 "(is_user, windomain, winname, is_nt4, " 715c5c4113dSnw141292 "unixname, w2u_order, u2w_order) " 716c5c4113dSnw141292 "VALUES(%d, %Q, %Q, %d, %Q, %q, %q);", 717c5c4113dSnw141292 rule->is_user?1:0, 718c5c4113dSnw141292 dom, 719*8e228215Sdm199847 rule->winname, rule->is_nt4?1:0, 720*8e228215Sdm199847 rule->unixname, 721c5c4113dSnw141292 w2u_order?w2ubuf:NULL, 722c5c4113dSnw141292 u2w_order?u2wbuf:NULL); 723c5c4113dSnw141292 UNLOCK_CONFIG(); 724c5c4113dSnw141292 725c5c4113dSnw141292 if (sql == NULL) { 726c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 727c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 728c5c4113dSnw141292 goto out; 729c5c4113dSnw141292 } 730c5c4113dSnw141292 731c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 732c5c4113dSnw141292 733c5c4113dSnw141292 if (retcode == IDMAP_ERR_OTHER) 734c5c4113dSnw141292 retcode = IDMAP_ERR_CFG; 735c5c4113dSnw141292 736c5c4113dSnw141292 out: 73762c60062Sbaban if (sql != NULL) 738c5c4113dSnw141292 sqlite_freemem(sql); 739c5c4113dSnw141292 return (retcode); 740c5c4113dSnw141292 } 741c5c4113dSnw141292 742c5c4113dSnw141292 /* 743c5c4113dSnw141292 * Flush name-based mapping rules 744c5c4113dSnw141292 */ 745c5c4113dSnw141292 idmap_retcode 746c5c4113dSnw141292 flush_namerules(sqlite *db, bool_t is_user) { 747c5c4113dSnw141292 char *sql = NULL; 748c5c4113dSnw141292 idmap_stat retcode; 749c5c4113dSnw141292 750c5c4113dSnw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 751c5c4113dSnw141292 "is_user = %d;", is_user?1:0); 752c5c4113dSnw141292 753c5c4113dSnw141292 if (sql == NULL) { 754c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 755c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 756c5c4113dSnw141292 } 757c5c4113dSnw141292 758c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 759c5c4113dSnw141292 760c5c4113dSnw141292 sqlite_freemem(sql); 761c5c4113dSnw141292 return (retcode); 762c5c4113dSnw141292 } 763c5c4113dSnw141292 764c5c4113dSnw141292 /* 765c5c4113dSnw141292 * Generate and execute SQL statement to remove a name-based mapping rule 766c5c4113dSnw141292 */ 767c5c4113dSnw141292 idmap_retcode 768c5c4113dSnw141292 rm_namerule(sqlite *db, idmap_namerule *rule) { 769c5c4113dSnw141292 char *sql = NULL; 770c5c4113dSnw141292 idmap_stat retcode; 771c5c4113dSnw141292 char *s_windomain = NULL, *s_winname = NULL; 772c5c4113dSnw141292 char *s_unixname = NULL; 773c5c4113dSnw141292 char buf[80]; 774c5c4113dSnw141292 775*8e228215Sdm199847 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 776*8e228215Sdm199847 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 777c5c4113dSnw141292 return (IDMAP_SUCCESS); 778c5c4113dSnw141292 779c5c4113dSnw141292 if (rule->direction < 0) { 780c5c4113dSnw141292 buf[0] = 0; 781651c0131Sbaban } else if (rule->direction == IDMAP_DIRECTION_BI) { 782c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 783c5c4113dSnw141292 " AND u2w_order > 0"); 784651c0131Sbaban } else if (rule->direction == IDMAP_DIRECTION_W2U) { 785c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 786c5c4113dSnw141292 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 787651c0131Sbaban } else if (rule->direction == IDMAP_DIRECTION_U2W) { 788c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 789c5c4113dSnw141292 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 790c5c4113dSnw141292 } 791c5c4113dSnw141292 792c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 793*8e228215Sdm199847 if (!EMPTY_STRING(rule->windomain)) { 794c5c4113dSnw141292 if (gen_sql_expr_from_utf8str("AND", "windomain", "=", 795*8e228215Sdm199847 rule->windomain, "", &s_windomain) != IDMAP_SUCCESS) 796c5c4113dSnw141292 goto out; 797c5c4113dSnw141292 } 798c5c4113dSnw141292 799*8e228215Sdm199847 if (!EMPTY_STRING(rule->winname)) { 800c5c4113dSnw141292 if (gen_sql_expr_from_utf8str("AND", "winname", "=", 801*8e228215Sdm199847 rule->winname, "", &s_winname) != IDMAP_SUCCESS) 802c5c4113dSnw141292 goto out; 803c5c4113dSnw141292 } 804c5c4113dSnw141292 805*8e228215Sdm199847 if (!EMPTY_STRING(rule->unixname)) { 806c5c4113dSnw141292 if (gen_sql_expr_from_utf8str("AND", "unixname", "=", 807*8e228215Sdm199847 rule->unixname, "", &s_unixname) != IDMAP_SUCCESS) 808c5c4113dSnw141292 goto out; 809c5c4113dSnw141292 } 810c5c4113dSnw141292 811c5c4113dSnw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 812c5c4113dSnw141292 "is_user = %d %s %s %s %s;", 813c5c4113dSnw141292 rule->is_user?1:0, 814c5c4113dSnw141292 s_windomain?s_windomain:"", 815c5c4113dSnw141292 s_winname?s_winname:"", 816c5c4113dSnw141292 s_unixname?s_unixname:"", 817c5c4113dSnw141292 buf); 818c5c4113dSnw141292 819c5c4113dSnw141292 if (sql == NULL) { 820c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 821c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 822c5c4113dSnw141292 goto out; 823c5c4113dSnw141292 } 824c5c4113dSnw141292 825c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 826c5c4113dSnw141292 827c5c4113dSnw141292 out: 82862c60062Sbaban if (s_windomain != NULL) 829c5c4113dSnw141292 sqlite_freemem(s_windomain); 83062c60062Sbaban if (s_winname != NULL) 831c5c4113dSnw141292 sqlite_freemem(s_winname); 83262c60062Sbaban if (s_unixname != NULL) 833c5c4113dSnw141292 sqlite_freemem(s_unixname); 83462c60062Sbaban if (sql != NULL) 835c5c4113dSnw141292 sqlite_freemem(sql); 836c5c4113dSnw141292 return (retcode); 837c5c4113dSnw141292 } 838c5c4113dSnw141292 839c5c4113dSnw141292 /* 840c5c4113dSnw141292 * Compile the given SQL query and step just once. 841c5c4113dSnw141292 * 842c5c4113dSnw141292 * Input: 843c5c4113dSnw141292 * db - db handle 844c5c4113dSnw141292 * sql - SQL statement 845c5c4113dSnw141292 * 846c5c4113dSnw141292 * Output: 847c5c4113dSnw141292 * vm - virtual SQL machine 848c5c4113dSnw141292 * ncol - number of columns in the result 849c5c4113dSnw141292 * values - column values 850c5c4113dSnw141292 * 851c5c4113dSnw141292 * Return values: 852c5c4113dSnw141292 * IDMAP_SUCCESS 853c5c4113dSnw141292 * IDMAP_ERR_NOTFOUND 854c5c4113dSnw141292 * IDMAP_ERR_INTERNAL 855c5c4113dSnw141292 */ 856c5c4113dSnw141292 857c5c4113dSnw141292 static idmap_retcode 858c5c4113dSnw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 859c5c4113dSnw141292 int reqcol, const char ***values) { 860c5c4113dSnw141292 char *errmsg = NULL; 86184decf41Sjp151216 int r; 862c5c4113dSnw141292 86384decf41Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 864c5c4113dSnw141292 idmapdlog(LOG_ERR, 865c5c4113dSnw141292 "Database error during %s (%s)", 866c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 867c5c4113dSnw141292 sqlite_freemem(errmsg); 868c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 869c5c4113dSnw141292 } 870c5c4113dSnw141292 871c5c4113dSnw141292 r = sqlite_step(*vm, ncol, values, NULL); 87284decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 873c5c4113dSnw141292 87484decf41Sjp151216 if (r == SQLITE_ROW) { 87562c60062Sbaban if (ncol != NULL && *ncol < reqcol) { 876c5c4113dSnw141292 (void) sqlite_finalize(*vm, NULL); 877c5c4113dSnw141292 *vm = NULL; 878c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 879c5c4113dSnw141292 } 880c5c4113dSnw141292 /* Caller will call finalize after using the results */ 881c5c4113dSnw141292 return (IDMAP_SUCCESS); 882c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 883c5c4113dSnw141292 (void) sqlite_finalize(*vm, NULL); 884c5c4113dSnw141292 *vm = NULL; 885c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 886c5c4113dSnw141292 } 887c5c4113dSnw141292 888c5c4113dSnw141292 (void) sqlite_finalize(*vm, &errmsg); 889c5c4113dSnw141292 *vm = NULL; 890c5c4113dSnw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 891c5c4113dSnw141292 sql, CHECK_NULL(errmsg)); 892c5c4113dSnw141292 sqlite_freemem(errmsg); 893c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 894c5c4113dSnw141292 } 895c5c4113dSnw141292 89662c60062Sbaban /* 89762c60062Sbaban * Table for well-known SIDs. 89862c60062Sbaban * 89962c60062Sbaban * Background: 90062c60062Sbaban * 90162c60062Sbaban * These well-known principals are stored (as of Windows Server 2003) under: 90262c60062Sbaban * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 90362c60062Sbaban * They belong to objectClass "foreignSecurityPrincipal". They don't have 90462c60062Sbaban * "samAccountName" nor "userPrincipalName" attributes. Their names are 90562c60062Sbaban * available in "cn" and "name" attributes. Some of these principals have a 90662c60062Sbaban * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 90762c60062Sbaban * these duplicate entries have the stringified SID in the "name" and "cn" 90862c60062Sbaban * attributes instead of the actual name. 90962c60062Sbaban * 91062c60062Sbaban * These principals remain constant across all operating systems. Using 91162c60062Sbaban * a hard-coded table here improves performance and avoids additional 91262c60062Sbaban * complexity in the AD lookup code in adutils.c 91362c60062Sbaban * 91462c60062Sbaban * Currently we don't support localization of well-known SID names, 91562c60062Sbaban * unlike Windows. 91662c60062Sbaban * 91762c60062Sbaban * Note that other well-known SIDs (i.e. S-1-5-<domain>-<w-k RID> and 91862c60062Sbaban * S-1-5-32-<w-k RID>) are not stored here because AD does have normal 91962c60062Sbaban * user/group objects for these objects and can be looked up using the 92062c60062Sbaban * existing AD lookup code. 92162c60062Sbaban */ 92262c60062Sbaban static wksids_table_t wksids[] = { 92362c60062Sbaban {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 92462c60062Sbaban {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 92562c60062Sbaban {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 92662c60062Sbaban {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 92762c60062Sbaban {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 92862c60062Sbaban {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 92962c60062Sbaban {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 93062c60062Sbaban {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 93162c60062Sbaban {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 93262c60062Sbaban {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 93362c60062Sbaban {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 93462c60062Sbaban {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 93562c60062Sbaban {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 93662c60062Sbaban {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 93762c60062Sbaban {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 93862c60062Sbaban {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 93962c60062Sbaban {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 94062c60062Sbaban {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 94162c60062Sbaban {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 94262c60062Sbaban {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 94362c60062Sbaban {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 94462c60062Sbaban {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 94562c60062Sbaban {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 94662c60062Sbaban {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 94762c60062Sbaban {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 94862c60062Sbaban {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 94962c60062Sbaban {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 950c5c4113dSnw141292 }; 951c5c4113dSnw141292 952c5c4113dSnw141292 static idmap_retcode 953c5c4113dSnw141292 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) { 954c5c4113dSnw141292 int i; 95562c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 95662c60062Sbaban if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 95762c60062Sbaban (strcasecmp(wksids[i].sidprefix, 95862c60062Sbaban req->id1.idmap_id_u.sid.prefix) == 0)) { 95962c60062Sbaban 96062c60062Sbaban if (wksids[i].pid == SENTINEL_PID) 96162c60062Sbaban /* Not mapped, break */ 96262c60062Sbaban break; 96362c60062Sbaban else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 96462c60062Sbaban continue; 96562c60062Sbaban 966c5c4113dSnw141292 switch (req->id2.idtype) { 967c5c4113dSnw141292 case IDMAP_UID: 96862c60062Sbaban if (wksids[i].is_user == 0) 96962c60062Sbaban continue; 97062c60062Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 97162c60062Sbaban res->direction = wksids[i].direction; 972c5c4113dSnw141292 return (IDMAP_SUCCESS); 973c5c4113dSnw141292 case IDMAP_GID: 97462c60062Sbaban if (wksids[i].is_user == 1) 97562c60062Sbaban continue; 97662c60062Sbaban res->id.idmap_id_u.gid = wksids[i].pid; 97762c60062Sbaban res->direction = wksids[i].direction; 978c5c4113dSnw141292 return (IDMAP_SUCCESS); 979c5c4113dSnw141292 case IDMAP_POSIXID: 98062c60062Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 98162c60062Sbaban res->id.idtype = (!wksids[i].is_user)? 982c5c4113dSnw141292 IDMAP_GID:IDMAP_UID; 98362c60062Sbaban res->direction = wksids[i].direction; 984c5c4113dSnw141292 return (IDMAP_SUCCESS); 985c5c4113dSnw141292 default: 986c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 987c5c4113dSnw141292 } 988c5c4113dSnw141292 } 989c5c4113dSnw141292 } 990c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 991c5c4113dSnw141292 } 992c5c4113dSnw141292 993c5c4113dSnw141292 static idmap_retcode 994c5c4113dSnw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) { 995c5c4113dSnw141292 int i; 99662c60062Sbaban if (req->id2.idtype != IDMAP_SID) 99762c60062Sbaban return (IDMAP_ERR_NOTSUPPORTED); 99862c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 99962c60062Sbaban if (wksids[i].pid == req->id1.idmap_id_u.uid && 100062c60062Sbaban wksids[i].is_user == is_user && 100162c60062Sbaban wksids[i].direction != IDMAP_DIRECTION_W2U) { 100262c60062Sbaban res->id.idmap_id_u.sid.rid = wksids[i].rid; 1003c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = 100462c60062Sbaban strdup(wksids[i].sidprefix); 1005c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 1006c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1007c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 1008c5c4113dSnw141292 } 100962c60062Sbaban res->direction = wksids[i].direction; 1010c5c4113dSnw141292 return (IDMAP_SUCCESS); 1011c5c4113dSnw141292 } 1012c5c4113dSnw141292 } 101362c60062Sbaban return (IDMAP_ERR_NOTFOUND); 101462c60062Sbaban } 101562c60062Sbaban 101662c60062Sbaban static idmap_retcode 101762c60062Sbaban lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 101862c60062Sbaban int *type) { 101962c60062Sbaban int i; 102062c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 102162c60062Sbaban if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 102262c60062Sbaban wksids[i].rid == rid) { 102362c60062Sbaban if ((*name = strdup(wksids[i].winname)) == NULL) { 102462c60062Sbaban idmapdlog(LOG_ERR, "Out of memory"); 102562c60062Sbaban return (IDMAP_ERR_MEMORY); 102662c60062Sbaban } 102762c60062Sbaban *type = (wksids[i].is_user)? 102862c60062Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 102962c60062Sbaban return (IDMAP_SUCCESS); 103062c60062Sbaban } 103162c60062Sbaban } 103262c60062Sbaban return (IDMAP_ERR_NOTFOUND); 103362c60062Sbaban } 103462c60062Sbaban 103562c60062Sbaban static idmap_retcode 103662c60062Sbaban lookup_wksids_name2sid(const char *name, char **sidprefix, idmap_rid_t *rid, 103762c60062Sbaban int *type) { 103862c60062Sbaban int i; 103962c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 104062c60062Sbaban if (strcasecmp(wksids[i].winname, name) == 0) { 104162c60062Sbaban if (sidprefix != NULL && (*sidprefix = 104262c60062Sbaban strdup(wksids[i].sidprefix)) == NULL) { 104362c60062Sbaban idmapdlog(LOG_ERR, "Out of memory"); 104462c60062Sbaban return (IDMAP_ERR_MEMORY); 104562c60062Sbaban } 104662c60062Sbaban if (type != NULL) 104762c60062Sbaban *type = (wksids[i].is_user)? 104862c60062Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 104962c60062Sbaban if (rid != NULL) 105062c60062Sbaban *rid = wksids[i].rid; 105162c60062Sbaban return (IDMAP_SUCCESS); 105262c60062Sbaban } 1053c5c4113dSnw141292 } 1054c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1055c5c4113dSnw141292 } 1056c5c4113dSnw141292 1057c5c4113dSnw141292 static idmap_retcode 1058c5c4113dSnw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 1059c5c4113dSnw141292 char *end; 1060c5c4113dSnw141292 char *sql = NULL; 1061c5c4113dSnw141292 const char **values; 1062c5c4113dSnw141292 sqlite_vm *vm = NULL; 1063c5c4113dSnw141292 int ncol, is_user; 1064c5c4113dSnw141292 uid_t pid; 1065c5c4113dSnw141292 time_t curtime, exp; 1066c5c4113dSnw141292 idmap_retcode retcode; 1067c5c4113dSnw141292 1068c5c4113dSnw141292 /* Current time */ 1069c5c4113dSnw141292 errno = 0; 1070c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 1071c5c4113dSnw141292 idmapdlog(LOG_ERR, 1072c5c4113dSnw141292 "Failed to get current time (%s)", 1073c5c4113dSnw141292 strerror(errno)); 1074c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1075c5c4113dSnw141292 goto out; 1076c5c4113dSnw141292 } 1077c5c4113dSnw141292 1078c5c4113dSnw141292 /* SQL to lookup the cache */ 1079c5c4113dSnw141292 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 1080c5c4113dSnw141292 "FROM idmap_cache WHERE " 1081c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 1082c5c4113dSnw141292 "(pid >= 2147483648 OR " 1083c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 1084c5c4113dSnw141292 "expiration > %d));", 1085c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 1086c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 1087c5c4113dSnw141292 curtime); 1088c5c4113dSnw141292 if (sql == NULL) { 1089c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1090c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1091c5c4113dSnw141292 goto out; 1092c5c4113dSnw141292 } 1093c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 1094c5c4113dSnw141292 sqlite_freemem(sql); 1095c5c4113dSnw141292 1096c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 1097c5c4113dSnw141292 goto out; 1098c5c4113dSnw141292 } else if (retcode == IDMAP_SUCCESS) { 1099c5c4113dSnw141292 /* sanity checks */ 1100c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 1101c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 1102c5c4113dSnw141292 goto out; 1103c5c4113dSnw141292 } 1104c5c4113dSnw141292 1105c5c4113dSnw141292 pid = strtoul(values[0], &end, 10); 1106c5c4113dSnw141292 is_user = strncmp(values[1], "0", 2)?1:0; 1107c5c4113dSnw141292 1108c5c4113dSnw141292 /* 1109c5c4113dSnw141292 * We may have an expired ephemeral mapping. Consider 1110c5c4113dSnw141292 * the expired entry as valid if we are not going to 1111c5c4113dSnw141292 * perform name-based mapping. But do not renew the 1112c5c4113dSnw141292 * expiration. 1113c5c4113dSnw141292 * If we will be doing name-based mapping then store the 1114c5c4113dSnw141292 * ephemeral pid in the result so that we can use it 1115c5c4113dSnw141292 * if we end up doing dynamic mapping again. 1116c5c4113dSnw141292 */ 1117c5c4113dSnw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 1118c5c4113dSnw141292 !AVOID_NAMESERVICE(req)) { 111962c60062Sbaban if (IS_EPHEMERAL(pid) && values[2] != NULL) { 1120c5c4113dSnw141292 exp = strtoll(values[2], &end, 10); 1121c5c4113dSnw141292 if (exp && exp <= curtime) { 1122c5c4113dSnw141292 /* Store the ephemeral pid */ 1123c5c4113dSnw141292 res->id.idmap_id_u.uid = pid; 1124c5c4113dSnw141292 res->id.idtype = is_user? 1125c5c4113dSnw141292 IDMAP_UID:IDMAP_GID; 1126651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 1127c5c4113dSnw141292 req->direction |= is_user? 1128c5c4113dSnw141292 _IDMAP_F_EXP_EPH_UID: 1129c5c4113dSnw141292 _IDMAP_F_EXP_EPH_GID; 1130c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 1131c5c4113dSnw141292 goto out; 1132c5c4113dSnw141292 } 1133c5c4113dSnw141292 } 1134c5c4113dSnw141292 } 1135c5c4113dSnw141292 1136c5c4113dSnw141292 switch (req->id2.idtype) { 1137c5c4113dSnw141292 case IDMAP_UID: 1138c5c4113dSnw141292 if (!is_user) 1139c5c4113dSnw141292 retcode = IDMAP_ERR_NOTUSER; 1140c5c4113dSnw141292 else 1141c5c4113dSnw141292 res->id.idmap_id_u.uid = pid; 1142c5c4113dSnw141292 break; 1143c5c4113dSnw141292 case IDMAP_GID: 1144c5c4113dSnw141292 if (is_user) 1145c5c4113dSnw141292 retcode = IDMAP_ERR_NOTGROUP; 1146c5c4113dSnw141292 else 1147c5c4113dSnw141292 res->id.idmap_id_u.gid = pid; 1148c5c4113dSnw141292 break; 1149c5c4113dSnw141292 case IDMAP_POSIXID: 1150c5c4113dSnw141292 res->id.idmap_id_u.uid = pid; 1151c5c4113dSnw141292 res->id.idtype = (is_user)?IDMAP_UID:IDMAP_GID; 1152c5c4113dSnw141292 break; 1153c5c4113dSnw141292 default: 1154c5c4113dSnw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 1155c5c4113dSnw141292 break; 1156c5c4113dSnw141292 } 1157c5c4113dSnw141292 } 1158c5c4113dSnw141292 1159c5c4113dSnw141292 out: 1160c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 116162c60062Sbaban if (values[4] != NULL) 1162c5c4113dSnw141292 res->direction = 1163651c0131Sbaban (strtol(values[4], &end, 10) == 0)? 1164651c0131Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 1165c5c4113dSnw141292 else 1166651c0131Sbaban res->direction = IDMAP_DIRECTION_W2U; 1167c5c4113dSnw141292 116862c60062Sbaban if (values[3] != NULL) { 1169*8e228215Sdm199847 req->id2name = strdup(values[3]); 1170*8e228215Sdm199847 if (req->id2name == NULL) { 1171c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1172c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1173c5c4113dSnw141292 } 1174c5c4113dSnw141292 } 1175c5c4113dSnw141292 } 117662c60062Sbaban if (vm != NULL) 1177c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1178c5c4113dSnw141292 return (retcode); 1179c5c4113dSnw141292 } 1180c5c4113dSnw141292 1181c5c4113dSnw141292 static idmap_retcode 118262c60062Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 1183c5c4113dSnw141292 char **name, char **domain, int *type) { 1184c5c4113dSnw141292 char *end; 1185c5c4113dSnw141292 char *sql = NULL; 1186c5c4113dSnw141292 const char **values; 1187c5c4113dSnw141292 sqlite_vm *vm = NULL; 1188c5c4113dSnw141292 int ncol; 1189c5c4113dSnw141292 time_t curtime; 1190c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 1191c5c4113dSnw141292 1192c5c4113dSnw141292 /* Get current time */ 1193c5c4113dSnw141292 errno = 0; 1194c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 1195c5c4113dSnw141292 idmapdlog(LOG_ERR, 1196c5c4113dSnw141292 "Failed to get current time (%s)", 1197c5c4113dSnw141292 strerror(errno)); 1198c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1199c5c4113dSnw141292 goto out; 1200c5c4113dSnw141292 } 1201c5c4113dSnw141292 1202c5c4113dSnw141292 /* SQL to lookup the cache */ 1203c5c4113dSnw141292 sql = sqlite_mprintf("SELECT name, domain, type FROM name_cache WHERE " 1204c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND " 1205c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 1206c5c4113dSnw141292 "expiration > %d);", 1207c5c4113dSnw141292 sidprefix, rid, curtime); 1208c5c4113dSnw141292 if (sql == NULL) { 1209c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1210c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1211c5c4113dSnw141292 goto out; 1212c5c4113dSnw141292 } 1213c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 1214c5c4113dSnw141292 sqlite_freemem(sql); 1215c5c4113dSnw141292 1216c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 121762c60062Sbaban if (type != NULL) { 1218c5c4113dSnw141292 if (values[2] == NULL) { 1219c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 1220c5c4113dSnw141292 goto out; 1221c5c4113dSnw141292 } 1222c5c4113dSnw141292 *type = strtol(values[2], &end, 10); 1223c5c4113dSnw141292 } 1224c5c4113dSnw141292 122562c60062Sbaban if (name != NULL && values[0] != NULL) { 1226c5c4113dSnw141292 if ((*name = strdup(values[0])) == NULL) { 1227c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1228c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1229c5c4113dSnw141292 goto out; 1230c5c4113dSnw141292 } 1231c5c4113dSnw141292 } 1232c5c4113dSnw141292 123362c60062Sbaban if (domain != NULL && values[1] != NULL) { 1234c5c4113dSnw141292 if ((*domain = strdup(values[1])) == NULL) { 123562c60062Sbaban if (name != NULL && *name) { 1236c5c4113dSnw141292 free(*name); 1237c5c4113dSnw141292 *name = NULL; 1238c5c4113dSnw141292 } 1239c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1240c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1241c5c4113dSnw141292 goto out; 1242c5c4113dSnw141292 } 1243c5c4113dSnw141292 } 1244c5c4113dSnw141292 } 1245c5c4113dSnw141292 1246c5c4113dSnw141292 out: 124762c60062Sbaban if (vm != NULL) 1248c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1249c5c4113dSnw141292 return (retcode); 1250c5c4113dSnw141292 } 1251c5c4113dSnw141292 1252c5c4113dSnw141292 static idmap_retcode 1253c5c4113dSnw141292 verify_type(idmap_id_type idtype, int type, idmap_id_res *res) { 1254c5c4113dSnw141292 switch (idtype) { 1255c5c4113dSnw141292 case IDMAP_UID: 1256c5c4113dSnw141292 if (type != _IDMAP_T_USER) 1257c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 1258c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1259c5c4113dSnw141292 break; 1260c5c4113dSnw141292 case IDMAP_GID: 1261c5c4113dSnw141292 if (type != _IDMAP_T_GROUP) 1262c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 1263c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1264c5c4113dSnw141292 break; 1265c5c4113dSnw141292 case IDMAP_POSIXID: 1266c5c4113dSnw141292 if (type == _IDMAP_T_USER) 1267c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1268c5c4113dSnw141292 else if (type == _IDMAP_T_GROUP) 1269c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1270c5c4113dSnw141292 else 1271c5c4113dSnw141292 return (IDMAP_ERR_SID); 1272c5c4113dSnw141292 break; 1273c5c4113dSnw141292 default: 1274c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1275c5c4113dSnw141292 } 1276c5c4113dSnw141292 return (IDMAP_SUCCESS); 1277c5c4113dSnw141292 } 1278c5c4113dSnw141292 1279c5c4113dSnw141292 /* 128062c60062Sbaban * Lookup sid to name locally 1281c5c4113dSnw141292 */ 1282c5c4113dSnw141292 static idmap_retcode 128362c60062Sbaban lookup_local_sid2name(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 1284c5c4113dSnw141292 int type = -1; 1285c5c4113dSnw141292 idmap_retcode retcode; 1286c5c4113dSnw141292 char *sidprefix; 1287c5c4113dSnw141292 idmap_rid_t rid; 1288c5c4113dSnw141292 char *name = NULL, *domain = NULL; 1289c5c4113dSnw141292 1290c5c4113dSnw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 1291c5c4113dSnw141292 rid = req->id1.idmap_id_u.sid.rid; 1292c5c4113dSnw141292 129362c60062Sbaban /* Lookup sids to name in well-known sids table */ 129462c60062Sbaban retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 129562c60062Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 129662c60062Sbaban goto out; 129762c60062Sbaban 1298c5c4113dSnw141292 /* Lookup sid to name in cache */ 129962c60062Sbaban retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 1300c5c4113dSnw141292 &domain, &type); 1301c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 1302c5c4113dSnw141292 goto out; 1303c5c4113dSnw141292 130462c60062Sbaban out: 130562c60062Sbaban if (retcode == IDMAP_SUCCESS) { 1306c5c4113dSnw141292 /* Verify that the sid type matches the request */ 1307c5c4113dSnw141292 retcode = verify_type(req->id2.idtype, type, res); 1308c5c4113dSnw141292 1309c5c4113dSnw141292 /* update state in 'req' */ 1310*8e228215Sdm199847 if (name != NULL) 1311*8e228215Sdm199847 req->id1name = name; 1312*8e228215Sdm199847 if (domain != NULL) 1313*8e228215Sdm199847 req->id1domain = domain; 1314c5c4113dSnw141292 } else { 131562c60062Sbaban if (name != NULL) 1316c5c4113dSnw141292 free(name); 131762c60062Sbaban if (domain != NULL) 1318c5c4113dSnw141292 free(domain); 1319c5c4113dSnw141292 } 1320c5c4113dSnw141292 return (retcode); 1321c5c4113dSnw141292 } 1322c5c4113dSnw141292 1323c5c4113dSnw141292 idmap_retcode 1324c5c4113dSnw141292 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 1325c5c4113dSnw141292 idmap_ids_res *result) { 1326c5c4113dSnw141292 idmap_retcode retcode; 1327c5c4113dSnw141292 int ret, i; 1328c5c4113dSnw141292 int retries = 0; 1329c5c4113dSnw141292 idmap_mapping *req; 1330c5c4113dSnw141292 idmap_id_res *res; 1331c5c4113dSnw141292 1332c5c4113dSnw141292 if (state->ad_nqueries == 0) 1333c5c4113dSnw141292 return (IDMAP_SUCCESS); 1334c5c4113dSnw141292 1335c5c4113dSnw141292 retry: 1336c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 1337c5c4113dSnw141292 &state->ad_lookup); 1338c5c4113dSnw141292 if (ret != 0) { 1339c5c4113dSnw141292 idmapdlog(LOG_ERR, 1340c5c4113dSnw141292 "Failed to create sid2name batch for AD lookup"); 1341c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1342c5c4113dSnw141292 } 1343c5c4113dSnw141292 1344c5c4113dSnw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 1345c5c4113dSnw141292 req = &batch->idmap_mapping_batch_val[i]; 1346c5c4113dSnw141292 res = &result->ids.ids_val[i]; 1347c5c4113dSnw141292 134862c60062Sbaban if (req->id1.idtype == IDMAP_SID && 134962c60062Sbaban req->direction & _IDMAP_F_S2N_AD) { 1350c5c4113dSnw141292 if (retries == 0) 1351c5c4113dSnw141292 res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 1352c5c4113dSnw141292 else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 1353c5c4113dSnw141292 continue; 1354c5c4113dSnw141292 retcode = idmap_sid2name_batch_add1( 1355c5c4113dSnw141292 state->ad_lookup, 1356c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 1357c5c4113dSnw141292 &req->id1.idmap_id_u.sid.rid, 1358*8e228215Sdm199847 &req->id1name, 1359*8e228215Sdm199847 &req->id1domain, 1360c5c4113dSnw141292 (int *)&res->id.idtype, 1361c5c4113dSnw141292 &res->retcode); 1362c5c4113dSnw141292 1363c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1364c5c4113dSnw141292 break; 1365c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 1366c5c4113dSnw141292 goto out; 1367c5c4113dSnw141292 } 1368c5c4113dSnw141292 } 1369c5c4113dSnw141292 1370c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 137184decf41Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 1372c5c4113dSnw141292 else 1373c5c4113dSnw141292 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 1374c5c4113dSnw141292 1375c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 1376c5c4113dSnw141292 goto retry; 1377c5c4113dSnw141292 1378c5c4113dSnw141292 return (retcode); 1379c5c4113dSnw141292 1380c5c4113dSnw141292 out: 1381c5c4113dSnw141292 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 138284decf41Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 1383c5c4113dSnw141292 return (retcode); 1384c5c4113dSnw141292 } 1385c5c4113dSnw141292 1386c5c4113dSnw141292 idmap_retcode 1387c5c4113dSnw141292 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 1388c5c4113dSnw141292 idmap_id_res *res) { 1389c5c4113dSnw141292 idmap_retcode retcode; 1390c5c4113dSnw141292 1391c5c4113dSnw141292 /* 1392c5c4113dSnw141292 * The req->direction field is used to maintain state of the 1393c5c4113dSnw141292 * sid2pid request. 1394c5c4113dSnw141292 */ 1395c5c4113dSnw141292 req->direction = _IDMAP_F_DONE; 1396c5c4113dSnw141292 1397c5c4113dSnw141292 if (req->id1.idmap_id_u.sid.prefix == NULL) { 1398c5c4113dSnw141292 retcode = IDMAP_ERR_SID; 1399c5c4113dSnw141292 goto out; 1400c5c4113dSnw141292 } 1401c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 1402c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 1403c5c4113dSnw141292 140462c60062Sbaban /* Lookup well-known sid to pid mapping */ 1405c5c4113dSnw141292 retcode = lookup_wksids_sid2pid(req, res); 1406c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 1407c5c4113dSnw141292 goto out; 1408c5c4113dSnw141292 1409c5c4113dSnw141292 /* Lookup sid to pid in cache */ 1410c5c4113dSnw141292 retcode = lookup_cache_sid2pid(cache, req, res); 1411c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 1412c5c4113dSnw141292 goto out; 1413c5c4113dSnw141292 1414c5c4113dSnw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 1415c5c4113dSnw141292 res->id.idmap_id_u.uid = SENTINEL_PID; 1416c5c4113dSnw141292 goto out; 1417c5c4113dSnw141292 } 1418c5c4113dSnw141292 1419c5c4113dSnw141292 /* 1420c5c4113dSnw141292 * Failed to find non-expired entry in cache. Tell the caller 1421c5c4113dSnw141292 * that we are not done yet. 1422c5c4113dSnw141292 */ 1423c5c4113dSnw141292 state->sid2pid_done = FALSE; 1424c5c4113dSnw141292 1425c5c4113dSnw141292 /* 1426c5c4113dSnw141292 * Our next step is name-based mapping. To lookup name-based 1427c5c4113dSnw141292 * mapping rules, we need the windows name and domain-name 1428c5c4113dSnw141292 * associated with the SID. 1429c5c4113dSnw141292 */ 1430c5c4113dSnw141292 1431c5c4113dSnw141292 /* 1432c5c4113dSnw141292 * Check if we already have the name (i.e name2pid lookups) 1433c5c4113dSnw141292 */ 1434*8e228215Sdm199847 if (req->id1name != NULL && 1435*8e228215Sdm199847 req->id1domain != NULL) { 1436c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 1437c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_CACHE; 1438c5c4113dSnw141292 goto out; 1439c5c4113dSnw141292 } 1440c5c4113dSnw141292 144162c60062Sbaban /* Lookup sid to winname@domain locally first */ 144262c60062Sbaban retcode = lookup_local_sid2name(cache, req, res); 144362c60062Sbaban if (retcode == IDMAP_SUCCESS) { 144462c60062Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 144562c60062Sbaban } else if (retcode == IDMAP_ERR_NOTFOUND) { 1446c5c4113dSnw141292 /* Batch sid to name AD lookup request */ 1447c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 1448c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_AD; 1449c5c4113dSnw141292 state->ad_nqueries++; 1450c5c4113dSnw141292 goto out; 1451c5c4113dSnw141292 } 1452c5c4113dSnw141292 1453c5c4113dSnw141292 1454c5c4113dSnw141292 out: 1455c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 1456c5c4113dSnw141292 return (retcode); 1457c5c4113dSnw141292 } 1458c5c4113dSnw141292 1459c5c4113dSnw141292 /* 1460c5c4113dSnw141292 * Generate SID using the following convention 1461c5c4113dSnw141292 * <machine-sid-prefix>-<1000 + uid> 1462c5c4113dSnw141292 * <machine-sid-prefix>-<2^31 + gid> 1463c5c4113dSnw141292 */ 1464c5c4113dSnw141292 static idmap_retcode 1465c5c4113dSnw141292 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) { 1466c5c4113dSnw141292 146762c60062Sbaban if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 1468c5c4113dSnw141292 /* Skip 1000 UIDs */ 1469c5c4113dSnw141292 if (is_user && req->id1.idmap_id_u.uid > 1470c5c4113dSnw141292 (INT32_MAX - LOCALRID_MIN)) 147162c60062Sbaban return (IDMAP_ERR_NOMAPPING); 1472c5c4113dSnw141292 1473c5c4113dSnw141292 RDLOCK_CONFIG(); 1474c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = 1475c5c4113dSnw141292 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 1476c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 1477c5c4113dSnw141292 UNLOCK_CONFIG(); 1478c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1479c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 1480c5c4113dSnw141292 } 1481c5c4113dSnw141292 UNLOCK_CONFIG(); 1482c5c4113dSnw141292 res->id.idmap_id_u.sid.rid = 1483c5c4113dSnw141292 (is_user)?req->id1.idmap_id_u.uid + LOCALRID_MIN: 1484c5c4113dSnw141292 req->id1.idmap_id_u.gid + INT32_MAX + 1; 1485651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 1486c5c4113dSnw141292 1487c5c4113dSnw141292 /* 1488c5c4113dSnw141292 * Don't update name_cache because local sids don't have 1489c5c4113dSnw141292 * valid windows names. 1490c5c4113dSnw141292 * We mark the entry as being found in the namecache so that 1491c5c4113dSnw141292 * the cache update routine doesn't update namecache. 1492c5c4113dSnw141292 */ 1493c5c4113dSnw141292 req->direction = _IDMAP_F_S2N_CACHE; 1494947c7bc0Sbaban return (IDMAP_SUCCESS); 1495c5c4113dSnw141292 } 1496c5c4113dSnw141292 149762c60062Sbaban return (IDMAP_ERR_NOMAPPING); 1498c5c4113dSnw141292 } 1499c5c4113dSnw141292 1500c5c4113dSnw141292 static idmap_retcode 1501c5c4113dSnw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) { 1502c5c4113dSnw141292 char *sidprefix; 1503c5c4113dSnw141292 uint32_t rid; 1504c5c4113dSnw141292 int s; 1505c5c4113dSnw141292 1506c5c4113dSnw141292 /* 1507c5c4113dSnw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 1508c5c4113dSnw141292 * GID = last RID - 2^31. 1509c5c4113dSnw141292 */ 1510c5c4113dSnw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 1511c5c4113dSnw141292 rid = req->id1.idmap_id_u.sid.rid; 1512c5c4113dSnw141292 1513c5c4113dSnw141292 RDLOCK_CONFIG(); 1514c5c4113dSnw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid)? 1515c5c4113dSnw141292 strcasecmp(sidprefix, 1516c5c4113dSnw141292 _idmapdstate.cfg->pgcfg.machine_sid):1; 1517c5c4113dSnw141292 UNLOCK_CONFIG(); 1518c5c4113dSnw141292 1519c5c4113dSnw141292 if (s == 0) { 1520c5c4113dSnw141292 switch (req->id2.idtype) { 1521c5c4113dSnw141292 case IDMAP_UID: 1522c5c4113dSnw141292 if (rid > INT32_MAX) { 1523c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 1524c5c4113dSnw141292 } else if (rid < LOCALRID_MIN) { 1525c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1526c5c4113dSnw141292 } 1527c5c4113dSnw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1528c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1529c5c4113dSnw141292 break; 1530c5c4113dSnw141292 case IDMAP_GID: 1531c5c4113dSnw141292 if (rid <= INT32_MAX) { 1532c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 1533c5c4113dSnw141292 } 1534c5c4113dSnw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 1535c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1536c5c4113dSnw141292 break; 1537c5c4113dSnw141292 case IDMAP_POSIXID: 1538c5c4113dSnw141292 if (rid > INT32_MAX) { 1539c5c4113dSnw141292 res->id.idmap_id_u.gid = 1540c5c4113dSnw141292 rid - INT32_MAX - 1; 1541c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1542c5c4113dSnw141292 } else if (rid < LOCALRID_MIN) { 1543c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1544c5c4113dSnw141292 } else { 1545c5c4113dSnw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1546c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1547c5c4113dSnw141292 } 1548c5c4113dSnw141292 break; 1549c5c4113dSnw141292 default: 1550c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1551c5c4113dSnw141292 } 1552c5c4113dSnw141292 return (IDMAP_SUCCESS); 1553c5c4113dSnw141292 } 1554c5c4113dSnw141292 1555c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1556c5c4113dSnw141292 } 1557c5c4113dSnw141292 1558c5c4113dSnw141292 static idmap_retcode 1559c5c4113dSnw141292 ns_lookup_byname(int is_user, const char *name, idmap_id_res *res) { 1560c5c4113dSnw141292 struct passwd pwd; 1561c5c4113dSnw141292 struct group grp; 1562c5c4113dSnw141292 char buf[1024]; 1563c5c4113dSnw141292 int errnum; 1564c5c4113dSnw141292 const char *me = "ns_lookup_byname"; 1565c5c4113dSnw141292 1566c5c4113dSnw141292 if (is_user) { 1567c5c4113dSnw141292 if (getpwnam_r(name, &pwd, buf, sizeof (buf)) == NULL) { 1568c5c4113dSnw141292 errnum = errno; 1569c5c4113dSnw141292 idmapdlog(LOG_WARNING, 1570c5c4113dSnw141292 "%s: getpwnam_r(%s) failed (%s).", 1571c5c4113dSnw141292 me, name, 1572c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 1573c5c4113dSnw141292 if (errnum == 0) 1574c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1575c5c4113dSnw141292 else 1576c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1577c5c4113dSnw141292 } 1578c5c4113dSnw141292 res->id.idmap_id_u.uid = pwd.pw_uid; 1579c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1580c5c4113dSnw141292 } else { 1581c5c4113dSnw141292 if (getgrnam_r(name, &grp, buf, sizeof (buf)) == NULL) { 1582c5c4113dSnw141292 errnum = errno; 1583c5c4113dSnw141292 idmapdlog(LOG_WARNING, 1584c5c4113dSnw141292 "%s: getgrnam_r(%s) failed (%s).", 1585c5c4113dSnw141292 me, name, 1586c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 1587c5c4113dSnw141292 if (errnum == 0) 1588c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1589c5c4113dSnw141292 else 1590c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1591c5c4113dSnw141292 } 1592c5c4113dSnw141292 res->id.idmap_id_u.gid = grp.gr_gid; 1593c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1594c5c4113dSnw141292 } 1595c5c4113dSnw141292 return (IDMAP_SUCCESS); 1596c5c4113dSnw141292 } 1597c5c4113dSnw141292 1598c5c4113dSnw141292 /* 1599c5c4113dSnw141292 * Name-based mapping 1600c5c4113dSnw141292 * 1601c5c4113dSnw141292 * Case 1: If no rule matches do ephemeral 1602c5c4113dSnw141292 * 1603c5c4113dSnw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 1604c5c4113dSnw141292 * 1605c5c4113dSnw141292 * Case 3: If rule matches and unixname is specified then lookup name 1606c5c4113dSnw141292 * service using the unixname. If unixname not found then return no mapping. 1607c5c4113dSnw141292 * 1608c5c4113dSnw141292 * Case 4: If rule matches and unixname is * then lookup name service 1609c5c4113dSnw141292 * using winname as the unixname. If unixname not found then process 1610c5c4113dSnw141292 * other rules using the lookup order. If no other rule matches then do 1611c5c4113dSnw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 1612c5c4113dSnw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 1613c5c4113dSnw141292 * instead of the default behaviour of doing ephemeral mapping. 1614c5c4113dSnw141292 * 1615c5c4113dSnw141292 * Example 1: 1616c5c4113dSnw141292 * *@sfbay == * 1617c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1618c5c4113dSnw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 1619c5c4113dSnw141292 * 1620c5c4113dSnw141292 * Example 2: 1621c5c4113dSnw141292 * *@sfbay == * 1622c5c4113dSnw141292 * *@sfbay => guest 1623c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1624c5c4113dSnw141292 * the name service then foo@sfbay will be mapped to guest. 1625c5c4113dSnw141292 * 1626c5c4113dSnw141292 * Example 3: 1627c5c4113dSnw141292 * *@sfbay == * 1628c5c4113dSnw141292 * *@sfbay => "" 1629c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1630c5c4113dSnw141292 * the name service then we will return no mapping for foo@sfbay. 1631c5c4113dSnw141292 * 1632c5c4113dSnw141292 */ 1633c5c4113dSnw141292 static idmap_retcode 1634c5c4113dSnw141292 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) { 1635c5c4113dSnw141292 const char *unixname, *winname, *windomain; 1636c5c4113dSnw141292 char *sql = NULL, *errmsg = NULL; 1637c5c4113dSnw141292 idmap_retcode retcode; 1638c5c4113dSnw141292 char *end; 1639c5c4113dSnw141292 const char **values; 1640c5c4113dSnw141292 sqlite_vm *vm = NULL; 164184decf41Sjp151216 int ncol, r, i, is_user; 1642c5c4113dSnw141292 const char *me = "name_based_mapping_sid2pid"; 1643c5c4113dSnw141292 1644*8e228215Sdm199847 winname = req->id1name; 1645*8e228215Sdm199847 windomain = req->id1domain; 1646c5c4113dSnw141292 is_user = (res->id.idtype == IDMAP_UID)?1:0; 1647c5c4113dSnw141292 1648c5c4113dSnw141292 i = 0; 164962c60062Sbaban if (windomain == NULL) { 165062c60062Sbaban windomain = ""; 165162c60062Sbaban } else { 165262c60062Sbaban RDLOCK_CONFIG(); 165362c60062Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 1654c5c4113dSnw141292 if (strcasecmp(_idmapdstate.cfg->pgcfg.mapping_domain, 1655c5c4113dSnw141292 windomain) == 0) 1656c5c4113dSnw141292 i = 1; 1657c5c4113dSnw141292 } 1658c5c4113dSnw141292 UNLOCK_CONFIG(); 165962c60062Sbaban } 1660c5c4113dSnw141292 1661c5c4113dSnw141292 sql = sqlite_mprintf( 1662c5c4113dSnw141292 "SELECT unixname, u2w_order FROM namerules WHERE " 1663c5c4113dSnw141292 "w2u_order > 0 AND is_user = %d AND " 1664c5c4113dSnw141292 "(winname = %Q OR winname = '*') AND " 1665c5c4113dSnw141292 "(windomain = %Q OR windomain = '*' %s) " 1666c5c4113dSnw141292 "ORDER BY w2u_order ASC;", 166762c60062Sbaban is_user, winname, 166862c60062Sbaban windomain, 166962c60062Sbaban i?"OR windomain ISNULL OR windomain = ''":""); 1670c5c4113dSnw141292 if (sql == NULL) { 1671c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1672c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1673c5c4113dSnw141292 goto out; 1674c5c4113dSnw141292 } 1675c5c4113dSnw141292 1676c5c4113dSnw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 1677c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1678c5c4113dSnw141292 idmapdlog(LOG_ERR, 1679c5c4113dSnw141292 "%s: database error (%s)", 1680c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 1681c5c4113dSnw141292 sqlite_freemem(errmsg); 1682c5c4113dSnw141292 goto out; 1683c5c4113dSnw141292 } 1684c5c4113dSnw141292 168584decf41Sjp151216 for (; ; ) { 1686c5c4113dSnw141292 r = sqlite_step(vm, &ncol, &values, NULL); 168784decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 1688c5c4113dSnw141292 168984decf41Sjp151216 if (r == SQLITE_ROW) { 1690c5c4113dSnw141292 if (ncol < 2) { 1691c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1692c5c4113dSnw141292 goto out; 1693c5c4113dSnw141292 } 1694c5c4113dSnw141292 if (values[0] == NULL) { 1695c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1696c5c4113dSnw141292 goto out; 1697c5c4113dSnw141292 } 1698c5c4113dSnw141292 1699c5c4113dSnw141292 if (EMPTY_NAME(values[0])) { 1700c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 1701c5c4113dSnw141292 goto out; 1702c5c4113dSnw141292 } 1703c5c4113dSnw141292 unixname = (values[0][0] == '*')?winname:values[0]; 1704c5c4113dSnw141292 retcode = ns_lookup_byname(is_user, unixname, res); 1705c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 1706c5c4113dSnw141292 if (unixname == winname) 1707c5c4113dSnw141292 /* Case 4 */ 1708c5c4113dSnw141292 continue; 1709c5c4113dSnw141292 else 1710c5c4113dSnw141292 /* Case 3 */ 1711c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 1712c5c4113dSnw141292 } 1713c5c4113dSnw141292 goto out; 1714c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 1715c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 1716c5c4113dSnw141292 goto out; 1717c5c4113dSnw141292 } else { 1718c5c4113dSnw141292 (void) sqlite_finalize(vm, &errmsg); 1719c5c4113dSnw141292 vm = NULL; 1720c5c4113dSnw141292 idmapdlog(LOG_ERR, 1721c5c4113dSnw141292 "%s: database error (%s)", 1722c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 1723c5c4113dSnw141292 sqlite_freemem(errmsg); 1724c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1725c5c4113dSnw141292 goto out; 1726c5c4113dSnw141292 } 1727c5c4113dSnw141292 } 1728c5c4113dSnw141292 1729c5c4113dSnw141292 out: 173062c60062Sbaban if (sql != NULL) 1731c5c4113dSnw141292 sqlite_freemem(sql); 1732c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 173362c60062Sbaban if (values[1] != NULL) 1734c5c4113dSnw141292 res->direction = 1735651c0131Sbaban (strtol(values[1], &end, 10) == 0)? 1736651c0131Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 1737c5c4113dSnw141292 else 1738651c0131Sbaban res->direction = IDMAP_DIRECTION_W2U; 1739*8e228215Sdm199847 req->id2name = strdup(unixname); 1740c5c4113dSnw141292 } 174162c60062Sbaban if (vm != NULL) 1742c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1743c5c4113dSnw141292 return (retcode); 1744c5c4113dSnw141292 } 1745c5c4113dSnw141292 1746c5c4113dSnw141292 static 1747c5c4113dSnw141292 int 1748c5c4113dSnw141292 get_next_eph_uid(uid_t *next_uid) 1749c5c4113dSnw141292 { 1750c5c4113dSnw141292 uid_t uid; 1751c5c4113dSnw141292 gid_t gid; 1752c5c4113dSnw141292 int err; 1753c5c4113dSnw141292 1754c5c4113dSnw141292 *next_uid = (uid_t)-1; 1755c5c4113dSnw141292 uid = _idmapdstate.next_uid++; 1756c5c4113dSnw141292 if (uid >= _idmapdstate.limit_uid) { 1757c5c4113dSnw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 1758c5c4113dSnw141292 return (err); 1759c5c4113dSnw141292 1760c5c4113dSnw141292 _idmapdstate.limit_uid = uid + 8192; 1761c5c4113dSnw141292 _idmapdstate.next_uid = uid; 1762c5c4113dSnw141292 } 1763c5c4113dSnw141292 *next_uid = uid; 1764c5c4113dSnw141292 1765c5c4113dSnw141292 return (0); 1766c5c4113dSnw141292 } 1767c5c4113dSnw141292 1768c5c4113dSnw141292 static 1769c5c4113dSnw141292 int 1770c5c4113dSnw141292 get_next_eph_gid(gid_t *next_gid) 1771c5c4113dSnw141292 { 1772c5c4113dSnw141292 uid_t uid; 1773c5c4113dSnw141292 gid_t gid; 1774c5c4113dSnw141292 int err; 1775c5c4113dSnw141292 1776c5c4113dSnw141292 *next_gid = (uid_t)-1; 1777c5c4113dSnw141292 gid = _idmapdstate.next_gid++; 1778c5c4113dSnw141292 if (gid >= _idmapdstate.limit_gid) { 1779c5c4113dSnw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 1780c5c4113dSnw141292 return (err); 1781c5c4113dSnw141292 1782c5c4113dSnw141292 _idmapdstate.limit_gid = gid + 8192; 1783c5c4113dSnw141292 _idmapdstate.next_gid = gid; 1784c5c4113dSnw141292 } 1785c5c4113dSnw141292 *next_gid = gid; 1786c5c4113dSnw141292 1787c5c4113dSnw141292 return (0); 1788c5c4113dSnw141292 } 1789c5c4113dSnw141292 179062c60062Sbaban static 179162c60062Sbaban int 179262c60062Sbaban gethash(const char *str, uint32_t num, uint_t htsize) { 179362c60062Sbaban uint_t hval, i, len; 179462c60062Sbaban 179562c60062Sbaban if (str == NULL) 179662c60062Sbaban return (0); 179762c60062Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 179862c60062Sbaban hval += str[i]; 179962c60062Sbaban hval += (hval << 10); 180062c60062Sbaban hval ^= (hval >> 6); 180162c60062Sbaban } 180262c60062Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 180362c60062Sbaban hval += str[i]; 180462c60062Sbaban hval += (hval << 10); 180562c60062Sbaban hval ^= (hval >> 6); 180662c60062Sbaban } 180762c60062Sbaban hval += (hval << 3); 180862c60062Sbaban hval ^= (hval >> 11); 180962c60062Sbaban hval += (hval << 15); 181062c60062Sbaban return (hval % htsize); 181162c60062Sbaban } 181262c60062Sbaban 181362c60062Sbaban static 181462c60062Sbaban int 181562c60062Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 181662c60062Sbaban uid_t *pid) { 181762c60062Sbaban uint_t next, key; 181862c60062Sbaban uint_t htsize = state->sid_history_size; 181962c60062Sbaban idmap_sid *sid; 182062c60062Sbaban 182162c60062Sbaban next = gethash(prefix, rid, htsize); 182262c60062Sbaban while (next != htsize) { 182362c60062Sbaban key = state->sid_history[next].key; 182462c60062Sbaban if (key == htsize) 182562c60062Sbaban return (0); 182662c60062Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 182762c60062Sbaban idmap_id_u.sid; 182862c60062Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 182962c60062Sbaban *pid = state->result->ids.ids_val[key].id. 183062c60062Sbaban idmap_id_u.uid; 183162c60062Sbaban return (1); 183262c60062Sbaban } 183362c60062Sbaban next = state->sid_history[next].next; 183462c60062Sbaban } 183562c60062Sbaban return (0); 183662c60062Sbaban } 183762c60062Sbaban 183862c60062Sbaban static 183962c60062Sbaban void 184062c60062Sbaban add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) { 184162c60062Sbaban uint_t hash, next; 184262c60062Sbaban uint_t htsize = state->sid_history_size; 184362c60062Sbaban 184462c60062Sbaban hash = next = gethash(prefix, rid, htsize); 184562c60062Sbaban while (state->sid_history[next].key != htsize) { 184662c60062Sbaban next++; 184762c60062Sbaban next %= htsize; 184862c60062Sbaban } 184962c60062Sbaban state->sid_history[next].key = state->curpos; 185062c60062Sbaban if (hash == next) 185162c60062Sbaban return; 185262c60062Sbaban state->sid_history[next].next = state->sid_history[hash].next; 185362c60062Sbaban state->sid_history[hash].next = next; 185462c60062Sbaban } 1855c5c4113dSnw141292 1856c5c4113dSnw141292 /* ARGSUSED */ 1857c5c4113dSnw141292 static 1858c5c4113dSnw141292 idmap_retcode 185962c60062Sbaban dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 186062c60062Sbaban idmap_mapping *req, idmap_id_res *res) { 1861c5c4113dSnw141292 1862c5c4113dSnw141292 uid_t next_pid; 1863c5c4113dSnw141292 1864651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 186562c60062Sbaban 186662c60062Sbaban if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 186762c60062Sbaban return (IDMAP_SUCCESS); 186862c60062Sbaban 186962c60062Sbaban if (state->sid_history != NULL && 187062c60062Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 187162c60062Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 187262c60062Sbaban res->id.idmap_id_u.uid = next_pid; 187362c60062Sbaban return (IDMAP_SUCCESS); 187462c60062Sbaban } 187562c60062Sbaban 187662c60062Sbaban if (res->id.idtype == IDMAP_UID) { 1877c5c4113dSnw141292 if (get_next_eph_uid(&next_pid) != 0) 1878c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1879c5c4113dSnw141292 res->id.idmap_id_u.uid = next_pid; 1880c5c4113dSnw141292 } else { 1881c5c4113dSnw141292 if (get_next_eph_gid(&next_pid) != 0) 1882c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1883c5c4113dSnw141292 res->id.idmap_id_u.gid = next_pid; 1884c5c4113dSnw141292 } 1885c5c4113dSnw141292 188662c60062Sbaban if (state->sid_history != NULL) 188762c60062Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 188862c60062Sbaban req->id1.idmap_id_u.sid.rid); 188962c60062Sbaban 1890c5c4113dSnw141292 return (IDMAP_SUCCESS); 1891c5c4113dSnw141292 } 1892c5c4113dSnw141292 1893c5c4113dSnw141292 idmap_retcode 1894c5c4113dSnw141292 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 1895c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res) { 1896c5c4113dSnw141292 idmap_retcode retcode; 1897c5c4113dSnw141292 1898c5c4113dSnw141292 /* 1899c5c4113dSnw141292 * The req->direction field is used to maintain state of the 1900c5c4113dSnw141292 * sid2pid request. 1901c5c4113dSnw141292 */ 1902c5c4113dSnw141292 1903c5c4113dSnw141292 /* Check if second pass is needed */ 1904c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 1905c5c4113dSnw141292 return (res->retcode); 1906c5c4113dSnw141292 1907c5c4113dSnw141292 /* Get status from previous pass */ 1908c5c4113dSnw141292 retcode = (res->retcode == IDMAP_NEXT)?IDMAP_SUCCESS:res->retcode; 1909c5c4113dSnw141292 1910c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 1911c5c4113dSnw141292 /* Reset return type */ 1912c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 1913c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 1914c5c4113dSnw141292 1915c5c4113dSnw141292 /* Check if this is a localsid */ 1916c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND && 1917c5c4113dSnw141292 _idmapdstate.cfg->pgcfg.machine_sid) { 1918c5c4113dSnw141292 retcode = lookup_localsid2pid(req, res); 1919c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 1920c5c4113dSnw141292 state->sid2pid_done = FALSE; 1921c5c4113dSnw141292 req->direction = _IDMAP_F_S2N_CACHE; 1922c5c4113dSnw141292 } 1923c5c4113dSnw141292 } 1924c5c4113dSnw141292 goto out; 1925c5c4113dSnw141292 } 1926c5c4113dSnw141292 1927c5c4113dSnw141292 /* 1928c5c4113dSnw141292 * Verify that the sid type matches the request if the 1929c5c4113dSnw141292 * SID was validated by an AD lookup. 1930c5c4113dSnw141292 */ 1931c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_AD) { 1932c5c4113dSnw141292 retcode = verify_type(req->id2.idtype, 1933c5c4113dSnw141292 (int)res->id.idtype, res); 1934c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 1935c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 1936c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 1937c5c4113dSnw141292 goto out; 1938c5c4113dSnw141292 } 1939c5c4113dSnw141292 } 1940c5c4113dSnw141292 1941c5c4113dSnw141292 /* Name-based mapping */ 1942c5c4113dSnw141292 retcode = name_based_mapping_sid2pid(db, req, res); 1943c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) 1944c5c4113dSnw141292 /* If not found, do ephemeral mapping */ 1945c5c4113dSnw141292 goto ephemeral; 1946c5c4113dSnw141292 else if (retcode != IDMAP_SUCCESS) 1947c5c4113dSnw141292 goto out; 1948c5c4113dSnw141292 1949c5c4113dSnw141292 state->sid2pid_done = FALSE; 1950c5c4113dSnw141292 goto out; 1951c5c4113dSnw141292 1952c5c4113dSnw141292 1953c5c4113dSnw141292 ephemeral: 195462c60062Sbaban retcode = dynamic_ephemeral_mapping(state, cache, req, res); 1955c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) 1956c5c4113dSnw141292 state->sid2pid_done = FALSE; 1957c5c4113dSnw141292 1958c5c4113dSnw141292 out: 1959c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 1960c5c4113dSnw141292 return (retcode); 1961c5c4113dSnw141292 } 1962c5c4113dSnw141292 1963c5c4113dSnw141292 idmap_retcode 1964c5c4113dSnw141292 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 1965c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res) { 1966c5c4113dSnw141292 char *sql = NULL; 1967c5c4113dSnw141292 idmap_retcode retcode; 1968c5c4113dSnw141292 1969c5c4113dSnw141292 /* Check if we need to cache anything */ 1970c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 1971c5c4113dSnw141292 return (IDMAP_SUCCESS); 1972c5c4113dSnw141292 1973c5c4113dSnw141292 /* We don't cache negative entries */ 1974c5c4113dSnw141292 if (res->retcode != IDMAP_SUCCESS) 1975c5c4113dSnw141292 return (IDMAP_SUCCESS); 1976c5c4113dSnw141292 1977c5c4113dSnw141292 /* 1978c5c4113dSnw141292 * Using NULL for u2w instead of 0 so that our trigger allows 1979c5c4113dSnw141292 * the same pid to be the destination in multiple entries 1980c5c4113dSnw141292 */ 1981c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 1982c5c4113dSnw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 1983c5c4113dSnw141292 "is_user, expiration, w2u, u2w) " 1984c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 1985c5c4113dSnw141292 "strftime('%%s','now') + 600, %q, 1); ", 1986c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix, 1987c5c4113dSnw141292 res->id.idmap_id_u.sid.rid, 1988*8e228215Sdm199847 req->id2domain, 1989*8e228215Sdm199847 req->id2name, 1990c5c4113dSnw141292 req->id1.idmap_id_u.uid, 1991*8e228215Sdm199847 req->id1name, 1992c5c4113dSnw141292 (req->id1.idtype == IDMAP_UID)?1:0, 1993c5c4113dSnw141292 (res->direction == 0)?"1":NULL); 1994c5c4113dSnw141292 1995c5c4113dSnw141292 if (sql == NULL) { 1996c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1997c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1998c5c4113dSnw141292 goto out; 1999c5c4113dSnw141292 } 2000c5c4113dSnw141292 2001c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2002c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2003c5c4113dSnw141292 goto out; 2004c5c4113dSnw141292 2005c5c4113dSnw141292 state->pid2sid_done = FALSE; 2006c5c4113dSnw141292 sqlite_freemem(sql); 2007c5c4113dSnw141292 sql = NULL; 2008c5c4113dSnw141292 2009c5c4113dSnw141292 /* If sid2name was found in the cache, no need to update namecache */ 2010c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 2011c5c4113dSnw141292 goto out; 2012c5c4113dSnw141292 2013*8e228215Sdm199847 if (req->id2name == NULL) 2014c5c4113dSnw141292 goto out; 2015c5c4113dSnw141292 2016c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2017c5c4113dSnw141292 "(sidprefix, rid, name, domain, type, expiration) " 2018c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2019c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix, 2020c5c4113dSnw141292 res->id.idmap_id_u.sid.rid, 2021*8e228215Sdm199847 req->id2name, 2022*8e228215Sdm199847 req->id2domain, 2023c5c4113dSnw141292 (req->id1.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 2024c5c4113dSnw141292 2025c5c4113dSnw141292 if (sql == NULL) { 2026c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2027c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2028c5c4113dSnw141292 goto out; 2029c5c4113dSnw141292 } 2030c5c4113dSnw141292 2031c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2032c5c4113dSnw141292 2033c5c4113dSnw141292 out: 203462c60062Sbaban if (sql != NULL) 2035c5c4113dSnw141292 sqlite_freemem(sql); 2036c5c4113dSnw141292 return (retcode); 2037c5c4113dSnw141292 } 2038c5c4113dSnw141292 2039c5c4113dSnw141292 idmap_retcode 2040c5c4113dSnw141292 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 2041c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res) { 2042c5c4113dSnw141292 char *sql = NULL; 2043c5c4113dSnw141292 idmap_retcode retcode; 2044c5c4113dSnw141292 int is_eph_user; 2045c5c4113dSnw141292 2046c5c4113dSnw141292 /* Check if we need to cache anything */ 2047c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 2048c5c4113dSnw141292 return (IDMAP_SUCCESS); 2049c5c4113dSnw141292 2050c5c4113dSnw141292 /* We don't cache negative entries */ 2051c5c4113dSnw141292 if (res->retcode != IDMAP_SUCCESS) 2052c5c4113dSnw141292 return (IDMAP_SUCCESS); 2053c5c4113dSnw141292 2054c5c4113dSnw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 2055c5c4113dSnw141292 is_eph_user = 1; 2056c5c4113dSnw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 2057c5c4113dSnw141292 is_eph_user = 0; 2058c5c4113dSnw141292 else 2059c5c4113dSnw141292 is_eph_user = -1; 2060c5c4113dSnw141292 2061c5c4113dSnw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 2062c5c4113dSnw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 2063c5c4113dSnw141292 "SET w2u = 0 WHERE " 2064c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 2065c5c4113dSnw141292 "pid >= 2147483648 AND is_user = %d;", 2066c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2067c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 2068c5c4113dSnw141292 is_eph_user); 2069c5c4113dSnw141292 if (sql == NULL) { 2070c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2071c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2072c5c4113dSnw141292 goto out; 2073c5c4113dSnw141292 } 2074c5c4113dSnw141292 2075c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2076c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2077c5c4113dSnw141292 goto out; 2078c5c4113dSnw141292 2079c5c4113dSnw141292 sqlite_freemem(sql); 2080c5c4113dSnw141292 sql = NULL; 2081c5c4113dSnw141292 } 2082c5c4113dSnw141292 2083c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2084c5c4113dSnw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 2085c5c4113dSnw141292 "is_user, expiration, w2u, u2w) " 2086c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 2087c5c4113dSnw141292 "strftime('%%s','now') + 600, 1, %q); ", 2088c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2089c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 2090*8e228215Sdm199847 req->id1domain, 2091*8e228215Sdm199847 req->id1name, 2092c5c4113dSnw141292 res->id.idmap_id_u.uid, 2093*8e228215Sdm199847 req->id2name, 2094c5c4113dSnw141292 (res->id.idtype == IDMAP_UID)?1:0, 2095c5c4113dSnw141292 (res->direction == 0)?"1":NULL); 2096c5c4113dSnw141292 2097c5c4113dSnw141292 if (sql == NULL) { 2098c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2099c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2100c5c4113dSnw141292 goto out; 2101c5c4113dSnw141292 } 2102c5c4113dSnw141292 2103c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2104c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2105c5c4113dSnw141292 goto out; 2106c5c4113dSnw141292 2107c5c4113dSnw141292 state->sid2pid_done = FALSE; 2108c5c4113dSnw141292 sqlite_freemem(sql); 2109c5c4113dSnw141292 sql = NULL; 2110c5c4113dSnw141292 2111c5c4113dSnw141292 /* If name2sid was found in the cache, no need to update namecache */ 2112c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 2113c5c4113dSnw141292 goto out; 2114c5c4113dSnw141292 2115*8e228215Sdm199847 if (req->id1name == NULL) 2116c5c4113dSnw141292 goto out; 2117c5c4113dSnw141292 2118c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2119c5c4113dSnw141292 "(sidprefix, rid, name, domain, type, expiration) " 2120c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2121c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2122c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 2123*8e228215Sdm199847 req->id1name, 2124*8e228215Sdm199847 req->id1domain, 2125c5c4113dSnw141292 (res->id.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 2126c5c4113dSnw141292 2127c5c4113dSnw141292 if (sql == NULL) { 2128c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2129c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2130c5c4113dSnw141292 goto out; 2131c5c4113dSnw141292 } 2132c5c4113dSnw141292 2133c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2134c5c4113dSnw141292 2135c5c4113dSnw141292 out: 213662c60062Sbaban if (sql != NULL) 2137c5c4113dSnw141292 sqlite_freemem(sql); 2138c5c4113dSnw141292 return (retcode); 2139c5c4113dSnw141292 } 2140c5c4113dSnw141292 2141c5c4113dSnw141292 static idmap_retcode 2142c5c4113dSnw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 2143c5c4113dSnw141292 int is_user, int getname) { 2144c5c4113dSnw141292 char *end; 2145c5c4113dSnw141292 char *sql = NULL; 2146c5c4113dSnw141292 const char **values; 2147c5c4113dSnw141292 sqlite_vm *vm = NULL; 2148c5c4113dSnw141292 int ncol; 2149c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2150c5c4113dSnw141292 time_t curtime; 2151c5c4113dSnw141292 2152c5c4113dSnw141292 /* Current time */ 2153c5c4113dSnw141292 errno = 0; 2154c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 2155c5c4113dSnw141292 idmapdlog(LOG_ERR, 2156c5c4113dSnw141292 "Failed to get current time (%s)", 2157c5c4113dSnw141292 strerror(errno)); 2158c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2159c5c4113dSnw141292 goto out; 2160c5c4113dSnw141292 } 2161c5c4113dSnw141292 2162c5c4113dSnw141292 /* SQL to lookup the cache */ 2163c5c4113dSnw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, winname, windomain, w2u " 2164c5c4113dSnw141292 "FROM idmap_cache WHERE " 2165c5c4113dSnw141292 "pid = %u AND u2w = 1 AND is_user = %d AND " 2166c5c4113dSnw141292 "(pid >= 2147483648 OR " 2167c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 2168c5c4113dSnw141292 "expiration > %d));", 2169c5c4113dSnw141292 req->id1.idmap_id_u.uid, is_user, curtime); 2170c5c4113dSnw141292 if (sql == NULL) { 2171c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2172c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2173c5c4113dSnw141292 goto out; 2174c5c4113dSnw141292 } 2175c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 2176c5c4113dSnw141292 sqlite_freemem(sql); 2177c5c4113dSnw141292 2178c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) 2179c5c4113dSnw141292 goto out; 2180c5c4113dSnw141292 else if (retcode == IDMAP_SUCCESS) { 2181c5c4113dSnw141292 /* sanity checks */ 2182c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 2183c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2184c5c4113dSnw141292 goto out; 2185c5c4113dSnw141292 } 2186c5c4113dSnw141292 2187c5c4113dSnw141292 switch (req->id2.idtype) { 2188c5c4113dSnw141292 case IDMAP_SID: 2189c5c4113dSnw141292 res->id.idmap_id_u.sid.rid = 2190c5c4113dSnw141292 strtoul(values[1], &end, 10); 2191c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 2192c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 2193c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2194c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2195c5c4113dSnw141292 goto out; 2196c5c4113dSnw141292 } 2197c5c4113dSnw141292 219862c60062Sbaban if (values[4] != NULL) 2199c5c4113dSnw141292 res->direction = 2200651c0131Sbaban (strtol(values[4], &end, 10) == 0)? 2201651c0131Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2202c5c4113dSnw141292 else 2203651c0131Sbaban res->direction = IDMAP_DIRECTION_U2W; 2204c5c4113dSnw141292 2205c5c4113dSnw141292 if (getname == 0 || values[2] == NULL) 2206c5c4113dSnw141292 break; 2207*8e228215Sdm199847 req->id2name = strdup(values[2]); 2208*8e228215Sdm199847 if (req->id2name == NULL) { 2209c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2210c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2211c5c4113dSnw141292 goto out; 2212c5c4113dSnw141292 } 2213c5c4113dSnw141292 2214c5c4113dSnw141292 if (values[3] == NULL) 2215c5c4113dSnw141292 break; 2216*8e228215Sdm199847 req->id2domain = strdup(values[3]); 2217*8e228215Sdm199847 if (req->id2domain == NULL) { 2218c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2219c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2220c5c4113dSnw141292 goto out; 2221c5c4113dSnw141292 } 2222c5c4113dSnw141292 break; 2223c5c4113dSnw141292 default: 2224c5c4113dSnw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 2225c5c4113dSnw141292 break; 2226c5c4113dSnw141292 } 2227c5c4113dSnw141292 } 2228c5c4113dSnw141292 2229c5c4113dSnw141292 out: 223062c60062Sbaban if (vm != NULL) 2231c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2232c5c4113dSnw141292 return (retcode); 2233c5c4113dSnw141292 } 2234c5c4113dSnw141292 2235c5c4113dSnw141292 static idmap_retcode 2236c5c4113dSnw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 2237c5c4113dSnw141292 char **sidprefix, idmap_rid_t *rid, int *type) { 2238c5c4113dSnw141292 char *end; 2239c5c4113dSnw141292 char *sql = NULL; 2240c5c4113dSnw141292 const char **values; 2241c5c4113dSnw141292 sqlite_vm *vm = NULL; 2242c5c4113dSnw141292 int ncol; 2243c5c4113dSnw141292 time_t curtime; 2244c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2245c5c4113dSnw141292 2246c5c4113dSnw141292 /* Get current time */ 2247c5c4113dSnw141292 errno = 0; 2248c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 2249c5c4113dSnw141292 idmapdlog(LOG_ERR, 2250c5c4113dSnw141292 "Failed to get current time (%s)", 2251c5c4113dSnw141292 strerror(errno)); 2252c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2253c5c4113dSnw141292 goto out; 2254c5c4113dSnw141292 } 2255c5c4113dSnw141292 2256c5c4113dSnw141292 /* SQL to lookup the cache */ 2257c5c4113dSnw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type FROM name_cache " 2258c5c4113dSnw141292 "WHERE name = %Q AND domain = %Q AND " 2259c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 2260c5c4113dSnw141292 "expiration > %d);", 2261c5c4113dSnw141292 name, domain, curtime); 2262c5c4113dSnw141292 if (sql == NULL) { 2263c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2264c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2265c5c4113dSnw141292 goto out; 2266c5c4113dSnw141292 } 2267c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 2268c5c4113dSnw141292 sqlite_freemem(sql); 2269c5c4113dSnw141292 2270c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 227162c60062Sbaban if (type != NULL) { 2272c5c4113dSnw141292 if (values[2] == NULL) { 2273c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2274c5c4113dSnw141292 goto out; 2275c5c4113dSnw141292 } 2276c5c4113dSnw141292 *type = strtol(values[2], &end, 10); 2277c5c4113dSnw141292 } 2278c5c4113dSnw141292 2279c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 2280c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2281c5c4113dSnw141292 goto out; 2282c5c4113dSnw141292 } 2283c5c4113dSnw141292 if ((*sidprefix = strdup(values[0])) == NULL) { 2284c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2285c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2286c5c4113dSnw141292 goto out; 2287c5c4113dSnw141292 } 2288c5c4113dSnw141292 *rid = strtoul(values[1], &end, 10); 2289c5c4113dSnw141292 } 2290c5c4113dSnw141292 2291c5c4113dSnw141292 out: 229262c60062Sbaban if (vm != NULL) 2293c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2294c5c4113dSnw141292 return (retcode); 2295c5c4113dSnw141292 } 2296c5c4113dSnw141292 2297c5c4113dSnw141292 static idmap_retcode 2298c5c4113dSnw141292 lookup_win_name2sid(const char *name, const char *domain, char **sidprefix, 2299c5c4113dSnw141292 idmap_rid_t *rid, int *type) { 2300c5c4113dSnw141292 int ret; 2301c5c4113dSnw141292 int retries = 0; 2302c5c4113dSnw141292 idmap_query_state_t *qs = NULL; 2303c5c4113dSnw141292 idmap_retcode rc, retcode; 2304c5c4113dSnw141292 2305c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2306c5c4113dSnw141292 2307c5c4113dSnw141292 retry: 2308c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 2309c5c4113dSnw141292 if (ret != 0) { 2310c5c4113dSnw141292 idmapdlog(LOG_ERR, 2311c5c4113dSnw141292 "Failed to create name2sid batch for AD lookup"); 2312c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2313c5c4113dSnw141292 } 2314c5c4113dSnw141292 2315c5c4113dSnw141292 retcode = idmap_name2sid_batch_add1(qs, name, domain, sidprefix, 2316c5c4113dSnw141292 rid, type, &rc); 2317c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2318c5c4113dSnw141292 goto out; 2319c5c4113dSnw141292 2320c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2321c5c4113dSnw141292 idmapdlog(LOG_ERR, 2322c5c4113dSnw141292 "Failed to batch name2sid for AD lookup"); 232384decf41Sjp151216 idmap_lookup_release_batch(&qs); 2324c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2325c5c4113dSnw141292 } 2326c5c4113dSnw141292 2327c5c4113dSnw141292 out: 2328c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 232984decf41Sjp151216 idmap_lookup_release_batch(&qs); 2330c5c4113dSnw141292 else 2331c5c4113dSnw141292 retcode = idmap_lookup_batch_end(&qs, NULL); 2332c5c4113dSnw141292 2333c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 2334c5c4113dSnw141292 goto retry; 2335c5c4113dSnw141292 2336c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2337c5c4113dSnw141292 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 2338c5c4113dSnw141292 "failed"); 2339c5c4113dSnw141292 return (retcode); 2340c5c4113dSnw141292 } else 2341c5c4113dSnw141292 return (rc); 2342c5c4113dSnw141292 /* NOTREACHED */ 2343c5c4113dSnw141292 } 2344c5c4113dSnw141292 2345c5c4113dSnw141292 static idmap_retcode 2346c5c4113dSnw141292 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 2347c5c4113dSnw141292 int *is_user, char **sidprefix, idmap_rid_t *rid, 2348c5c4113dSnw141292 idmap_mapping *req) { 2349c5c4113dSnw141292 int type; 2350c5c4113dSnw141292 idmap_retcode retcode; 2351c5c4113dSnw141292 235262c60062Sbaban /* Lookup name@domain to sid in the well-known sids table */ 235362c60062Sbaban retcode = lookup_wksids_name2sid(name, sidprefix, rid, &type); 235462c60062Sbaban if (retcode == IDMAP_SUCCESS) { 235562c60062Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 235662c60062Sbaban goto out; 235762c60062Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 235862c60062Sbaban return (retcode); 235962c60062Sbaban } 236062c60062Sbaban 236162c60062Sbaban /* Lookup name@domain to sid in cache */ 2362c5c4113dSnw141292 retcode = lookup_cache_name2sid(cache, name, domain, sidprefix, 2363c5c4113dSnw141292 rid, &type); 2364c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2365c5c4113dSnw141292 /* Lookup Windows NT/AD to map name@domain to sid */ 2366c5c4113dSnw141292 retcode = lookup_win_name2sid(name, domain, sidprefix, rid, 2367c5c4113dSnw141292 &type); 2368c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2369c5c4113dSnw141292 return (retcode); 2370c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_AD; 2371c5c4113dSnw141292 } else if (retcode != IDMAP_SUCCESS) { 2372c5c4113dSnw141292 return (retcode); 2373c5c4113dSnw141292 } else { 2374c5c4113dSnw141292 /* Set flag */ 2375c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_CACHE; 2376c5c4113dSnw141292 } 2377c5c4113dSnw141292 237862c60062Sbaban out: 2379c5c4113dSnw141292 /* 2380c5c4113dSnw141292 * Entry found (cache or Windows lookup) 2381c5c4113dSnw141292 * is_user is both input as well as output parameter 2382c5c4113dSnw141292 */ 2383c5c4113dSnw141292 if (*is_user == 1) { 2384c5c4113dSnw141292 if (type != _IDMAP_T_USER) 2385c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 2386c5c4113dSnw141292 } else if (*is_user == 0) { 2387c5c4113dSnw141292 if (type != _IDMAP_T_GROUP) 2388c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 2389c5c4113dSnw141292 } else if (*is_user == -1) { 2390c5c4113dSnw141292 /* Caller wants to know if its user or group */ 2391c5c4113dSnw141292 if (type == _IDMAP_T_USER) 2392c5c4113dSnw141292 *is_user = 1; 2393c5c4113dSnw141292 else if (type == _IDMAP_T_GROUP) 2394c5c4113dSnw141292 *is_user = 0; 2395c5c4113dSnw141292 else 2396c5c4113dSnw141292 return (IDMAP_ERR_SID); 2397c5c4113dSnw141292 } 2398c5c4113dSnw141292 2399c5c4113dSnw141292 return (retcode); 2400c5c4113dSnw141292 } 2401c5c4113dSnw141292 2402c5c4113dSnw141292 static idmap_retcode 2403c5c4113dSnw141292 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 2404c5c4113dSnw141292 int is_user, idmap_mapping *req, idmap_id_res *res) { 2405c5c4113dSnw141292 const char *winname, *windomain; 2406c5c4113dSnw141292 char *mapping_domain = NULL; 2407c5c4113dSnw141292 char *sql = NULL, *errmsg = NULL; 2408c5c4113dSnw141292 idmap_retcode retcode; 2409c5c4113dSnw141292 char *end; 2410c5c4113dSnw141292 const char **values; 2411c5c4113dSnw141292 sqlite_vm *vm = NULL; 241284decf41Sjp151216 int ncol, r; 2413c5c4113dSnw141292 const char *me = "name_based_mapping_pid2sid"; 2414c5c4113dSnw141292 2415c5c4113dSnw141292 RDLOCK_CONFIG(); 241662c60062Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 2417c5c4113dSnw141292 mapping_domain = 2418c5c4113dSnw141292 strdup(_idmapdstate.cfg->pgcfg.mapping_domain); 2419c5c4113dSnw141292 if (mapping_domain == NULL) { 2420c5c4113dSnw141292 UNLOCK_CONFIG(); 2421c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2422c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2423c5c4113dSnw141292 goto out; 2424c5c4113dSnw141292 } 2425c5c4113dSnw141292 } 2426c5c4113dSnw141292 UNLOCK_CONFIG(); 2427c5c4113dSnw141292 2428c5c4113dSnw141292 sql = sqlite_mprintf( 2429c5c4113dSnw141292 "SELECT winname, windomain, w2u_order FROM namerules WHERE " 2430c5c4113dSnw141292 "u2w_order > 0 AND is_user = %d AND " 2431c5c4113dSnw141292 "(unixname = %Q OR unixname = '*') " 2432c5c4113dSnw141292 "ORDER BY u2w_order ASC;", 2433c5c4113dSnw141292 is_user, unixname); 2434c5c4113dSnw141292 if (sql == NULL) { 2435c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2436c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2437c5c4113dSnw141292 goto out; 2438c5c4113dSnw141292 } 2439c5c4113dSnw141292 2440c5c4113dSnw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 2441c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2442c5c4113dSnw141292 idmapdlog(LOG_ERR, 2443c5c4113dSnw141292 "%s: database error (%s)", 2444c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 2445c5c4113dSnw141292 sqlite_freemem(errmsg); 2446c5c4113dSnw141292 goto out; 2447c5c4113dSnw141292 } 2448c5c4113dSnw141292 244984decf41Sjp151216 for (;;) { 2450c5c4113dSnw141292 r = sqlite_step(vm, &ncol, &values, NULL); 245184decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 245284decf41Sjp151216 if (r == SQLITE_ROW) { 2453c5c4113dSnw141292 if (ncol < 3) { 2454c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2455c5c4113dSnw141292 goto out; 2456c5c4113dSnw141292 } 2457c5c4113dSnw141292 if (values[0] == NULL) { 2458c5c4113dSnw141292 /* values [1] and [2] can be null */ 2459c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2460c5c4113dSnw141292 goto out; 2461c5c4113dSnw141292 } 2462c5c4113dSnw141292 if (EMPTY_NAME(values[0])) { 2463c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2464c5c4113dSnw141292 goto out; 2465c5c4113dSnw141292 } 2466c5c4113dSnw141292 winname = (values[0][0] == '*')?unixname:values[0]; 246762c60062Sbaban if (values[1] != NULL) 2468c5c4113dSnw141292 windomain = values[1]; 246962c60062Sbaban else if (mapping_domain != NULL) 2470c5c4113dSnw141292 windomain = mapping_domain; 2471c5c4113dSnw141292 else { 2472c5c4113dSnw141292 idmapdlog(LOG_ERR, 2473c5c4113dSnw141292 "%s: no domain", me); 2474c5c4113dSnw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 2475c5c4113dSnw141292 goto out; 2476c5c4113dSnw141292 } 2477c5c4113dSnw141292 /* Lookup winname@domain to sid */ 2478c5c4113dSnw141292 retcode = lookup_name2sid(cache, winname, windomain, 2479c5c4113dSnw141292 &is_user, &res->id.idmap_id_u.sid.prefix, 2480c5c4113dSnw141292 &res->id.idmap_id_u.sid.rid, req); 2481c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2482c5c4113dSnw141292 if (winname == unixname) 2483c5c4113dSnw141292 continue; 2484c5c4113dSnw141292 else 2485c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2486c5c4113dSnw141292 } 2487c5c4113dSnw141292 goto out; 2488c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 2489c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2490c5c4113dSnw141292 goto out; 2491c5c4113dSnw141292 } else { 2492c5c4113dSnw141292 (void) sqlite_finalize(vm, &errmsg); 2493c5c4113dSnw141292 vm = NULL; 2494c5c4113dSnw141292 idmapdlog(LOG_ERR, 2495c5c4113dSnw141292 "%s: database error (%s)", 2496c5c4113dSnw141292 me, CHECK_NULL(errmsg)); 2497c5c4113dSnw141292 sqlite_freemem(errmsg); 2498c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2499c5c4113dSnw141292 goto out; 2500c5c4113dSnw141292 } 2501c5c4113dSnw141292 } 2502c5c4113dSnw141292 2503c5c4113dSnw141292 out: 250462c60062Sbaban if (sql != NULL) 2505c5c4113dSnw141292 sqlite_freemem(sql); 2506c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 250762c60062Sbaban if (values[2] != NULL) 2508c5c4113dSnw141292 res->direction = 2509651c0131Sbaban (strtol(values[2], &end, 10) == 0)? 2510651c0131Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2511c5c4113dSnw141292 else 2512651c0131Sbaban res->direction = IDMAP_DIRECTION_U2W; 2513*8e228215Sdm199847 2514*8e228215Sdm199847 req->id2name = strdup(winname); 2515*8e228215Sdm199847 if (req->id2name != NULL) { 2516c5c4113dSnw141292 if (windomain == mapping_domain) { 2517*8e228215Sdm199847 req->id2domain = (char *)windomain; 2518c5c4113dSnw141292 mapping_domain = NULL; 2519*8e228215Sdm199847 } else { 2520*8e228215Sdm199847 req->id2domain = strdup(windomain); 2521*8e228215Sdm199847 } 2522c5c4113dSnw141292 } 2523c5c4113dSnw141292 } 252462c60062Sbaban if (vm != NULL) 2525c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 252662c60062Sbaban if (mapping_domain != NULL) 2527c5c4113dSnw141292 free(mapping_domain); 2528c5c4113dSnw141292 return (retcode); 2529c5c4113dSnw141292 } 2530c5c4113dSnw141292 2531c5c4113dSnw141292 idmap_retcode 2532c5c4113dSnw141292 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 2533c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res, int is_user, 2534c5c4113dSnw141292 int getname) { 2535c5c4113dSnw141292 char *unixname = NULL; 2536c5c4113dSnw141292 struct passwd pwd; 2537c5c4113dSnw141292 struct group grp; 2538c5c4113dSnw141292 char buf[1024]; 2539c5c4113dSnw141292 int errnum; 2540c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2541c5c4113dSnw141292 const char *me = "pid2sid"; 2542c5c4113dSnw141292 2543c5c4113dSnw141292 req->direction = _IDMAP_F_DONE; 2544c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 2545c5c4113dSnw141292 2546c5c4113dSnw141292 /* Lookup well-known SIDs */ 2547c5c4113dSnw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 2548c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 2549c5c4113dSnw141292 goto out; 2550c5c4113dSnw141292 2551c5c4113dSnw141292 /* Lookup pid to sid in cache */ 2552c5c4113dSnw141292 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 2553c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 2554c5c4113dSnw141292 goto out; 2555c5c4113dSnw141292 2556c5c4113dSnw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 2557c5c4113dSnw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 255862c60062Sbaban retcode = IDMAP_ERR_NOMAPPING; 2559c5c4113dSnw141292 goto out; 2560c5c4113dSnw141292 } 2561c5c4113dSnw141292 2562c5c4113dSnw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 256362c60062Sbaban retcode = IDMAP_ERR_NOMAPPING; 2564c5c4113dSnw141292 goto out; 2565c5c4113dSnw141292 } 2566c5c4113dSnw141292 2567c5c4113dSnw141292 /* uid/gid to name */ 2568*8e228215Sdm199847 if (req->id1name != NULL) { 2569*8e228215Sdm199847 unixname = req->id1name; 2570*8e228215Sdm199847 } else if (is_user) { 2571c5c4113dSnw141292 errno = 0; 2572c5c4113dSnw141292 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 2573c5c4113dSnw141292 sizeof (buf)) == NULL) { 2574c5c4113dSnw141292 errnum = errno; 2575c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2576c5c4113dSnw141292 "%s: getpwuid_r(%u) failed (%s).", 2577c5c4113dSnw141292 me, req->id1.idmap_id_u.uid, 2578c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2579c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2580c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2581c5c4113dSnw141292 goto fallback_localsid; 2582c5c4113dSnw141292 } 2583c5c4113dSnw141292 unixname = pwd.pw_name; 2584c5c4113dSnw141292 } else { 2585c5c4113dSnw141292 errno = 0; 2586c5c4113dSnw141292 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 2587c5c4113dSnw141292 sizeof (buf)) == NULL) { 2588c5c4113dSnw141292 errnum = errno; 2589c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2590c5c4113dSnw141292 "%s: getgrgid_r(%u) failed (%s).", 2591c5c4113dSnw141292 me, req->id1.idmap_id_u.gid, 2592c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2593c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2594c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2595c5c4113dSnw141292 goto fallback_localsid; 2596c5c4113dSnw141292 } 2597c5c4113dSnw141292 unixname = grp.gr_name; 2598c5c4113dSnw141292 } 2599c5c4113dSnw141292 2600c5c4113dSnw141292 /* Name-based mapping */ 2601c5c4113dSnw141292 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 2602c5c4113dSnw141292 req, res); 2603c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2604c5c4113dSnw141292 retcode = generate_localsid(req, res, is_user); 2605c5c4113dSnw141292 goto out; 2606c5c4113dSnw141292 } else if (retcode == IDMAP_SUCCESS) 2607c5c4113dSnw141292 goto out; 2608c5c4113dSnw141292 2609c5c4113dSnw141292 fallback_localsid: 2610c5c4113dSnw141292 /* 2611c5c4113dSnw141292 * Here we generate localsid as fallback id on errors. Our 2612c5c4113dSnw141292 * return status is the error that's been previously assigned. 2613c5c4113dSnw141292 */ 2614c5c4113dSnw141292 (void) generate_localsid(req, res, is_user); 2615c5c4113dSnw141292 2616c5c4113dSnw141292 out: 2617*8e228215Sdm199847 if (retcode == IDMAP_SUCCESS && req->id1name == NULL && 261862c60062Sbaban unixname != NULL) { 2619*8e228215Sdm199847 req->id1name = strdup(unixname); 2620c5c4113dSnw141292 } 2621c5c4113dSnw141292 if (req->direction != _IDMAP_F_DONE) 2622c5c4113dSnw141292 state->pid2sid_done = FALSE; 2623c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 2624c5c4113dSnw141292 return (retcode); 2625c5c4113dSnw141292 } 2626c5c4113dSnw141292 2627c5c4113dSnw141292 static idmap_retcode 2628c5c4113dSnw141292 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 2629c5c4113dSnw141292 char **domain, int *type) { 2630c5c4113dSnw141292 int ret; 2631c5c4113dSnw141292 idmap_query_state_t *qs = NULL; 2632c5c4113dSnw141292 idmap_retcode rc, retcode; 2633c5c4113dSnw141292 2634c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2635c5c4113dSnw141292 2636c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 2637c5c4113dSnw141292 if (ret != 0) { 2638c5c4113dSnw141292 idmapdlog(LOG_ERR, 2639c5c4113dSnw141292 "Failed to create sid2name batch for AD lookup"); 2640c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2641c5c4113dSnw141292 goto out; 2642c5c4113dSnw141292 } 2643c5c4113dSnw141292 2644c5c4113dSnw141292 ret = idmap_sid2name_batch_add1( 2645c5c4113dSnw141292 qs, sidprefix, &rid, name, domain, type, &rc); 2646c5c4113dSnw141292 if (ret != 0) { 2647c5c4113dSnw141292 idmapdlog(LOG_ERR, 2648c5c4113dSnw141292 "Failed to batch sid2name for AD lookup"); 2649c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2650c5c4113dSnw141292 goto out; 2651c5c4113dSnw141292 } 2652c5c4113dSnw141292 2653c5c4113dSnw141292 out: 265462c60062Sbaban if (qs != NULL) { 2655c5c4113dSnw141292 ret = idmap_lookup_batch_end(&qs, NULL); 2656c5c4113dSnw141292 if (ret != 0) { 2657c5c4113dSnw141292 idmapdlog(LOG_ERR, 2658c5c4113dSnw141292 "Failed to execute sid2name AD lookup"); 2659c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2660c5c4113dSnw141292 } else 2661c5c4113dSnw141292 retcode = rc; 2662c5c4113dSnw141292 } 2663c5c4113dSnw141292 2664c5c4113dSnw141292 return (retcode); 2665c5c4113dSnw141292 } 2666c5c4113dSnw141292 2667651c0131Sbaban static int 2668651c0131Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 2669c5c4113dSnw141292 { 2670651c0131Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 2671651c0131Sbaban 2672c5c4113dSnw141292 mapping->flag = request->flag; 2673c5c4113dSnw141292 mapping->direction = request->direction; 2674651c0131Sbaban mapping->id2.idtype = request->id2.idtype; 2675c5c4113dSnw141292 2676c5c4113dSnw141292 mapping->id1.idtype = request->id1.idtype; 2677c5c4113dSnw141292 if (request->id1.idtype == IDMAP_SID) { 2678c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.rid = 2679c5c4113dSnw141292 request->id1.idmap_id_u.sid.rid; 2680651c0131Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 2681c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.prefix = 2682c5c4113dSnw141292 strdup(request->id1.idmap_id_u.sid.prefix); 2683651c0131Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 2684*8e228215Sdm199847 goto errout; 2685651c0131Sbaban } 2686c5c4113dSnw141292 } else { 2687c5c4113dSnw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 2688c5c4113dSnw141292 } 2689c5c4113dSnw141292 2690*8e228215Sdm199847 mapping->id1domain = strdup(request->id1domain); 2691*8e228215Sdm199847 if (mapping->id1domain == NULL) 2692*8e228215Sdm199847 goto errout; 2693c5c4113dSnw141292 2694*8e228215Sdm199847 mapping->id1name = strdup(request->id1name); 2695*8e228215Sdm199847 if (mapping->id1name == NULL) 2696*8e228215Sdm199847 goto errout; 2697c5c4113dSnw141292 2698651c0131Sbaban /* We don't need the rest of the request i.e request->id2 */ 2699651c0131Sbaban return (0); 2700c5c4113dSnw141292 2701651c0131Sbaban errout: 2702*8e228215Sdm199847 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 2703651c0131Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 2704*8e228215Sdm199847 if (mapping->id1domain != NULL) 2705*8e228215Sdm199847 free(mapping->id1domain); 2706*8e228215Sdm199847 if (mapping->id1name != NULL) 2707*8e228215Sdm199847 free(mapping->id1name); 2708651c0131Sbaban 2709651c0131Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 2710651c0131Sbaban return (-1); 2711c5c4113dSnw141292 } 2712c5c4113dSnw141292 2713c5c4113dSnw141292 2714c5c4113dSnw141292 idmap_retcode 2715c5c4113dSnw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 2716c5c4113dSnw141292 idmap_mapping *mapping) { 2717c5c4113dSnw141292 idmap_id_res idres; 2718c5c4113dSnw141292 lookup_state_t state; 2719dd5829d1Sbaban char *cp; 2720c5c4113dSnw141292 int is_user; 2721c5c4113dSnw141292 idmap_retcode retcode; 2722c5c4113dSnw141292 const char *winname, *windomain; 2723c5c4113dSnw141292 2724c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 2725c5c4113dSnw141292 (void) memset(&state, 0, sizeof (state)); 2726c5c4113dSnw141292 2727c5c4113dSnw141292 if (request->id2.idtype == IDMAP_UID) 2728c5c4113dSnw141292 is_user = 1; 2729c5c4113dSnw141292 else if (request->id2.idtype == IDMAP_GID) 2730c5c4113dSnw141292 is_user = 0; 2731c5c4113dSnw141292 else if (request->id2.idtype == IDMAP_POSIXID) 2732c5c4113dSnw141292 is_user = -1; 2733c5c4113dSnw141292 else { 2734c5c4113dSnw141292 retcode = IDMAP_ERR_IDTYPE; 2735c5c4113dSnw141292 goto out; 2736c5c4113dSnw141292 } 2737c5c4113dSnw141292 2738c5c4113dSnw141292 /* Copy data from request to result */ 2739651c0131Sbaban if (copy_mapping_request(mapping, request) < 0) { 2740651c0131Sbaban retcode = IDMAP_ERR_MEMORY; 2741651c0131Sbaban goto out; 2742651c0131Sbaban } 2743c5c4113dSnw141292 2744*8e228215Sdm199847 winname = mapping->id1name; 2745*8e228215Sdm199847 windomain = mapping->id1domain; 2746c5c4113dSnw141292 274762c60062Sbaban if (winname == NULL && windomain != NULL) { 2748c5c4113dSnw141292 retcode = IDMAP_ERR_ARG; 2749c5c4113dSnw141292 goto out; 2750c5c4113dSnw141292 } 2751c5c4113dSnw141292 275262c60062Sbaban if (winname != NULL && windomain == NULL) { 2753*8e228215Sdm199847 retcode = IDMAP_SUCCESS; 2754dd5829d1Sbaban if ((cp = strchr(winname, '@')) != NULL) { 2755dd5829d1Sbaban /* 2756dd5829d1Sbaban * if winname is qualified with a domain, use it. 2757dd5829d1Sbaban */ 2758dd5829d1Sbaban *cp = '\0'; 2759*8e228215Sdm199847 mapping->id1domain = strdup(cp + 1); 2760*8e228215Sdm199847 if (mapping->id1domain == NULL) 2761*8e228215Sdm199847 retcode = IDMAP_ERR_MEMORY; 2762*8e228215Sdm199847 } else { 2763*8e228215Sdm199847 RDLOCK_CONFIG(); 2764*8e228215Sdm199847 if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 2765dd5829d1Sbaban /* 2766dd5829d1Sbaban * otherwise use the mapping domain 2767dd5829d1Sbaban */ 2768*8e228215Sdm199847 mapping->id1domain = 2769*8e228215Sdm199847 strdup(_idmapdstate.cfg-> 2770*8e228215Sdm199847 pgcfg.mapping_domain); 2771*8e228215Sdm199847 if (mapping->id1domain == NULL) 2772*8e228215Sdm199847 retcode = IDMAP_ERR_MEMORY; 2773*8e228215Sdm199847 } 2774c5c4113dSnw141292 UNLOCK_CONFIG(); 2775*8e228215Sdm199847 } 2776dd5829d1Sbaban 2777dd5829d1Sbaban if (retcode != IDMAP_SUCCESS) { 2778c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2779c5c4113dSnw141292 goto out; 2780c5c4113dSnw141292 } 2781*8e228215Sdm199847 windomain = mapping->id1domain; 2782c5c4113dSnw141292 } 2783c5c4113dSnw141292 278462c60062Sbaban if (winname != NULL && mapping->id1.idmap_id_u.sid.prefix == NULL) { 2785c5c4113dSnw141292 retcode = lookup_name2sid(cache, winname, windomain, 2786c5c4113dSnw141292 &is_user, &mapping->id1.idmap_id_u.sid.prefix, 2787c5c4113dSnw141292 &mapping->id1.idmap_id_u.sid.rid, mapping); 2788c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2789c5c4113dSnw141292 goto out; 2790c5c4113dSnw141292 if (mapping->id2.idtype == IDMAP_POSIXID) 2791c5c4113dSnw141292 mapping->id2.idtype = is_user?IDMAP_UID:IDMAP_GID; 2792c5c4113dSnw141292 } 2793c5c4113dSnw141292 2794c5c4113dSnw141292 state.sid2pid_done = TRUE; 2795c5c4113dSnw141292 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 2796c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 2797c5c4113dSnw141292 goto out; 2798c5c4113dSnw141292 2799c5c4113dSnw141292 if (state.ad_nqueries) { 2800c5c4113dSnw141292 /* sid2name AD lookup */ 2801c5c4113dSnw141292 retcode = lookup_win_sid2name( 2802c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.prefix, 2803c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.rid, 2804*8e228215Sdm199847 &mapping->id1name, 2805*8e228215Sdm199847 &mapping->id1domain, 2806c5c4113dSnw141292 (int *)&idres.id.idtype); 2807c5c4113dSnw141292 2808c5c4113dSnw141292 idres.retcode = retcode; 2809c5c4113dSnw141292 } 2810c5c4113dSnw141292 2811c5c4113dSnw141292 state.sid2pid_done = TRUE; 2812c5c4113dSnw141292 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 2813c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 2814c5c4113dSnw141292 goto out; 2815c5c4113dSnw141292 2816c5c4113dSnw141292 /* Update cache */ 2817c5c4113dSnw141292 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 2818c5c4113dSnw141292 2819c5c4113dSnw141292 out: 2820c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 2821c5c4113dSnw141292 mapping->direction = idres.direction; 2822c5c4113dSnw141292 mapping->id2 = idres.id; 2823c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 282462c60062Sbaban } else { 282562c60062Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 2826c5c4113dSnw141292 } 2827c5c4113dSnw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 2828c5c4113dSnw141292 return (retcode); 2829c5c4113dSnw141292 } 2830c5c4113dSnw141292 2831c5c4113dSnw141292 idmap_retcode 2832c5c4113dSnw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 2833c5c4113dSnw141292 idmap_mapping *mapping, int is_user) { 2834c5c4113dSnw141292 idmap_id_res idres; 2835c5c4113dSnw141292 lookup_state_t state; 2836c5c4113dSnw141292 struct passwd pwd; 2837c5c4113dSnw141292 struct group grp; 2838c5c4113dSnw141292 char buf[1024]; 2839c5c4113dSnw141292 int errnum; 2840c5c4113dSnw141292 idmap_retcode retcode; 2841c5c4113dSnw141292 const char *unixname; 2842c5c4113dSnw141292 const char *me = "get_u2w_mapping"; 2843c5c4113dSnw141292 2844c5c4113dSnw141292 /* 2845c5c4113dSnw141292 * In order to re-use the pid2sid code, we convert 2846c5c4113dSnw141292 * our input data into structs that are expected by 2847c5c4113dSnw141292 * pid2sid_first_pass. 2848c5c4113dSnw141292 */ 2849c5c4113dSnw141292 2850c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 2851c5c4113dSnw141292 (void) memset(&state, 0, sizeof (state)); 2852c5c4113dSnw141292 2853c5c4113dSnw141292 /* Copy data from request to result */ 2854651c0131Sbaban if (copy_mapping_request(mapping, request) < 0) { 2855651c0131Sbaban retcode = IDMAP_ERR_MEMORY; 2856651c0131Sbaban goto out; 2857651c0131Sbaban } 2858c5c4113dSnw141292 2859*8e228215Sdm199847 unixname = mapping->id1name; 2860c5c4113dSnw141292 2861c5c4113dSnw141292 if (unixname == NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 2862c5c4113dSnw141292 retcode = IDMAP_ERR_ARG; 2863c5c4113dSnw141292 goto out; 2864c5c4113dSnw141292 } 2865c5c4113dSnw141292 286662c60062Sbaban if (unixname != NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 2867c5c4113dSnw141292 /* Get uid/gid by name */ 2868c5c4113dSnw141292 if (is_user) { 2869c5c4113dSnw141292 errno = 0; 2870c5c4113dSnw141292 if (getpwnam_r(unixname, &pwd, buf, 2871c5c4113dSnw141292 sizeof (buf)) == NULL) { 2872c5c4113dSnw141292 errnum = errno; 2873c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2874c5c4113dSnw141292 "%s: getpwnam_r(%s) failed (%s).", 2875c5c4113dSnw141292 me, unixname, 2876c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2877c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2878c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2879c5c4113dSnw141292 goto out; 2880c5c4113dSnw141292 } 2881c5c4113dSnw141292 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 2882c5c4113dSnw141292 } else { 2883c5c4113dSnw141292 errno = 0; 2884c5c4113dSnw141292 if (getgrnam_r(unixname, &grp, buf, 2885c5c4113dSnw141292 sizeof (buf)) == NULL) { 2886c5c4113dSnw141292 errnum = errno; 2887c5c4113dSnw141292 idmapdlog(LOG_WARNING, 2888c5c4113dSnw141292 "%s: getgrnam_r(%s) failed (%s).", 2889c5c4113dSnw141292 me, unixname, 2890c5c4113dSnw141292 errnum?strerror(errnum):"not found"); 2891c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 2892c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 2893c5c4113dSnw141292 goto out; 2894c5c4113dSnw141292 } 2895c5c4113dSnw141292 mapping->id1.idmap_id_u.gid = grp.gr_gid; 2896c5c4113dSnw141292 } 2897c5c4113dSnw141292 } 2898c5c4113dSnw141292 2899c5c4113dSnw141292 state.pid2sid_done = TRUE; 2900c5c4113dSnw141292 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 2901c5c4113dSnw141292 is_user, 1); 2902c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 2903c5c4113dSnw141292 goto out; 2904c5c4113dSnw141292 2905c5c4113dSnw141292 /* Update cache */ 2906c5c4113dSnw141292 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 2907c5c4113dSnw141292 2908c5c4113dSnw141292 out: 2909c5c4113dSnw141292 mapping->direction = idres.direction; 2910c5c4113dSnw141292 mapping->id2 = idres.id; 2911c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 2912c5c4113dSnw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 2913c5c4113dSnw141292 return (retcode); 2914c5c4113dSnw141292 } 2915