14520Snw141292 /* 24520Snw141292 * CDDL HEADER START 34520Snw141292 * 44520Snw141292 * The contents of this file are subject to the terms of the 54520Snw141292 * Common Development and Distribution License (the "License"). 64520Snw141292 * You may not use this file except in compliance with the License. 74520Snw141292 * 84520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94520Snw141292 * or http://www.opensolaris.org/os/licensing. 104520Snw141292 * See the License for the specific language governing permissions 114520Snw141292 * and limitations under the License. 124520Snw141292 * 134520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 144520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 164520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 174520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 184520Snw141292 * 194520Snw141292 * CDDL HEADER END 204520Snw141292 */ 214520Snw141292 /* 224520Snw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 234520Snw141292 * Use is subject to license terms. 244520Snw141292 */ 254520Snw141292 264520Snw141292 #pragma ident "%Z%%M% %I% %E% SMI" 274520Snw141292 284520Snw141292 /* 294520Snw141292 * Database related utility routines 304520Snw141292 */ 314520Snw141292 324520Snw141292 #include <stdio.h> 334520Snw141292 #include <stdlib.h> 344520Snw141292 #include <string.h> 354520Snw141292 #include <errno.h> 364520Snw141292 #include <sys/types.h> 374520Snw141292 #include <sys/stat.h> 384520Snw141292 #include <rpc/rpc.h> 394520Snw141292 #include <sys/sid.h> 404520Snw141292 #include <time.h> 414520Snw141292 #include <pwd.h> 424520Snw141292 #include <grp.h> 43*4884Sjp151216 #include <pthread.h> 44*4884Sjp151216 #include <assert.h> 454520Snw141292 464520Snw141292 #include "idmapd.h" 474520Snw141292 #include "adutils.h" 484520Snw141292 #include "string.h" 494520Snw141292 #include "idmap_priv.h" 504520Snw141292 51*4884Sjp151216 524520Snw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 534520Snw141292 sqlite_vm **, int *, int, const char ***); 544864Sbaban static idmap_retcode lookup_wksids_name2sid(const char *, char **, 554864Sbaban idmap_rid_t *, int *); 564520Snw141292 574520Snw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 584520Snw141292 594520Snw141292 #define EMPTY_STRING(str) (str == NULL || *str == 0) 604520Snw141292 614520Snw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 624520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 634520Snw141292 644520Snw141292 #define AVOID_NAMESERVICE(req)\ 654520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 664520Snw141292 674520Snw141292 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 684520Snw141292 694520Snw141292 #define LOCALRID_MIN 1000 704520Snw141292 714520Snw141292 724520Snw141292 734520Snw141292 typedef enum init_db_option { 744520Snw141292 FAIL_IF_CORRUPT = 0, 754520Snw141292 REMOVE_IF_CORRUPT = 1 764520Snw141292 } init_db_option_t; 774520Snw141292 78*4884Sjp151216 /* 79*4884Sjp151216 * Thread specfic data to hold the database handles so that the 80*4884Sjp151216 * databaes are not opened and closed for every request. It also 81*4884Sjp151216 * contains the sqlite busy handler structure. 82*4884Sjp151216 */ 83*4884Sjp151216 84*4884Sjp151216 struct idmap_busy { 85*4884Sjp151216 const char *name; 86*4884Sjp151216 const int *delays; 87*4884Sjp151216 int delay_size; 88*4884Sjp151216 int total; 89*4884Sjp151216 int sec; 90*4884Sjp151216 }; 91*4884Sjp151216 92*4884Sjp151216 93*4884Sjp151216 typedef struct idmap_tsd { 94*4884Sjp151216 sqlite *db_db; 95*4884Sjp151216 sqlite *cache_db; 96*4884Sjp151216 struct idmap_busy cache_busy; 97*4884Sjp151216 struct idmap_busy db_busy; 98*4884Sjp151216 } idmap_tsd_t; 99*4884Sjp151216 100*4884Sjp151216 101*4884Sjp151216 102*4884Sjp151216 static const int cache_delay_table[] = 103*4884Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 104*4884Sjp151216 50, 50, 60, 70, 80, 90, 100}; 105*4884Sjp151216 106*4884Sjp151216 static const int db_delay_table[] = 107*4884Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 108*4884Sjp151216 109*4884Sjp151216 110*4884Sjp151216 static pthread_key_t idmap_tsd_key; 111*4884Sjp151216 112*4884Sjp151216 void 113*4884Sjp151216 idmap_tsd_destroy(void *key) 114*4884Sjp151216 { 115*4884Sjp151216 116*4884Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 117*4884Sjp151216 if (tsd) { 118*4884Sjp151216 if (tsd->db_db) 119*4884Sjp151216 (void) sqlite_close(tsd->db_db); 120*4884Sjp151216 if (tsd->cache_db) 121*4884Sjp151216 (void) sqlite_close(tsd->cache_db); 122*4884Sjp151216 free(tsd); 123*4884Sjp151216 } 124*4884Sjp151216 } 125*4884Sjp151216 126*4884Sjp151216 int 127*4884Sjp151216 idmap_init_tsd_key(void) { 128*4884Sjp151216 129*4884Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 130*4884Sjp151216 } 131*4884Sjp151216 132*4884Sjp151216 133*4884Sjp151216 134*4884Sjp151216 idmap_tsd_t * 135*4884Sjp151216 idmap_get_tsd(void) 136*4884Sjp151216 { 137*4884Sjp151216 idmap_tsd_t *tsd; 138*4884Sjp151216 139*4884Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 140*4884Sjp151216 /* No thread specific data so create it */ 141*4884Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 142*4884Sjp151216 /* Initialize thread specific data */ 143*4884Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 144*4884Sjp151216 /* save the trhread specific data */ 145*4884Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 146*4884Sjp151216 /* Can't store key */ 147*4884Sjp151216 free(tsd); 148*4884Sjp151216 tsd = NULL; 149*4884Sjp151216 } 150*4884Sjp151216 } else { 151*4884Sjp151216 tsd = NULL; 152*4884Sjp151216 } 153*4884Sjp151216 } 154*4884Sjp151216 155*4884Sjp151216 return (tsd); 156*4884Sjp151216 } 157*4884Sjp151216 158*4884Sjp151216 1594520Snw141292 1604520Snw141292 /* 1614520Snw141292 * Initialize 'dbname' using 'sql' 1624520Snw141292 */ 1634520Snw141292 static int 1644520Snw141292 init_db_instance(const char *dbname, const char *sql, init_db_option_t opt, 1654520Snw141292 int *new_db_created) 1664520Snw141292 { 1674520Snw141292 int rc = 0; 1684520Snw141292 int tries = 0; 1694520Snw141292 sqlite *db = NULL; 1704520Snw141292 char *str = NULL; 1714520Snw141292 1724520Snw141292 if (new_db_created != NULL) 1734520Snw141292 *new_db_created = 0; 1744520Snw141292 1754520Snw141292 db = sqlite_open(dbname, 0600, &str); 1764520Snw141292 while (db == NULL) { 1774520Snw141292 idmapdlog(LOG_ERR, 1784520Snw141292 "Error creating database %s (%s)", 1794520Snw141292 dbname, CHECK_NULL(str)); 1804520Snw141292 sqlite_freemem(str); 1814520Snw141292 if (opt == FAIL_IF_CORRUPT || opt != REMOVE_IF_CORRUPT || 1824520Snw141292 tries > 0) 1834520Snw141292 return (-1); 1844520Snw141292 1854520Snw141292 tries++; 1864520Snw141292 (void) unlink(dbname); 1874520Snw141292 db = sqlite_open(dbname, 0600, &str); 1884520Snw141292 } 1894520Snw141292 1904520Snw141292 sqlite_busy_timeout(db, 3000); 1914520Snw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &str); 1924520Snw141292 if (SQLITE_OK != rc) { 1934520Snw141292 idmapdlog(LOG_ERR, "Cannot begin database transaction (%s)", 1944520Snw141292 str); 1954520Snw141292 sqlite_freemem(str); 1964520Snw141292 sqlite_close(db); 1974520Snw141292 return (1); 1984520Snw141292 } 1994520Snw141292 2004520Snw141292 switch (sqlite_exec(db, sql, NULL, NULL, &str)) { 2014520Snw141292 case SQLITE_ERROR: 2024520Snw141292 /* 2034520Snw141292 * This is the normal situation: CREATE probably failed because tables 2044520Snw141292 * already exist. It may indicate an error in SQL as well, but we cannot 2054520Snw141292 * tell. 2064520Snw141292 */ 2074520Snw141292 sqlite_freemem(str); 2084520Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 2094520Snw141292 NULL, NULL, &str); 2104520Snw141292 break; 2114520Snw141292 case SQLITE_OK: 2124520Snw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", 2134520Snw141292 NULL, NULL, &str); 2144520Snw141292 idmapdlog(LOG_INFO, 2154520Snw141292 "Database created at %s", dbname); 2164520Snw141292 2174520Snw141292 if (new_db_created != NULL) 2184520Snw141292 *new_db_created = 1; 2194520Snw141292 break; 2204520Snw141292 default: 2214520Snw141292 idmapdlog(LOG_ERR, 2224520Snw141292 "Error initializing database %s (%s)", 2234520Snw141292 dbname, str); 2244520Snw141292 sqlite_freemem(str); 2254520Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", 2264520Snw141292 NULL, NULL, &str); 2274520Snw141292 break; 2284520Snw141292 } 2294520Snw141292 2304520Snw141292 if (SQLITE_OK != rc) { 2314520Snw141292 /* this is bad - database may be left in a locked state */ 2324520Snw141292 idmapdlog(LOG_ERR, 2334520Snw141292 "Error closing transaction (%s)", str); 2344520Snw141292 sqlite_freemem(str); 2354520Snw141292 } 2364520Snw141292 2374520Snw141292 (void) sqlite_close(db); 2384520Snw141292 return (rc); 2394520Snw141292 } 2404520Snw141292 241*4884Sjp151216 242*4884Sjp151216 /* 243*4884Sjp151216 * This is the SQLite database busy handler that retries the SQL 244*4884Sjp151216 * operation until it is successful. 245*4884Sjp151216 */ 246*4884Sjp151216 int 247*4884Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 248*4884Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 249*4884Sjp151216 { 250*4884Sjp151216 struct idmap_busy *busy = arg; 251*4884Sjp151216 int delay; 252*4884Sjp151216 struct timespec rqtp; 253*4884Sjp151216 254*4884Sjp151216 if (count == 1) { 255*4884Sjp151216 busy->total = 0; 256*4884Sjp151216 busy->sec = 2; 257*4884Sjp151216 } 258*4884Sjp151216 if (busy->total > 1000 * busy->sec) { 259*4884Sjp151216 idmapdlog(LOG_ERR, 260*4884Sjp151216 "Thread %d waited %d sec for the %s database", 261*4884Sjp151216 pthread_self(), busy->sec, busy->name); 262*4884Sjp151216 busy->sec++; 263*4884Sjp151216 } 264*4884Sjp151216 265*4884Sjp151216 if (count <= busy->delay_size) { 266*4884Sjp151216 delay = busy->delays[count-1]; 267*4884Sjp151216 } else { 268*4884Sjp151216 delay = busy->delays[busy->delay_size - 1]; 269*4884Sjp151216 } 270*4884Sjp151216 busy->total += delay; 271*4884Sjp151216 rqtp.tv_sec = 0; 272*4884Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 273*4884Sjp151216 (void) nanosleep(&rqtp, NULL); 274*4884Sjp151216 return (1); 275*4884Sjp151216 } 276*4884Sjp151216 277*4884Sjp151216 2784520Snw141292 /* 2794520Snw141292 * Get the database handle 2804520Snw141292 */ 2814520Snw141292 idmap_retcode 2824520Snw141292 get_db_handle(sqlite **db) { 2834520Snw141292 char *errmsg; 284*4884Sjp151216 idmap_tsd_t *tsd; 2854520Snw141292 2864520Snw141292 /* 287*4884Sjp151216 * Retrieve the db handle from thread-specific storage 2884520Snw141292 * If none exists, open and store in thread-specific storage. 2894520Snw141292 */ 290*4884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 2914520Snw141292 idmapdlog(LOG_ERR, 292*4884Sjp151216 "Error getting thread specific data for %s", 293*4884Sjp151216 IDMAP_DBNAME); 294*4884Sjp151216 return (IDMAP_ERR_MEMORY); 2954520Snw141292 } 296*4884Sjp151216 297*4884Sjp151216 if (tsd->db_db == NULL) { 298*4884Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 299*4884Sjp151216 if (tsd->db_db == NULL) { 300*4884Sjp151216 idmapdlog(LOG_ERR, 301*4884Sjp151216 "Error opening database %s (%s)", 302*4884Sjp151216 IDMAP_DBNAME, CHECK_NULL(errmsg)); 303*4884Sjp151216 sqlite_freemem(errmsg); 304*4884Sjp151216 return (IDMAP_ERR_INTERNAL); 305*4884Sjp151216 } 306*4884Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 307*4884Sjp151216 tsd->db_busy.delays = db_delay_table; 308*4884Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 309*4884Sjp151216 sizeof (int); 310*4884Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 311*4884Sjp151216 &tsd->db_busy); 312*4884Sjp151216 } 313*4884Sjp151216 *db = tsd->db_db; 3144520Snw141292 return (IDMAP_SUCCESS); 3154520Snw141292 } 3164520Snw141292 3174520Snw141292 /* 3184520Snw141292 * Get the cache handle 3194520Snw141292 */ 3204520Snw141292 idmap_retcode 321*4884Sjp151216 get_cache_handle(sqlite **cache) { 3224520Snw141292 char *errmsg; 323*4884Sjp151216 idmap_tsd_t *tsd; 3244520Snw141292 3254520Snw141292 /* 326*4884Sjp151216 * Retrieve the db handle from thread-specific storage 3274520Snw141292 * If none exists, open and store in thread-specific storage. 3284520Snw141292 */ 329*4884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 3304520Snw141292 idmapdlog(LOG_ERR, 331*4884Sjp151216 "Error getting thread specific data for %s", 332*4884Sjp151216 IDMAP_DBNAME); 333*4884Sjp151216 return (IDMAP_ERR_MEMORY); 3344520Snw141292 } 335*4884Sjp151216 336*4884Sjp151216 if (tsd->cache_db == NULL) { 337*4884Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 338*4884Sjp151216 if (tsd->cache_db == NULL) { 339*4884Sjp151216 idmapdlog(LOG_ERR, 340*4884Sjp151216 "Error opening database %s (%s)", 341*4884Sjp151216 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 342*4884Sjp151216 sqlite_freemem(errmsg); 343*4884Sjp151216 return (IDMAP_ERR_INTERNAL); 344*4884Sjp151216 } 345*4884Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 346*4884Sjp151216 tsd->cache_busy.delays = cache_delay_table; 347*4884Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 348*4884Sjp151216 sizeof (int); 349*4884Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 350*4884Sjp151216 &tsd->cache_busy); 351*4884Sjp151216 } 352*4884Sjp151216 *cache = tsd->cache_db; 3534520Snw141292 return (IDMAP_SUCCESS); 3544520Snw141292 } 3554520Snw141292 3564520Snw141292 #define CACHE_SQL\ 3574520Snw141292 "CREATE TABLE idmap_cache ("\ 3584520Snw141292 " sidprefix TEXT,"\ 3594520Snw141292 " rid INTEGER,"\ 3604520Snw141292 " windomain TEXT,"\ 3614520Snw141292 " winname TEXT,"\ 3624520Snw141292 " pid INTEGER,"\ 3634520Snw141292 " unixname TEXT,"\ 3644520Snw141292 " is_user INTEGER,"\ 3654520Snw141292 " w2u INTEGER,"\ 3664520Snw141292 " u2w INTEGER,"\ 3674520Snw141292 " expiration INTEGER"\ 3684520Snw141292 ");"\ 3694520Snw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache"\ 3704520Snw141292 " (sidprefix, rid, w2u);"\ 3714520Snw141292 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache"\ 3724520Snw141292 " (pid, is_user, u2w);"\ 3734520Snw141292 "CREATE TABLE name_cache ("\ 3744520Snw141292 " sidprefix TEXT,"\ 3754520Snw141292 " rid INTEGER,"\ 3764520Snw141292 " name TEXT,"\ 3774520Snw141292 " domain TEXT,"\ 3784520Snw141292 " type INTEGER,"\ 3794520Snw141292 " expiration INTEGER"\ 3804520Snw141292 ");"\ 3814520Snw141292 "CREATE UNIQUE INDEX name_cache_sid ON name_cache"\ 3824520Snw141292 " (sidprefix, rid);" 3834520Snw141292 3844520Snw141292 #define DB_SQL\ 3854520Snw141292 "CREATE TABLE namerules ("\ 3864520Snw141292 " is_user INTEGER NOT NULL,"\ 3874520Snw141292 " windomain TEXT,"\ 3884520Snw141292 " winname TEXT NOT NULL,"\ 3894520Snw141292 " is_nt4 INTEGER NOT NULL,"\ 3904520Snw141292 " unixname NOT NULL,"\ 3914520Snw141292 " w2u_order INTEGER,"\ 3924520Snw141292 " u2w_order INTEGER"\ 3934520Snw141292 ");"\ 3944520Snw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules"\ 3954520Snw141292 " (winname, windomain, is_user, w2u_order);"\ 3964520Snw141292 "CREATE UNIQUE INDEX namerules_u2w ON namerules"\ 3974520Snw141292 " (unixname, is_user, u2w_order);" 3984520Snw141292 3994520Snw141292 /* 4004520Snw141292 * Initialize cache and db 4014520Snw141292 */ 4024520Snw141292 int 4034520Snw141292 init_dbs() { 4044520Snw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 4054520Snw141292 if (init_db_instance(IDMAP_DBNAME, DB_SQL, FAIL_IF_CORRUPT, NULL) < 0) 4064520Snw141292 return (-1); 4074520Snw141292 4084520Snw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 4094520Snw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_SQL, REMOVE_IF_CORRUPT, 4104520Snw141292 &_idmapdstate.new_eph_db) < 0) 4114520Snw141292 return (-1); 4124520Snw141292 4134520Snw141292 return (0); 4144520Snw141292 } 4154520Snw141292 4164520Snw141292 /* 4174520Snw141292 * Finalize databases 4184520Snw141292 */ 4194520Snw141292 void 4204520Snw141292 fini_dbs() { 4214520Snw141292 } 4224520Snw141292 4234520Snw141292 /* 4244520Snw141292 * This table is a listing of status codes that will returned to the 4254520Snw141292 * client when a SQL command fails with the corresponding error message. 4264520Snw141292 */ 4274520Snw141292 static msg_table_t sqlmsgtable[] = { 4284864Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 4294520Snw141292 "columns unixname, is_user, u2w_order are not unique"}, 4304864Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 4314520Snw141292 "columns winname, windomain, is_user, w2u_order are not unique"}, 4324520Snw141292 {-1, NULL} 4334520Snw141292 }; 4344520Snw141292 4354520Snw141292 /* 4364520Snw141292 * idmapd's version of string2stat to map SQLite messages to 4374520Snw141292 * status codes 4384520Snw141292 */ 4394520Snw141292 idmap_retcode 4404520Snw141292 idmapd_string2stat(const char *msg) { 4414520Snw141292 int i; 4424520Snw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 4434520Snw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 4444520Snw141292 return (sqlmsgtable[i].retcode); 4454520Snw141292 } 4464520Snw141292 return (IDMAP_ERR_OTHER); 4474520Snw141292 } 4484520Snw141292 4494520Snw141292 /* 4504520Snw141292 * Execute the given SQL statment without using any callbacks 4514520Snw141292 */ 4524520Snw141292 idmap_retcode 4534520Snw141292 sql_exec_no_cb(sqlite *db, char *sql) { 4544520Snw141292 char *errmsg = NULL; 455*4884Sjp151216 int r; 4564520Snw141292 idmap_retcode retcode; 4574520Snw141292 458*4884Sjp151216 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 459*4884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 4604520Snw141292 4614520Snw141292 if (r != SQLITE_OK) { 4624520Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 4634520Snw141292 sql, CHECK_NULL(errmsg)); 464*4884Sjp151216 retcode = idmapd_string2stat(errmsg); 4654864Sbaban if (errmsg != NULL) 4664520Snw141292 sqlite_freemem(errmsg); 4674520Snw141292 return (retcode); 4684520Snw141292 } 4694520Snw141292 4704520Snw141292 return (IDMAP_SUCCESS); 4714520Snw141292 } 4724520Snw141292 4734520Snw141292 /* 4744520Snw141292 * Generate expression that can be used in WHERE statements. 4754520Snw141292 * Examples: 4764520Snw141292 * <prefix> <col> <op> <value> <suffix> 4774520Snw141292 * "" "unixuser" "=" "foo" "AND" 4784520Snw141292 */ 4794520Snw141292 idmap_retcode 4804520Snw141292 gen_sql_expr_from_utf8str(const char *prefix, const char *col, 4814520Snw141292 const char *op, idmap_utf8str *value, 4824520Snw141292 const char *suffix, char **out) { 4834520Snw141292 char *str; 4844520Snw141292 idmap_stat retcode; 4854520Snw141292 4864520Snw141292 if (out == NULL) 4874520Snw141292 return (IDMAP_ERR_ARG); 4884520Snw141292 4894520Snw141292 if (value == NULL) 4904520Snw141292 return (IDMAP_SUCCESS); 4914520Snw141292 4924520Snw141292 retcode = idmap_utf82str(&str, 0, value); 4934520Snw141292 if (retcode != IDMAP_SUCCESS) 4944520Snw141292 return (retcode); 4954520Snw141292 4964520Snw141292 if (prefix == NULL) 4974520Snw141292 prefix = ""; 4984520Snw141292 if (suffix == NULL) 4994520Snw141292 suffix = ""; 5004520Snw141292 5014520Snw141292 *out = sqlite_mprintf("%s %s %s %Q %s", 5024520Snw141292 prefix, col, op, str, suffix); 5034520Snw141292 idmap_free(str); 5044520Snw141292 if (*out == NULL) 5054520Snw141292 return (IDMAP_ERR_MEMORY); 5064520Snw141292 return (IDMAP_SUCCESS); 5074520Snw141292 } 5084520Snw141292 5094520Snw141292 /* 5104520Snw141292 * Generate and execute SQL statement for LIST RPC calls 5114520Snw141292 */ 5124520Snw141292 idmap_retcode 5134520Snw141292 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 5144520Snw141292 list_svc_cb cb, void *result) { 5154520Snw141292 list_cb_data_t cb_data; 5164520Snw141292 char *errmsg = NULL; 517*4884Sjp151216 int r; 5184520Snw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 5194520Snw141292 5204520Snw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 5214520Snw141292 cb_data.result = result; 5224520Snw141292 cb_data.limit = limit; 5234520Snw141292 524*4884Sjp151216 525*4884Sjp151216 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 526*4884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 527*4884Sjp151216 switch (r) { 528*4884Sjp151216 case SQLITE_OK: 529*4884Sjp151216 retcode = IDMAP_SUCCESS; 530*4884Sjp151216 break; 531*4884Sjp151216 532*4884Sjp151216 default: 533*4884Sjp151216 retcode = IDMAP_ERR_INTERNAL; 534*4884Sjp151216 idmapdlog(LOG_ERR, 535*4884Sjp151216 "Database error during %s (%s)", 536*4884Sjp151216 sql, CHECK_NULL(errmsg)); 537*4884Sjp151216 break; 5384520Snw141292 } 5394864Sbaban if (errmsg != NULL) 5404520Snw141292 sqlite_freemem(errmsg); 5414520Snw141292 return (retcode); 5424520Snw141292 } 5434520Snw141292 5444520Snw141292 /* 5454520Snw141292 * This routine is called by callbacks that process the results of 5464520Snw141292 * LIST RPC calls to validate data and to allocate memory for 5474520Snw141292 * the result array. 5484520Snw141292 */ 5494520Snw141292 idmap_retcode 5504520Snw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 5514520Snw141292 int ncol, uchar_t **list, size_t valsize) { 5524520Snw141292 size_t nsize; 5534520Snw141292 void *tmplist; 5544520Snw141292 5554520Snw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 5564520Snw141292 return (IDMAP_NEXT); 5574520Snw141292 5584520Snw141292 if (argc < ncol || argv == NULL) { 5594520Snw141292 idmapdlog(LOG_ERR, "Invalid data"); 5604520Snw141292 return (IDMAP_ERR_INTERNAL); 5614520Snw141292 } 5624520Snw141292 5634520Snw141292 /* alloc in bulk to reduce number of reallocs */ 5644520Snw141292 if (cb_data->next >= cb_data->len) { 5654520Snw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 5664520Snw141292 tmplist = realloc(*list, nsize); 5674520Snw141292 if (tmplist == NULL) { 5684520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 5694520Snw141292 return (IDMAP_ERR_MEMORY); 5704520Snw141292 } 5714520Snw141292 *list = tmplist; 5724520Snw141292 (void) memset(*list + (cb_data->len * valsize), 0, 5734520Snw141292 SIZE_INCR * valsize); 5744520Snw141292 cb_data->len += SIZE_INCR; 5754520Snw141292 } 5764520Snw141292 return (IDMAP_SUCCESS); 5774520Snw141292 } 5784520Snw141292 5794520Snw141292 static idmap_retcode 5804520Snw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 5814520Snw141292 int direction, int *w2u_order, int *u2w_order) { 5824520Snw141292 5834520Snw141292 *w2u_order = 0; 5844520Snw141292 *u2w_order = 0; 5854520Snw141292 5864520Snw141292 /* 5874520Snw141292 * Windows to UNIX lookup order: 5884520Snw141292 * 1. winname@domain (or winname) to "" 5894520Snw141292 * 2. winname@domain (or winname) to unixname 5904520Snw141292 * 3. winname@* to "" 5914520Snw141292 * 4. winname@* to unixname 5924520Snw141292 * 5. *@domain (or *) to * 5934520Snw141292 * 6. *@domain (or *) to "" 5944520Snw141292 * 7. *@domain (or *) to unixname 5954520Snw141292 * 8. *@* to * 5964520Snw141292 * 9. *@* to "" 5974520Snw141292 * 10. *@* to unixname 5984520Snw141292 * 5994520Snw141292 * winname is a special case of winname@domain when domain is the 6004520Snw141292 * default domain. Similarly * is a special case of *@domain when 6014520Snw141292 * domain is the default domain. 6024520Snw141292 * 6034520Snw141292 * Note that "" has priority over specific names because "" inhibits 6044520Snw141292 * mappings and traditionally deny rules always had higher priority. 6054520Snw141292 */ 6064644Sbaban if (direction != IDMAP_DIRECTION_U2W) { 6074644Sbaban /* bi-directional or from windows to unix */ 6084520Snw141292 if (winname == NULL) 6094520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6104520Snw141292 else if (unixname == NULL) 6114520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6124520Snw141292 else if (EMPTY_NAME(winname)) 6134520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6144520Snw141292 else if (*winname == '*' && windomain && *windomain == '*') { 6154520Snw141292 if (*unixname == '*') 6164520Snw141292 *w2u_order = 8; 6174520Snw141292 else if (EMPTY_NAME(unixname)) 6184520Snw141292 *w2u_order = 9; 6194520Snw141292 else /* unixname == name */ 6204520Snw141292 *w2u_order = 10; 6214520Snw141292 } else if (*winname == '*') { 6224520Snw141292 if (*unixname == '*') 6234520Snw141292 *w2u_order = 5; 6244520Snw141292 else if (EMPTY_NAME(unixname)) 6254520Snw141292 *w2u_order = 6; 6264520Snw141292 else /* name */ 6274520Snw141292 *w2u_order = 7; 6284864Sbaban } else if (windomain != NULL && *windomain == '*') { 6294520Snw141292 /* winname == name */ 6304520Snw141292 if (*unixname == '*') 6314520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6324520Snw141292 else if (EMPTY_NAME(unixname)) 6334520Snw141292 *w2u_order = 3; 6344520Snw141292 else /* name */ 6354520Snw141292 *w2u_order = 4; 6364520Snw141292 } else { 6374520Snw141292 /* winname == name && windomain == null or name */ 6384520Snw141292 if (*unixname == '*') 6394520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 6404520Snw141292 else if (EMPTY_NAME(unixname)) 6414520Snw141292 *w2u_order = 1; 6424520Snw141292 else /* name */ 6434520Snw141292 *w2u_order = 2; 6444520Snw141292 } 6454520Snw141292 } 6464520Snw141292 6474520Snw141292 /* 6484520Snw141292 * 1. unixname to "" 6494520Snw141292 * 2. unixname to winname@domain (or winname) 6504520Snw141292 * 3. * to *@domain (or *) 6514520Snw141292 * 4. * to "" 6524520Snw141292 * 5. * to winname@domain (or winname) 6534520Snw141292 */ 6544644Sbaban if (direction != IDMAP_DIRECTION_W2U) { 6554644Sbaban /* bi-directional or from unix to windows */ 6564520Snw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 6574520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6584520Snw141292 else if (winname == NULL) 6594520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6604864Sbaban else if (windomain != NULL && *windomain == '*') 6614644Sbaban return (IDMAP_ERR_U2W_NAMERULE); 6624520Snw141292 else if (*unixname == '*') { 6634520Snw141292 if (*winname == '*') 6644520Snw141292 *u2w_order = 3; 6654520Snw141292 else if (EMPTY_NAME(winname)) 6664520Snw141292 *u2w_order = 4; 6674520Snw141292 else 6684520Snw141292 *u2w_order = 5; 6694520Snw141292 } else { 6704520Snw141292 if (*winname == '*') 6714520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 6724520Snw141292 else if (EMPTY_NAME(winname)) 6734520Snw141292 *u2w_order = 1; 6744520Snw141292 else 6754520Snw141292 *u2w_order = 2; 6764520Snw141292 } 6774520Snw141292 } 6784520Snw141292 return (IDMAP_SUCCESS); 6794520Snw141292 } 6804520Snw141292 6814520Snw141292 /* 6824520Snw141292 * Generate and execute SQL statement to add name-based mapping rule 6834520Snw141292 */ 6844520Snw141292 idmap_retcode 6854520Snw141292 add_namerule(sqlite *db, idmap_namerule *rule) { 6864520Snw141292 char *sql = NULL; 6874520Snw141292 idmap_stat retcode; 6884864Sbaban char *windomain = NULL, *winname = NULL, *dom = NULL; 6894520Snw141292 char *unixname = NULL; 6904520Snw141292 int w2u_order, u2w_order; 6914520Snw141292 char w2ubuf[11], u2wbuf[11]; 6924520Snw141292 6934520Snw141292 retcode = idmap_utf82str(&windomain, 0, &rule->windomain); 6944520Snw141292 if (retcode != IDMAP_SUCCESS) 6954520Snw141292 goto out; 6964520Snw141292 retcode = idmap_utf82str(&winname, 0, &rule->winname); 6974520Snw141292 if (retcode != IDMAP_SUCCESS) 6984520Snw141292 goto out; 6994520Snw141292 retcode = idmap_utf82str(&unixname, 0, &rule->unixname); 7004520Snw141292 if (retcode != IDMAP_SUCCESS) 7014520Snw141292 goto out; 7024520Snw141292 7034520Snw141292 retcode = get_namerule_order(winname, windomain, unixname, 7044520Snw141292 rule->direction, &w2u_order, &u2w_order); 7054520Snw141292 if (retcode != IDMAP_SUCCESS) 7064520Snw141292 goto out; 7074520Snw141292 7084520Snw141292 if (w2u_order) 7094520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 7104520Snw141292 if (u2w_order) 7114520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 7124520Snw141292 7134864Sbaban /* 7144864Sbaban * For the triggers on namerules table to work correctly: 7154864Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 7164864Sbaban * 2) Use "" instead of NULL for "no domain" 7174864Sbaban */ 7184864Sbaban 7194864Sbaban if (windomain != NULL) 7204864Sbaban dom = windomain; 7214864Sbaban else if (lookup_wksids_name2sid(winname, NULL, NULL, NULL) 7224864Sbaban == IDMAP_SUCCESS) { 7234864Sbaban /* well-known SIDs don't need domain */ 7244864Sbaban dom = ""; 7254864Sbaban } 7264520Snw141292 7274520Snw141292 RDLOCK_CONFIG(); 7284864Sbaban if (dom == NULL) { 7294864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain) 7304864Sbaban dom = _idmapdstate.cfg->pgcfg.mapping_domain; 7314864Sbaban else 7324864Sbaban dom = ""; 7334864Sbaban } 734*4884Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 7354520Snw141292 "(is_user, windomain, winname, is_nt4, " 7364520Snw141292 "unixname, w2u_order, u2w_order) " 7374520Snw141292 "VALUES(%d, %Q, %Q, %d, %Q, %q, %q);", 7384520Snw141292 rule->is_user?1:0, 7394520Snw141292 dom, 7404520Snw141292 winname, rule->is_nt4?1:0, 7414520Snw141292 unixname, 7424520Snw141292 w2u_order?w2ubuf:NULL, 7434520Snw141292 u2w_order?u2wbuf:NULL); 7444520Snw141292 UNLOCK_CONFIG(); 7454520Snw141292 7464520Snw141292 if (sql == NULL) { 7474520Snw141292 retcode = IDMAP_ERR_INTERNAL; 7484520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7494520Snw141292 goto out; 7504520Snw141292 } 7514520Snw141292 7524520Snw141292 retcode = sql_exec_no_cb(db, sql); 7534520Snw141292 7544520Snw141292 if (retcode == IDMAP_ERR_OTHER) 7554520Snw141292 retcode = IDMAP_ERR_CFG; 7564520Snw141292 7574520Snw141292 out: 7584864Sbaban if (windomain != NULL) 7594520Snw141292 idmap_free(windomain); 7604864Sbaban if (winname != NULL) 7614520Snw141292 idmap_free(winname); 7624864Sbaban if (unixname != NULL) 7634520Snw141292 idmap_free(unixname); 7644864Sbaban if (sql != NULL) 7654520Snw141292 sqlite_freemem(sql); 7664520Snw141292 return (retcode); 7674520Snw141292 } 7684520Snw141292 7694520Snw141292 /* 7704520Snw141292 * Flush name-based mapping rules 7714520Snw141292 */ 7724520Snw141292 idmap_retcode 7734520Snw141292 flush_namerules(sqlite *db, bool_t is_user) { 7744520Snw141292 char *sql = NULL; 7754520Snw141292 idmap_stat retcode; 7764520Snw141292 7774520Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 7784520Snw141292 "is_user = %d;", is_user?1:0); 7794520Snw141292 7804520Snw141292 if (sql == NULL) { 7814520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7824520Snw141292 return (IDMAP_ERR_MEMORY); 7834520Snw141292 } 7844520Snw141292 7854520Snw141292 retcode = sql_exec_no_cb(db, sql); 7864520Snw141292 7874520Snw141292 sqlite_freemem(sql); 7884520Snw141292 return (retcode); 7894520Snw141292 } 7904520Snw141292 7914520Snw141292 /* 7924520Snw141292 * Generate and execute SQL statement to remove a name-based mapping rule 7934520Snw141292 */ 7944520Snw141292 idmap_retcode 7954520Snw141292 rm_namerule(sqlite *db, idmap_namerule *rule) { 7964520Snw141292 char *sql = NULL; 7974520Snw141292 idmap_stat retcode; 7984520Snw141292 char *s_windomain = NULL, *s_winname = NULL; 7994520Snw141292 char *s_unixname = NULL; 8004520Snw141292 char buf[80]; 8014520Snw141292 8024520Snw141292 if (rule->direction < 0 && 8034520Snw141292 rule->windomain.idmap_utf8str_len < 1 && 8044520Snw141292 rule->winname.idmap_utf8str_len < 1 && 8054520Snw141292 rule->unixname.idmap_utf8str_len < 1) 8064520Snw141292 return (IDMAP_SUCCESS); 8074520Snw141292 8084520Snw141292 if (rule->direction < 0) { 8094520Snw141292 buf[0] = 0; 8104644Sbaban } else if (rule->direction == IDMAP_DIRECTION_BI) { 8114520Snw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 8124520Snw141292 " AND u2w_order > 0"); 8134644Sbaban } else if (rule->direction == IDMAP_DIRECTION_W2U) { 8144520Snw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 8154520Snw141292 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 8164644Sbaban } else if (rule->direction == IDMAP_DIRECTION_U2W) { 8174520Snw141292 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 8184520Snw141292 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 8194520Snw141292 } 8204520Snw141292 8214520Snw141292 retcode = IDMAP_ERR_INTERNAL; 8224520Snw141292 if (rule->windomain.idmap_utf8str_len > 0) { 8234520Snw141292 if (gen_sql_expr_from_utf8str("AND", "windomain", "=", 8244520Snw141292 &rule->windomain, 8254520Snw141292 "", &s_windomain) != IDMAP_SUCCESS) 8264520Snw141292 goto out; 8274520Snw141292 } 8284520Snw141292 8294520Snw141292 if (rule->winname.idmap_utf8str_len > 0) { 8304520Snw141292 if (gen_sql_expr_from_utf8str("AND", "winname", "=", 8314520Snw141292 &rule->winname, 8324520Snw141292 "", &s_winname) != IDMAP_SUCCESS) 8334520Snw141292 goto out; 8344520Snw141292 } 8354520Snw141292 8364520Snw141292 if (rule->unixname.idmap_utf8str_len > 0) { 8374520Snw141292 if (gen_sql_expr_from_utf8str("AND", "unixname", "=", 8384520Snw141292 &rule->unixname, 8394520Snw141292 "", &s_unixname) != IDMAP_SUCCESS) 8404520Snw141292 goto out; 8414520Snw141292 } 8424520Snw141292 8434520Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE " 8444520Snw141292 "is_user = %d %s %s %s %s;", 8454520Snw141292 rule->is_user?1:0, 8464520Snw141292 s_windomain?s_windomain:"", 8474520Snw141292 s_winname?s_winname:"", 8484520Snw141292 s_unixname?s_unixname:"", 8494520Snw141292 buf); 8504520Snw141292 8514520Snw141292 if (sql == NULL) { 8524520Snw141292 retcode = IDMAP_ERR_INTERNAL; 8534520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 8544520Snw141292 goto out; 8554520Snw141292 } 8564520Snw141292 8574520Snw141292 retcode = sql_exec_no_cb(db, sql); 8584520Snw141292 8594520Snw141292 out: 8604864Sbaban if (s_windomain != NULL) 8614520Snw141292 sqlite_freemem(s_windomain); 8624864Sbaban if (s_winname != NULL) 8634520Snw141292 sqlite_freemem(s_winname); 8644864Sbaban if (s_unixname != NULL) 8654520Snw141292 sqlite_freemem(s_unixname); 8664864Sbaban if (sql != NULL) 8674520Snw141292 sqlite_freemem(sql); 8684520Snw141292 return (retcode); 8694520Snw141292 } 8704520Snw141292 8714520Snw141292 /* 8724520Snw141292 * Compile the given SQL query and step just once. 8734520Snw141292 * 8744520Snw141292 * Input: 8754520Snw141292 * db - db handle 8764520Snw141292 * sql - SQL statement 8774520Snw141292 * 8784520Snw141292 * Output: 8794520Snw141292 * vm - virtual SQL machine 8804520Snw141292 * ncol - number of columns in the result 8814520Snw141292 * values - column values 8824520Snw141292 * 8834520Snw141292 * Return values: 8844520Snw141292 * IDMAP_SUCCESS 8854520Snw141292 * IDMAP_ERR_NOTFOUND 8864520Snw141292 * IDMAP_ERR_INTERNAL 8874520Snw141292 */ 8884520Snw141292 8894520Snw141292 static idmap_retcode 8904520Snw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 8914520Snw141292 int reqcol, const char ***values) { 8924520Snw141292 char *errmsg = NULL; 893*4884Sjp151216 int r; 894*4884Sjp151216 895*4884Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 8964520Snw141292 idmapdlog(LOG_ERR, 8974520Snw141292 "Database error during %s (%s)", 8984520Snw141292 sql, CHECK_NULL(errmsg)); 8994520Snw141292 sqlite_freemem(errmsg); 9004520Snw141292 return (IDMAP_ERR_INTERNAL); 9014520Snw141292 } 9024520Snw141292 903*4884Sjp151216 r = sqlite_step(*vm, ncol, values, NULL); 904*4884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 905*4884Sjp151216 906*4884Sjp151216 if (r == SQLITE_ROW) { 9074864Sbaban if (ncol != NULL && *ncol < reqcol) { 9084520Snw141292 (void) sqlite_finalize(*vm, NULL); 9094520Snw141292 *vm = NULL; 9104520Snw141292 return (IDMAP_ERR_INTERNAL); 9114520Snw141292 } 9124520Snw141292 /* Caller will call finalize after using the results */ 9134520Snw141292 return (IDMAP_SUCCESS); 9144520Snw141292 } else if (r == SQLITE_DONE) { 9154520Snw141292 (void) sqlite_finalize(*vm, NULL); 9164520Snw141292 *vm = NULL; 9174520Snw141292 return (IDMAP_ERR_NOTFOUND); 9184520Snw141292 } 9194520Snw141292 9204520Snw141292 (void) sqlite_finalize(*vm, &errmsg); 9214520Snw141292 *vm = NULL; 9224520Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", 923*4884Sjp151216 sql, CHECK_NULL(errmsg)); 9244520Snw141292 sqlite_freemem(errmsg); 9254520Snw141292 return (IDMAP_ERR_INTERNAL); 9264520Snw141292 } 9274520Snw141292 9284864Sbaban /* 9294864Sbaban * Table for well-known SIDs. 9304864Sbaban * 9314864Sbaban * Background: 9324864Sbaban * 9334864Sbaban * These well-known principals are stored (as of Windows Server 2003) under: 9344864Sbaban * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 9354864Sbaban * They belong to objectClass "foreignSecurityPrincipal". They don't have 9364864Sbaban * "samAccountName" nor "userPrincipalName" attributes. Their names are 9374864Sbaban * available in "cn" and "name" attributes. Some of these principals have a 9384864Sbaban * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 9394864Sbaban * these duplicate entries have the stringified SID in the "name" and "cn" 9404864Sbaban * attributes instead of the actual name. 9414864Sbaban * 9424864Sbaban * These principals remain constant across all operating systems. Using 9434864Sbaban * a hard-coded table here improves performance and avoids additional 9444864Sbaban * complexity in the AD lookup code in adutils.c 9454864Sbaban * 9464864Sbaban * Currently we don't support localization of well-known SID names, 9474864Sbaban * unlike Windows. 9484864Sbaban * 9494864Sbaban * Note that other well-known SIDs (i.e. S-1-5-<domain>-<w-k RID> and 9504864Sbaban * S-1-5-32-<w-k RID>) are not stored here because AD does have normal 9514864Sbaban * user/group objects for these objects and can be looked up using the 9524864Sbaban * existing AD lookup code. 9534864Sbaban */ 9544864Sbaban static wksids_table_t wksids[] = { 9554864Sbaban {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 9564864Sbaban {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 9574864Sbaban {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 9584864Sbaban {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 9594864Sbaban {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 9604864Sbaban {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 9614864Sbaban {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 9624864Sbaban {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 9634864Sbaban {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 9644864Sbaban {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 9654864Sbaban {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 9664864Sbaban {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 9674864Sbaban {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 9684864Sbaban {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 9694864Sbaban {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 9704864Sbaban {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 9714864Sbaban {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 9724864Sbaban {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 9734864Sbaban {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 9744864Sbaban {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 9754864Sbaban {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 9764864Sbaban {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 9774864Sbaban {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 9784864Sbaban {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 9794864Sbaban {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 9804864Sbaban {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 9814864Sbaban {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 9824520Snw141292 }; 9834520Snw141292 9844520Snw141292 static idmap_retcode 9854520Snw141292 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) { 9864520Snw141292 int i; 9874864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 9884864Sbaban if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 9894864Sbaban (strcasecmp(wksids[i].sidprefix, 9904864Sbaban req->id1.idmap_id_u.sid.prefix) == 0)) { 9914864Sbaban 9924864Sbaban if (wksids[i].pid == SENTINEL_PID) 9934864Sbaban /* Not mapped, break */ 9944864Sbaban break; 9954864Sbaban else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 9964864Sbaban continue; 9974864Sbaban 9984520Snw141292 switch (req->id2.idtype) { 9994520Snw141292 case IDMAP_UID: 10004864Sbaban if (wksids[i].is_user == 0) 10014864Sbaban continue; 10024864Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 10034864Sbaban res->direction = wksids[i].direction; 10044520Snw141292 return (IDMAP_SUCCESS); 10054520Snw141292 case IDMAP_GID: 10064864Sbaban if (wksids[i].is_user == 1) 10074864Sbaban continue; 10084864Sbaban res->id.idmap_id_u.gid = wksids[i].pid; 10094864Sbaban res->direction = wksids[i].direction; 10104520Snw141292 return (IDMAP_SUCCESS); 10114520Snw141292 case IDMAP_POSIXID: 10124864Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 10134864Sbaban res->id.idtype = (!wksids[i].is_user)? 10144520Snw141292 IDMAP_GID:IDMAP_UID; 10154864Sbaban res->direction = wksids[i].direction; 10164520Snw141292 return (IDMAP_SUCCESS); 10174520Snw141292 default: 10184520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 10194520Snw141292 } 10204520Snw141292 } 10214520Snw141292 } 10224520Snw141292 return (IDMAP_ERR_NOTFOUND); 10234520Snw141292 } 10244520Snw141292 10254520Snw141292 static idmap_retcode 10264520Snw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) { 10274520Snw141292 int i; 10284864Sbaban if (req->id2.idtype != IDMAP_SID) 10294864Sbaban return (IDMAP_ERR_NOTSUPPORTED); 10304864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10314864Sbaban if (wksids[i].pid == req->id1.idmap_id_u.uid && 10324864Sbaban wksids[i].is_user == is_user && 10334864Sbaban wksids[i].direction != IDMAP_DIRECTION_W2U) { 10344864Sbaban res->id.idmap_id_u.sid.rid = wksids[i].rid; 10354864Sbaban res->id.idmap_id_u.sid.prefix = 10364864Sbaban strdup(wksids[i].sidprefix); 10374864Sbaban if (res->id.idmap_id_u.sid.prefix == NULL) { 10384864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10394864Sbaban return (IDMAP_ERR_MEMORY); 10404520Snw141292 } 10414864Sbaban res->direction = wksids[i].direction; 10424864Sbaban return (IDMAP_SUCCESS); 10434864Sbaban } 10444864Sbaban } 10454864Sbaban return (IDMAP_ERR_NOTFOUND); 10464864Sbaban } 10474864Sbaban 10484864Sbaban static idmap_retcode 10494864Sbaban lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 10504864Sbaban int *type) { 10514864Sbaban int i; 10524864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10534864Sbaban if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 10544864Sbaban wksids[i].rid == rid) { 10554864Sbaban if ((*name = strdup(wksids[i].winname)) == NULL) { 10564864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10574864Sbaban return (IDMAP_ERR_MEMORY); 10584864Sbaban } 10594864Sbaban *type = (wksids[i].is_user)? 10604864Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 10614864Sbaban return (IDMAP_SUCCESS); 10624864Sbaban } 10634864Sbaban } 10644864Sbaban return (IDMAP_ERR_NOTFOUND); 10654864Sbaban } 10664864Sbaban 10674864Sbaban static idmap_retcode 10684864Sbaban lookup_wksids_name2sid(const char *name, char **sidprefix, idmap_rid_t *rid, 10694864Sbaban int *type) { 10704864Sbaban int i; 10714864Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 10724864Sbaban if (strcasecmp(wksids[i].winname, name) == 0) { 10734864Sbaban if (sidprefix != NULL && (*sidprefix = 10744864Sbaban strdup(wksids[i].sidprefix)) == NULL) { 10754864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 10764864Sbaban return (IDMAP_ERR_MEMORY); 10774864Sbaban } 10784864Sbaban if (type != NULL) 10794864Sbaban *type = (wksids[i].is_user)? 10804864Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 10814864Sbaban if (rid != NULL) 10824864Sbaban *rid = wksids[i].rid; 10834864Sbaban return (IDMAP_SUCCESS); 10844520Snw141292 } 10854520Snw141292 } 10864520Snw141292 return (IDMAP_ERR_NOTFOUND); 10874520Snw141292 } 10884520Snw141292 10894520Snw141292 static idmap_retcode 10904520Snw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 10914520Snw141292 char *end; 10924520Snw141292 char *sql = NULL; 10934520Snw141292 const char **values; 10944520Snw141292 sqlite_vm *vm = NULL; 10954520Snw141292 int ncol, is_user; 10964520Snw141292 uid_t pid; 10974520Snw141292 idmap_utf8str *str; 10984520Snw141292 time_t curtime, exp; 10994520Snw141292 idmap_retcode retcode; 11004520Snw141292 11014520Snw141292 /* Current time */ 11024520Snw141292 errno = 0; 11034520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 11044520Snw141292 idmapdlog(LOG_ERR, 11054520Snw141292 "Failed to get current time (%s)", 11064520Snw141292 strerror(errno)); 11074520Snw141292 retcode = IDMAP_ERR_INTERNAL; 11084520Snw141292 goto out; 11094520Snw141292 } 11104520Snw141292 11114520Snw141292 /* SQL to lookup the cache */ 11124520Snw141292 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 11134520Snw141292 "FROM idmap_cache WHERE " 11144520Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 11154520Snw141292 "(pid >= 2147483648 OR " 11164520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 11174520Snw141292 "expiration > %d));", 11184520Snw141292 req->id1.idmap_id_u.sid.prefix, 11194520Snw141292 req->id1.idmap_id_u.sid.rid, 11204520Snw141292 curtime); 11214520Snw141292 if (sql == NULL) { 11224520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 11234520Snw141292 retcode = IDMAP_ERR_MEMORY; 11244520Snw141292 goto out; 11254520Snw141292 } 11264520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 11274520Snw141292 sqlite_freemem(sql); 11284520Snw141292 11294520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 11304520Snw141292 goto out; 11314520Snw141292 } else if (retcode == IDMAP_SUCCESS) { 11324520Snw141292 /* sanity checks */ 11334520Snw141292 if (values[0] == NULL || values[1] == NULL) { 11344520Snw141292 retcode = IDMAP_ERR_CACHE; 11354520Snw141292 goto out; 11364520Snw141292 } 11374520Snw141292 11384520Snw141292 pid = strtoul(values[0], &end, 10); 11394520Snw141292 is_user = strncmp(values[1], "0", 2)?1:0; 11404520Snw141292 11414520Snw141292 /* 11424520Snw141292 * We may have an expired ephemeral mapping. Consider 11434520Snw141292 * the expired entry as valid if we are not going to 11444520Snw141292 * perform name-based mapping. But do not renew the 11454520Snw141292 * expiration. 11464520Snw141292 * If we will be doing name-based mapping then store the 11474520Snw141292 * ephemeral pid in the result so that we can use it 11484520Snw141292 * if we end up doing dynamic mapping again. 11494520Snw141292 */ 11504520Snw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 11514520Snw141292 !AVOID_NAMESERVICE(req)) { 11524864Sbaban if (IS_EPHEMERAL(pid) && values[2] != NULL) { 11534520Snw141292 exp = strtoll(values[2], &end, 10); 11544520Snw141292 if (exp && exp <= curtime) { 11554520Snw141292 /* Store the ephemeral pid */ 11564520Snw141292 res->id.idmap_id_u.uid = pid; 11574520Snw141292 res->id.idtype = is_user? 11584520Snw141292 IDMAP_UID:IDMAP_GID; 11594644Sbaban res->direction = IDMAP_DIRECTION_BI; 11604520Snw141292 req->direction |= is_user? 11614520Snw141292 _IDMAP_F_EXP_EPH_UID: 11624520Snw141292 _IDMAP_F_EXP_EPH_GID; 11634520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 11644520Snw141292 goto out; 11654520Snw141292 } 11664520Snw141292 } 11674520Snw141292 } 11684520Snw141292 11694520Snw141292 switch (req->id2.idtype) { 11704520Snw141292 case IDMAP_UID: 11714520Snw141292 if (!is_user) 11724520Snw141292 retcode = IDMAP_ERR_NOTUSER; 11734520Snw141292 else 11744520Snw141292 res->id.idmap_id_u.uid = pid; 11754520Snw141292 break; 11764520Snw141292 case IDMAP_GID: 11774520Snw141292 if (is_user) 11784520Snw141292 retcode = IDMAP_ERR_NOTGROUP; 11794520Snw141292 else 11804520Snw141292 res->id.idmap_id_u.gid = pid; 11814520Snw141292 break; 11824520Snw141292 case IDMAP_POSIXID: 11834520Snw141292 res->id.idmap_id_u.uid = pid; 11844520Snw141292 res->id.idtype = (is_user)?IDMAP_UID:IDMAP_GID; 11854520Snw141292 break; 11864520Snw141292 default: 11874520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 11884520Snw141292 break; 11894520Snw141292 } 11904520Snw141292 } 11914520Snw141292 11924520Snw141292 out: 11934520Snw141292 if (retcode == IDMAP_SUCCESS) { 11944864Sbaban if (values[4] != NULL) 11954520Snw141292 res->direction = 11964644Sbaban (strtol(values[4], &end, 10) == 0)? 11974644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 11984520Snw141292 else 11994644Sbaban res->direction = IDMAP_DIRECTION_W2U; 12004520Snw141292 12014864Sbaban if (values[3] != NULL) { 12024520Snw141292 str = &req->id2name; 12034520Snw141292 retcode = idmap_str2utf8(&str, values[3], 0); 12044520Snw141292 if (retcode != IDMAP_SUCCESS) { 12054520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12064520Snw141292 retcode = IDMAP_ERR_MEMORY; 12074520Snw141292 } 12084520Snw141292 } 12094520Snw141292 } 12104864Sbaban if (vm != NULL) 12114520Snw141292 (void) sqlite_finalize(vm, NULL); 12124520Snw141292 return (retcode); 12134520Snw141292 } 12144520Snw141292 12154520Snw141292 static idmap_retcode 12164864Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 12174520Snw141292 char **name, char **domain, int *type) { 12184520Snw141292 char *end; 12194520Snw141292 char *sql = NULL; 12204520Snw141292 const char **values; 12214520Snw141292 sqlite_vm *vm = NULL; 12224520Snw141292 int ncol; 12234520Snw141292 time_t curtime; 12244520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 12254520Snw141292 12264520Snw141292 /* Get current time */ 12274520Snw141292 errno = 0; 12284520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 12294520Snw141292 idmapdlog(LOG_ERR, 12304520Snw141292 "Failed to get current time (%s)", 12314520Snw141292 strerror(errno)); 12324520Snw141292 retcode = IDMAP_ERR_INTERNAL; 12334520Snw141292 goto out; 12344520Snw141292 } 12354520Snw141292 12364520Snw141292 /* SQL to lookup the cache */ 12374520Snw141292 sql = sqlite_mprintf("SELECT name, domain, type FROM name_cache WHERE " 12384520Snw141292 "sidprefix = %Q AND rid = %u AND " 12394520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 12404520Snw141292 "expiration > %d);", 12414520Snw141292 sidprefix, rid, curtime); 12424520Snw141292 if (sql == NULL) { 12434520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12444520Snw141292 retcode = IDMAP_ERR_MEMORY; 12454520Snw141292 goto out; 12464520Snw141292 } 12474520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 12484520Snw141292 sqlite_freemem(sql); 12494520Snw141292 12504520Snw141292 if (retcode == IDMAP_SUCCESS) { 12514864Sbaban if (type != NULL) { 12524520Snw141292 if (values[2] == NULL) { 12534520Snw141292 retcode = IDMAP_ERR_CACHE; 12544520Snw141292 goto out; 12554520Snw141292 } 12564520Snw141292 *type = strtol(values[2], &end, 10); 12574520Snw141292 } 12584520Snw141292 12594864Sbaban if (name != NULL && values[0] != NULL) { 12604520Snw141292 if ((*name = strdup(values[0])) == NULL) { 12614520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12624520Snw141292 retcode = IDMAP_ERR_MEMORY; 12634520Snw141292 goto out; 12644520Snw141292 } 12654520Snw141292 } 12664520Snw141292 12674864Sbaban if (domain != NULL && values[1] != NULL) { 12684520Snw141292 if ((*domain = strdup(values[1])) == NULL) { 12694864Sbaban if (name != NULL && *name) { 12704520Snw141292 free(*name); 12714520Snw141292 *name = NULL; 12724520Snw141292 } 12734520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 12744520Snw141292 retcode = IDMAP_ERR_MEMORY; 12754520Snw141292 goto out; 12764520Snw141292 } 12774520Snw141292 } 12784520Snw141292 } 12794520Snw141292 12804520Snw141292 out: 12814864Sbaban if (vm != NULL) 12824520Snw141292 (void) sqlite_finalize(vm, NULL); 12834520Snw141292 return (retcode); 12844520Snw141292 } 12854520Snw141292 12864520Snw141292 static idmap_retcode 12874520Snw141292 verify_type(idmap_id_type idtype, int type, idmap_id_res *res) { 12884520Snw141292 switch (idtype) { 12894520Snw141292 case IDMAP_UID: 12904520Snw141292 if (type != _IDMAP_T_USER) 12914520Snw141292 return (IDMAP_ERR_NOTUSER); 12924520Snw141292 res->id.idtype = IDMAP_UID; 12934520Snw141292 break; 12944520Snw141292 case IDMAP_GID: 12954520Snw141292 if (type != _IDMAP_T_GROUP) 12964520Snw141292 return (IDMAP_ERR_NOTGROUP); 12974520Snw141292 res->id.idtype = IDMAP_GID; 12984520Snw141292 break; 12994520Snw141292 case IDMAP_POSIXID: 13004520Snw141292 if (type == _IDMAP_T_USER) 13014520Snw141292 res->id.idtype = IDMAP_UID; 13024520Snw141292 else if (type == _IDMAP_T_GROUP) 13034520Snw141292 res->id.idtype = IDMAP_GID; 13044520Snw141292 else 13054520Snw141292 return (IDMAP_ERR_SID); 13064520Snw141292 break; 13074520Snw141292 default: 13084520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 13094520Snw141292 } 13104520Snw141292 return (IDMAP_SUCCESS); 13114520Snw141292 } 13124520Snw141292 13134520Snw141292 /* 13144864Sbaban * Lookup sid to name locally 13154520Snw141292 */ 13164520Snw141292 static idmap_retcode 13174864Sbaban lookup_local_sid2name(sqlite *cache, idmap_mapping *req, idmap_id_res *res) { 13184520Snw141292 int type = -1; 13194520Snw141292 idmap_retcode retcode; 13204520Snw141292 char *sidprefix; 13214520Snw141292 idmap_rid_t rid; 13224520Snw141292 char *name = NULL, *domain = NULL; 13234520Snw141292 idmap_utf8str *str; 13244520Snw141292 13254520Snw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 13264520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 13274520Snw141292 13284864Sbaban /* Lookup sids to name in well-known sids table */ 13294864Sbaban retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 13304864Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 13314864Sbaban goto out; 13324864Sbaban 13334520Snw141292 /* Lookup sid to name in cache */ 13344864Sbaban retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 13354520Snw141292 &domain, &type); 13364520Snw141292 if (retcode != IDMAP_SUCCESS) 13374520Snw141292 goto out; 13384520Snw141292 13394520Snw141292 out: 13404520Snw141292 if (retcode == IDMAP_SUCCESS) { 13414864Sbaban /* Verify that the sid type matches the request */ 13424864Sbaban retcode = verify_type(req->id2.idtype, type, res); 13434864Sbaban 13444520Snw141292 /* update state in 'req' */ 13454864Sbaban if (name != NULL) { 13464520Snw141292 str = &req->id1name; 13474520Snw141292 (void) idmap_str2utf8(&str, name, 1); 13484520Snw141292 } 13494864Sbaban if (domain != NULL) { 13504520Snw141292 str = &req->id1domain; 13514520Snw141292 (void) idmap_str2utf8(&str, domain, 1); 13524520Snw141292 } 13534520Snw141292 } else { 13544864Sbaban if (name != NULL) 13554520Snw141292 free(name); 13564864Sbaban if (domain != NULL) 13574520Snw141292 free(domain); 13584520Snw141292 } 13594520Snw141292 return (retcode); 13604520Snw141292 } 13614520Snw141292 13624520Snw141292 idmap_retcode 13634520Snw141292 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 13644520Snw141292 idmap_ids_res *result) { 13654520Snw141292 idmap_retcode retcode; 13664520Snw141292 int ret, i; 13674520Snw141292 int retries = 0; 13684520Snw141292 idmap_mapping *req; 13694520Snw141292 idmap_id_res *res; 13704520Snw141292 13714520Snw141292 if (state->ad_nqueries == 0) 13724520Snw141292 return (IDMAP_SUCCESS); 13734520Snw141292 13744520Snw141292 retry: 13754520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 13764520Snw141292 &state->ad_lookup); 13774520Snw141292 if (ret != 0) { 13784520Snw141292 idmapdlog(LOG_ERR, 13794520Snw141292 "Failed to create sid2name batch for AD lookup"); 13804520Snw141292 return (IDMAP_ERR_INTERNAL); 13814520Snw141292 } 13824520Snw141292 13834520Snw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 13844520Snw141292 req = &batch->idmap_mapping_batch_val[i]; 13854520Snw141292 res = &result->ids.ids_val[i]; 13864520Snw141292 13874520Snw141292 if (req->id1.idtype == IDMAP_SID && 13884520Snw141292 req->direction & _IDMAP_F_S2N_AD) { 13894864Sbaban if (retries == 0) 13904864Sbaban res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 13914864Sbaban else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 13924864Sbaban continue; 13934520Snw141292 retcode = idmap_sid2name_batch_add1( 13944520Snw141292 state->ad_lookup, 13954520Snw141292 req->id1.idmap_id_u.sid.prefix, 13964520Snw141292 &req->id1.idmap_id_u.sid.rid, 13974520Snw141292 &req->id1name.idmap_utf8str_val, 13984520Snw141292 &req->id1domain.idmap_utf8str_val, 13994520Snw141292 (int *)&res->id.idtype, 14004520Snw141292 &res->retcode); 14014520Snw141292 14024520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 14034520Snw141292 break; 14044520Snw141292 if (retcode != IDMAP_SUCCESS) 14054520Snw141292 goto out; 14064520Snw141292 } 14074520Snw141292 } 14084520Snw141292 14094520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1410*4884Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 14114520Snw141292 else 14124520Snw141292 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 14134520Snw141292 14144520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 14154520Snw141292 goto retry; 14164520Snw141292 14174520Snw141292 return (retcode); 14184520Snw141292 14194520Snw141292 out: 14204520Snw141292 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 1421*4884Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 14224520Snw141292 return (retcode); 14234520Snw141292 } 14244520Snw141292 14254520Snw141292 idmap_retcode 14264520Snw141292 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 14274520Snw141292 idmap_id_res *res) { 14284520Snw141292 idmap_retcode retcode; 14294520Snw141292 14304520Snw141292 /* 14314520Snw141292 * The req->direction field is used to maintain state of the 14324520Snw141292 * sid2pid request. 14334520Snw141292 */ 14344520Snw141292 req->direction = _IDMAP_F_DONE; 14354520Snw141292 14364520Snw141292 if (req->id1.idmap_id_u.sid.prefix == NULL) { 14374520Snw141292 retcode = IDMAP_ERR_SID; 14384520Snw141292 goto out; 14394520Snw141292 } 14404520Snw141292 res->id.idtype = req->id2.idtype; 14414520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 14424520Snw141292 14434864Sbaban /* Lookup well-known sid to pid mapping */ 14444520Snw141292 retcode = lookup_wksids_sid2pid(req, res); 14454520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 14464520Snw141292 goto out; 14474520Snw141292 14484520Snw141292 /* Lookup sid to pid in cache */ 14494520Snw141292 retcode = lookup_cache_sid2pid(cache, req, res); 14504520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 14514520Snw141292 goto out; 14524520Snw141292 14534520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 14544520Snw141292 res->id.idmap_id_u.uid = SENTINEL_PID; 14554520Snw141292 goto out; 14564520Snw141292 } 14574520Snw141292 14584520Snw141292 /* 14594520Snw141292 * Failed to find non-expired entry in cache. Tell the caller 14604520Snw141292 * that we are not done yet. 14614520Snw141292 */ 14624520Snw141292 state->sid2pid_done = FALSE; 14634520Snw141292 14644520Snw141292 /* 14654520Snw141292 * Our next step is name-based mapping. To lookup name-based 14664520Snw141292 * mapping rules, we need the windows name and domain-name 14674520Snw141292 * associated with the SID. 14684520Snw141292 */ 14694520Snw141292 14704520Snw141292 /* 14714520Snw141292 * Check if we already have the name (i.e name2pid lookups) 14724520Snw141292 */ 14734864Sbaban if (req->id1name.idmap_utf8str_val != NULL && 14744864Sbaban req->id1domain.idmap_utf8str_val != NULL) { 14754520Snw141292 retcode = IDMAP_SUCCESS; 14764520Snw141292 req->direction |= _IDMAP_F_S2N_CACHE; 14774520Snw141292 goto out; 14784520Snw141292 } 14794520Snw141292 14804864Sbaban /* Lookup sid to winname@domain locally first */ 14814864Sbaban retcode = lookup_local_sid2name(cache, req, res); 14824864Sbaban if (retcode == IDMAP_SUCCESS) { 14834864Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 14844864Sbaban } else if (retcode == IDMAP_ERR_NOTFOUND) { 14854520Snw141292 /* Batch sid to name AD lookup request */ 14864520Snw141292 retcode = IDMAP_SUCCESS; 14874520Snw141292 req->direction |= _IDMAP_F_S2N_AD; 14884520Snw141292 state->ad_nqueries++; 14894520Snw141292 goto out; 14904520Snw141292 } 14914520Snw141292 14924520Snw141292 14934520Snw141292 out: 14944520Snw141292 res->retcode = idmap_stat4prot(retcode); 14954520Snw141292 return (retcode); 14964520Snw141292 } 14974520Snw141292 14984520Snw141292 /* 14994520Snw141292 * Generate SID using the following convention 15004520Snw141292 * <machine-sid-prefix>-<1000 + uid> 15014520Snw141292 * <machine-sid-prefix>-<2^31 + gid> 15024520Snw141292 */ 15034520Snw141292 static idmap_retcode 15044520Snw141292 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) { 15054520Snw141292 15064864Sbaban if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 15074520Snw141292 /* Skip 1000 UIDs */ 15084520Snw141292 if (is_user && req->id1.idmap_id_u.uid > 15094520Snw141292 (INT32_MAX - LOCALRID_MIN)) 15104864Sbaban return (IDMAP_ERR_NOMAPPING); 15114520Snw141292 15124520Snw141292 RDLOCK_CONFIG(); 15134520Snw141292 res->id.idmap_id_u.sid.prefix = 15144520Snw141292 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 15154520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 15164520Snw141292 UNLOCK_CONFIG(); 15174520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 15184520Snw141292 return (IDMAP_ERR_MEMORY); 15194520Snw141292 } 15204520Snw141292 UNLOCK_CONFIG(); 15214520Snw141292 res->id.idmap_id_u.sid.rid = 15224520Snw141292 (is_user)?req->id1.idmap_id_u.uid + LOCALRID_MIN: 15234520Snw141292 req->id1.idmap_id_u.gid + INT32_MAX + 1; 15244644Sbaban res->direction = IDMAP_DIRECTION_BI; 15254520Snw141292 15264520Snw141292 /* 15274520Snw141292 * Don't update name_cache because local sids don't have 15284520Snw141292 * valid windows names. 15294520Snw141292 * We mark the entry as being found in the namecache so that 15304520Snw141292 * the cache update routine doesn't update namecache. 15314520Snw141292 */ 15324520Snw141292 req->direction = _IDMAP_F_S2N_CACHE; 15334868Sbaban return (IDMAP_SUCCESS); 15344520Snw141292 } 15354520Snw141292 15364864Sbaban return (IDMAP_ERR_NOMAPPING); 15374520Snw141292 } 15384520Snw141292 15394520Snw141292 static idmap_retcode 15404520Snw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) { 15414520Snw141292 char *sidprefix; 15424520Snw141292 uint32_t rid; 15434520Snw141292 int s; 15444520Snw141292 15454520Snw141292 /* 15464520Snw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 15474520Snw141292 * GID = last RID - 2^31. 15484520Snw141292 */ 15494520Snw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 15504520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 15514520Snw141292 15524520Snw141292 RDLOCK_CONFIG(); 15534520Snw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid)? 15544520Snw141292 strcasecmp(sidprefix, 15554520Snw141292 _idmapdstate.cfg->pgcfg.machine_sid):1; 15564520Snw141292 UNLOCK_CONFIG(); 15574520Snw141292 15584520Snw141292 if (s == 0) { 15594520Snw141292 switch (req->id2.idtype) { 15604520Snw141292 case IDMAP_UID: 15614520Snw141292 if (rid > INT32_MAX) { 15624520Snw141292 return (IDMAP_ERR_NOTUSER); 15634520Snw141292 } else if (rid < LOCALRID_MIN) { 15644520Snw141292 return (IDMAP_ERR_NOTFOUND); 15654520Snw141292 } 15664520Snw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 15674520Snw141292 res->id.idtype = IDMAP_UID; 15684520Snw141292 break; 15694520Snw141292 case IDMAP_GID: 15704520Snw141292 if (rid <= INT32_MAX) { 15714520Snw141292 return (IDMAP_ERR_NOTGROUP); 15724520Snw141292 } 15734520Snw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 15744520Snw141292 res->id.idtype = IDMAP_GID; 15754520Snw141292 break; 15764520Snw141292 case IDMAP_POSIXID: 15774520Snw141292 if (rid > INT32_MAX) { 15784520Snw141292 res->id.idmap_id_u.gid = 15794520Snw141292 rid - INT32_MAX - 1; 15804520Snw141292 res->id.idtype = IDMAP_GID; 15814520Snw141292 } else if (rid < LOCALRID_MIN) { 15824520Snw141292 return (IDMAP_ERR_NOTFOUND); 15834520Snw141292 } else { 15844520Snw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 15854520Snw141292 res->id.idtype = IDMAP_UID; 15864520Snw141292 } 15874520Snw141292 break; 15884520Snw141292 default: 15894520Snw141292 return (IDMAP_ERR_NOTSUPPORTED); 15904520Snw141292 } 15914520Snw141292 return (IDMAP_SUCCESS); 15924520Snw141292 } 15934520Snw141292 15944520Snw141292 return (IDMAP_ERR_NOTFOUND); 15954520Snw141292 } 15964520Snw141292 15974520Snw141292 static idmap_retcode 15984520Snw141292 ns_lookup_byname(int is_user, const char *name, idmap_id_res *res) { 15994520Snw141292 struct passwd pwd; 16004520Snw141292 struct group grp; 16014520Snw141292 char buf[1024]; 16024520Snw141292 int errnum; 16034520Snw141292 const char *me = "ns_lookup_byname"; 16044520Snw141292 16054520Snw141292 if (is_user) { 16064520Snw141292 if (getpwnam_r(name, &pwd, buf, sizeof (buf)) == NULL) { 16074520Snw141292 errnum = errno; 16084520Snw141292 idmapdlog(LOG_WARNING, 16094520Snw141292 "%s: getpwnam_r(%s) failed (%s).", 16104520Snw141292 me, name, 16114520Snw141292 errnum?strerror(errnum):"not found"); 16124520Snw141292 if (errnum == 0) 16134520Snw141292 return (IDMAP_ERR_NOTFOUND); 16144520Snw141292 else 16154520Snw141292 return (IDMAP_ERR_INTERNAL); 16164520Snw141292 } 16174520Snw141292 res->id.idmap_id_u.uid = pwd.pw_uid; 16184520Snw141292 res->id.idtype = IDMAP_UID; 16194520Snw141292 } else { 16204520Snw141292 if (getgrnam_r(name, &grp, buf, sizeof (buf)) == NULL) { 16214520Snw141292 errnum = errno; 16224520Snw141292 idmapdlog(LOG_WARNING, 16234520Snw141292 "%s: getgrnam_r(%s) failed (%s).", 16244520Snw141292 me, name, 16254520Snw141292 errnum?strerror(errnum):"not found"); 16264520Snw141292 if (errnum == 0) 16274520Snw141292 return (IDMAP_ERR_NOTFOUND); 16284520Snw141292 else 16294520Snw141292 return (IDMAP_ERR_INTERNAL); 16304520Snw141292 } 16314520Snw141292 res->id.idmap_id_u.gid = grp.gr_gid; 16324520Snw141292 res->id.idtype = IDMAP_GID; 16334520Snw141292 } 16344520Snw141292 return (IDMAP_SUCCESS); 16354520Snw141292 } 16364520Snw141292 16374520Snw141292 /* 16384520Snw141292 * Name-based mapping 16394520Snw141292 * 16404520Snw141292 * Case 1: If no rule matches do ephemeral 16414520Snw141292 * 16424520Snw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 16434520Snw141292 * 16444520Snw141292 * Case 3: If rule matches and unixname is specified then lookup name 16454520Snw141292 * service using the unixname. If unixname not found then return no mapping. 16464520Snw141292 * 16474520Snw141292 * Case 4: If rule matches and unixname is * then lookup name service 16484520Snw141292 * using winname as the unixname. If unixname not found then process 16494520Snw141292 * other rules using the lookup order. If no other rule matches then do 16504520Snw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 16514520Snw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 16524520Snw141292 * instead of the default behaviour of doing ephemeral mapping. 16534520Snw141292 * 16544520Snw141292 * Example 1: 16554520Snw141292 * *@sfbay == * 16564520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16574520Snw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 16584520Snw141292 * 16594520Snw141292 * Example 2: 16604520Snw141292 * *@sfbay == * 16614520Snw141292 * *@sfbay => guest 16624520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16634520Snw141292 * the name service then foo@sfbay will be mapped to guest. 16644520Snw141292 * 16654520Snw141292 * Example 3: 16664520Snw141292 * *@sfbay == * 16674520Snw141292 * *@sfbay => "" 16684520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 16694520Snw141292 * the name service then we will return no mapping for foo@sfbay. 16704520Snw141292 * 16714520Snw141292 */ 16724520Snw141292 static idmap_retcode 16734520Snw141292 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) { 16744520Snw141292 const char *unixname, *winname, *windomain; 16754520Snw141292 char *sql = NULL, *errmsg = NULL; 16764520Snw141292 idmap_retcode retcode; 16774520Snw141292 char *end; 16784520Snw141292 const char **values; 16794520Snw141292 sqlite_vm *vm = NULL; 16804520Snw141292 idmap_utf8str *str; 1681*4884Sjp151216 int ncol, r, i, is_user; 16824520Snw141292 const char *me = "name_based_mapping_sid2pid"; 16834520Snw141292 16844520Snw141292 winname = req->id1name.idmap_utf8str_val; 16854520Snw141292 windomain = req->id1domain.idmap_utf8str_val; 16864520Snw141292 is_user = (res->id.idtype == IDMAP_UID)?1:0; 16874520Snw141292 16884520Snw141292 i = 0; 16894864Sbaban if (windomain == NULL) { 16904864Sbaban windomain = ""; 16914864Sbaban } else { 16924864Sbaban RDLOCK_CONFIG(); 16934864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 16944864Sbaban if (strcasecmp(_idmapdstate.cfg->pgcfg.mapping_domain, 16954864Sbaban windomain) == 0) 16964864Sbaban i = 1; 16974864Sbaban } 16984864Sbaban UNLOCK_CONFIG(); 16994520Snw141292 } 17004520Snw141292 17014520Snw141292 sql = sqlite_mprintf( 17024520Snw141292 "SELECT unixname, u2w_order FROM namerules WHERE " 17034520Snw141292 "w2u_order > 0 AND is_user = %d AND " 17044520Snw141292 "(winname = %Q OR winname = '*') AND " 17054520Snw141292 "(windomain = %Q OR windomain = '*' %s) " 17064520Snw141292 "ORDER BY w2u_order ASC;", 17074864Sbaban is_user, winname, 17084864Sbaban windomain, 17094864Sbaban i?"OR windomain ISNULL OR windomain = ''":""); 17104520Snw141292 if (sql == NULL) { 17114520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 17124520Snw141292 retcode = IDMAP_ERR_MEMORY; 17134520Snw141292 goto out; 17144520Snw141292 } 17154520Snw141292 17164520Snw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 17174520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17184520Snw141292 idmapdlog(LOG_ERR, 17194520Snw141292 "%s: database error (%s)", 17204520Snw141292 me, CHECK_NULL(errmsg)); 17214520Snw141292 sqlite_freemem(errmsg); 17224520Snw141292 goto out; 17234520Snw141292 } 17244520Snw141292 1725*4884Sjp151216 for (; ; ) { 17264520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 1727*4884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 1728*4884Sjp151216 1729*4884Sjp151216 if (r == SQLITE_ROW) { 17304520Snw141292 if (ncol < 2) { 17314520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17324520Snw141292 goto out; 17334520Snw141292 } 17344520Snw141292 if (values[0] == NULL) { 17354520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17364520Snw141292 goto out; 17374520Snw141292 } 17384520Snw141292 17394520Snw141292 if (EMPTY_NAME(values[0])) { 17404520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 17414520Snw141292 goto out; 17424520Snw141292 } 17434520Snw141292 unixname = (values[0][0] == '*')?winname:values[0]; 17444520Snw141292 retcode = ns_lookup_byname(is_user, unixname, res); 17454520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 17464520Snw141292 if (unixname == winname) 17474520Snw141292 /* Case 4 */ 17484520Snw141292 continue; 17494520Snw141292 else 17504520Snw141292 /* Case 3 */ 17514520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 17524520Snw141292 } 17534520Snw141292 goto out; 17544520Snw141292 } else if (r == SQLITE_DONE) { 17554520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 17564520Snw141292 goto out; 17574520Snw141292 } else { 17584520Snw141292 (void) sqlite_finalize(vm, &errmsg); 17594520Snw141292 vm = NULL; 17604520Snw141292 idmapdlog(LOG_ERR, 17614520Snw141292 "%s: database error (%s)", 17624520Snw141292 me, CHECK_NULL(errmsg)); 17634520Snw141292 sqlite_freemem(errmsg); 17644520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17654520Snw141292 goto out; 17664520Snw141292 } 17674520Snw141292 } 17684520Snw141292 17694520Snw141292 out: 17704864Sbaban if (sql != NULL) 17714520Snw141292 sqlite_freemem(sql); 17724520Snw141292 if (retcode == IDMAP_SUCCESS) { 17734864Sbaban if (values[1] != NULL) 17744520Snw141292 res->direction = 17754644Sbaban (strtol(values[1], &end, 10) == 0)? 17764644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 17774520Snw141292 else 17784644Sbaban res->direction = IDMAP_DIRECTION_W2U; 17794520Snw141292 str = &req->id2name; 17804520Snw141292 retcode = idmap_str2utf8(&str, unixname, 0); 17814520Snw141292 } 17824864Sbaban if (vm != NULL) 17834520Snw141292 (void) sqlite_finalize(vm, NULL); 17844520Snw141292 return (retcode); 17854520Snw141292 } 17864520Snw141292 17874520Snw141292 static 17884520Snw141292 int 17894520Snw141292 get_next_eph_uid(uid_t *next_uid) 17904520Snw141292 { 17914520Snw141292 uid_t uid; 17924520Snw141292 gid_t gid; 17934520Snw141292 int err; 17944520Snw141292 17954520Snw141292 *next_uid = (uid_t)-1; 17964520Snw141292 uid = _idmapdstate.next_uid++; 17974520Snw141292 if (uid >= _idmapdstate.limit_uid) { 17984520Snw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 17994520Snw141292 return (err); 18004520Snw141292 18014520Snw141292 _idmapdstate.limit_uid = uid + 8192; 18024520Snw141292 _idmapdstate.next_uid = uid; 18034520Snw141292 } 18044520Snw141292 *next_uid = uid; 18054520Snw141292 18064520Snw141292 return (0); 18074520Snw141292 } 18084520Snw141292 18094520Snw141292 static 18104520Snw141292 int 18114520Snw141292 get_next_eph_gid(gid_t *next_gid) 18124520Snw141292 { 18134520Snw141292 uid_t uid; 18144520Snw141292 gid_t gid; 18154520Snw141292 int err; 18164520Snw141292 18174520Snw141292 *next_gid = (uid_t)-1; 18184520Snw141292 gid = _idmapdstate.next_gid++; 18194520Snw141292 if (gid >= _idmapdstate.limit_gid) { 18204520Snw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 18214520Snw141292 return (err); 18224520Snw141292 18234520Snw141292 _idmapdstate.limit_gid = gid + 8192; 18244520Snw141292 _idmapdstate.next_gid = gid; 18254520Snw141292 } 18264520Snw141292 *next_gid = gid; 18274520Snw141292 18284520Snw141292 return (0); 18294520Snw141292 } 18304520Snw141292 18314864Sbaban static 18324864Sbaban int 18334864Sbaban gethash(const char *str, uint32_t num, uint_t htsize) { 18344864Sbaban uint_t hval, i, len; 18354864Sbaban 18364864Sbaban if (str == NULL) 18374864Sbaban return (0); 18384864Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 18394864Sbaban hval += str[i]; 18404864Sbaban hval += (hval << 10); 18414864Sbaban hval ^= (hval >> 6); 18424864Sbaban } 18434864Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 18444864Sbaban hval += str[i]; 18454864Sbaban hval += (hval << 10); 18464864Sbaban hval ^= (hval >> 6); 18474864Sbaban } 18484864Sbaban hval += (hval << 3); 18494864Sbaban hval ^= (hval >> 11); 18504864Sbaban hval += (hval << 15); 18514864Sbaban return (hval % htsize); 18524864Sbaban } 18534864Sbaban 18544864Sbaban static 18554864Sbaban int 18564864Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 18574864Sbaban uid_t *pid) { 18584864Sbaban uint_t next, key; 18594864Sbaban uint_t htsize = state->sid_history_size; 18604864Sbaban idmap_sid *sid; 18614864Sbaban 18624864Sbaban next = gethash(prefix, rid, htsize); 18634864Sbaban while (next != htsize) { 18644864Sbaban key = state->sid_history[next].key; 18654864Sbaban if (key == htsize) 18664864Sbaban return (0); 18674864Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 18684864Sbaban idmap_id_u.sid; 18694864Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 18704864Sbaban *pid = state->result->ids.ids_val[key].id. 18714864Sbaban idmap_id_u.uid; 18724864Sbaban return (1); 18734864Sbaban } 18744864Sbaban next = state->sid_history[next].next; 18754864Sbaban } 18764864Sbaban return (0); 18774864Sbaban } 18784864Sbaban 18794864Sbaban static 18804864Sbaban void 18814864Sbaban add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) { 18824864Sbaban uint_t hash, next; 18834864Sbaban uint_t htsize = state->sid_history_size; 18844864Sbaban 18854864Sbaban hash = next = gethash(prefix, rid, htsize); 18864864Sbaban while (state->sid_history[next].key != htsize) { 18874864Sbaban next++; 18884864Sbaban next %= htsize; 18894864Sbaban } 18904864Sbaban state->sid_history[next].key = state->curpos; 18914864Sbaban if (hash == next) 18924864Sbaban return; 18934864Sbaban state->sid_history[next].next = state->sid_history[hash].next; 18944864Sbaban state->sid_history[hash].next = next; 18954864Sbaban } 18964520Snw141292 18974520Snw141292 /* ARGSUSED */ 18984520Snw141292 static 18994520Snw141292 idmap_retcode 19004864Sbaban dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 19014864Sbaban idmap_mapping *req, idmap_id_res *res) { 19024520Snw141292 19034520Snw141292 uid_t next_pid; 19044520Snw141292 19054864Sbaban res->direction = IDMAP_DIRECTION_BI; 19064864Sbaban 19074864Sbaban if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 19084864Sbaban return (IDMAP_SUCCESS); 19094864Sbaban 19104864Sbaban if (state->sid_history != NULL && 19114864Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 19124864Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 19134864Sbaban res->id.idmap_id_u.uid = next_pid; 19144864Sbaban return (IDMAP_SUCCESS); 19154864Sbaban } 19164864Sbaban 19174864Sbaban if (res->id.idtype == IDMAP_UID) { 19184520Snw141292 if (get_next_eph_uid(&next_pid) != 0) 19194520Snw141292 return (IDMAP_ERR_INTERNAL); 19204520Snw141292 res->id.idmap_id_u.uid = next_pid; 19214520Snw141292 } else { 19224520Snw141292 if (get_next_eph_gid(&next_pid) != 0) 19234520Snw141292 return (IDMAP_ERR_INTERNAL); 19244520Snw141292 res->id.idmap_id_u.gid = next_pid; 19254520Snw141292 } 19264520Snw141292 19274864Sbaban if (state->sid_history != NULL) 19284864Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 19294864Sbaban req->id1.idmap_id_u.sid.rid); 19304864Sbaban 19314520Snw141292 return (IDMAP_SUCCESS); 19324520Snw141292 } 19334520Snw141292 19344520Snw141292 idmap_retcode 19354520Snw141292 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 19364520Snw141292 idmap_mapping *req, idmap_id_res *res) { 19374520Snw141292 idmap_retcode retcode; 19384520Snw141292 19394520Snw141292 /* 19404520Snw141292 * The req->direction field is used to maintain state of the 19414520Snw141292 * sid2pid request. 19424520Snw141292 */ 19434520Snw141292 19444520Snw141292 /* Check if second pass is needed */ 19454520Snw141292 if (req->direction == _IDMAP_F_DONE) 19464520Snw141292 return (res->retcode); 19474520Snw141292 19484520Snw141292 /* Get status from previous pass */ 19494520Snw141292 retcode = (res->retcode == IDMAP_NEXT)?IDMAP_SUCCESS:res->retcode; 19504520Snw141292 19514520Snw141292 if (retcode != IDMAP_SUCCESS) { 19524520Snw141292 /* Reset return type */ 19534520Snw141292 res->id.idtype = req->id2.idtype; 19544520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 19554520Snw141292 19564520Snw141292 /* Check if this is a localsid */ 19574520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND && 19584864Sbaban _idmapdstate.cfg->pgcfg.machine_sid) { 19594520Snw141292 retcode = lookup_localsid2pid(req, res); 19604520Snw141292 if (retcode == IDMAP_SUCCESS) { 19614520Snw141292 state->sid2pid_done = FALSE; 19624520Snw141292 req->direction = _IDMAP_F_S2N_CACHE; 19634520Snw141292 } 19644520Snw141292 } 19654520Snw141292 goto out; 19664520Snw141292 } 19674520Snw141292 19684520Snw141292 /* 19694520Snw141292 * Verify that the sid type matches the request if the 19704520Snw141292 * SID was validated by an AD lookup. 19714520Snw141292 */ 19724520Snw141292 if (req->direction & _IDMAP_F_S2N_AD) { 19734520Snw141292 retcode = verify_type(req->id2.idtype, 19744520Snw141292 (int)res->id.idtype, res); 19754520Snw141292 if (retcode != IDMAP_SUCCESS) { 19764520Snw141292 res->id.idtype = req->id2.idtype; 19774520Snw141292 res->id.idmap_id_u.uid = UID_NOBODY; 19784520Snw141292 goto out; 19794520Snw141292 } 19804520Snw141292 } 19814520Snw141292 19824520Snw141292 /* Name-based mapping */ 19834520Snw141292 retcode = name_based_mapping_sid2pid(db, req, res); 19844520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 19854520Snw141292 /* If not found, do ephemeral mapping */ 19864520Snw141292 goto ephemeral; 19874520Snw141292 else if (retcode != IDMAP_SUCCESS) 19884520Snw141292 goto out; 19894520Snw141292 19904520Snw141292 state->sid2pid_done = FALSE; 19914520Snw141292 goto out; 19924520Snw141292 19934520Snw141292 19944520Snw141292 ephemeral: 19954864Sbaban retcode = dynamic_ephemeral_mapping(state, cache, req, res); 19964520Snw141292 if (retcode == IDMAP_SUCCESS) 19974520Snw141292 state->sid2pid_done = FALSE; 19984520Snw141292 19994520Snw141292 out: 20004520Snw141292 res->retcode = idmap_stat4prot(retcode); 20014520Snw141292 return (retcode); 20024520Snw141292 } 20034520Snw141292 20044520Snw141292 idmap_retcode 20054520Snw141292 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 20064520Snw141292 idmap_mapping *req, idmap_id_res *res) { 20074520Snw141292 char *sql = NULL; 20084520Snw141292 idmap_retcode retcode; 20094520Snw141292 20104520Snw141292 /* Check if we need to cache anything */ 20114520Snw141292 if (req->direction == _IDMAP_F_DONE) 20124520Snw141292 return (IDMAP_SUCCESS); 20134520Snw141292 20144520Snw141292 /* We don't cache negative entries */ 20154520Snw141292 if (res->retcode != IDMAP_SUCCESS) 20164520Snw141292 return (IDMAP_SUCCESS); 20174520Snw141292 20184520Snw141292 /* 20194520Snw141292 * Using NULL for u2w instead of 0 so that our trigger allows 20204520Snw141292 * the same pid to be the destination in multiple entries 20214520Snw141292 */ 20224520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 20234520Snw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 20244520Snw141292 "is_user, expiration, w2u, u2w) " 20254520Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 20264520Snw141292 "strftime('%%s','now') + 600, %q, 1); ", 20274520Snw141292 res->id.idmap_id_u.sid.prefix, 20284520Snw141292 res->id.idmap_id_u.sid.rid, 20294520Snw141292 req->id2domain.idmap_utf8str_val, 20304520Snw141292 req->id2name.idmap_utf8str_val, 20314520Snw141292 req->id1.idmap_id_u.uid, 20324520Snw141292 req->id1name.idmap_utf8str_val, 20334520Snw141292 (req->id1.idtype == IDMAP_UID)?1:0, 20344520Snw141292 (res->direction == 0)?"1":NULL); 20354520Snw141292 20364520Snw141292 if (sql == NULL) { 20374520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20384520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 20394520Snw141292 goto out; 20404520Snw141292 } 20414520Snw141292 20424520Snw141292 retcode = sql_exec_no_cb(cache, sql); 20434520Snw141292 if (retcode != IDMAP_SUCCESS) 20444520Snw141292 goto out; 20454520Snw141292 20464520Snw141292 state->pid2sid_done = FALSE; 20474520Snw141292 sqlite_freemem(sql); 20484520Snw141292 sql = NULL; 20494520Snw141292 20504520Snw141292 /* If sid2name was found in the cache, no need to update namecache */ 20514520Snw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 20524520Snw141292 goto out; 20534520Snw141292 20544520Snw141292 if (req->id2name.idmap_utf8str_val == NULL) 20554520Snw141292 goto out; 20564520Snw141292 20574520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 20584520Snw141292 "(sidprefix, rid, name, domain, type, expiration) " 20594520Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 20604520Snw141292 res->id.idmap_id_u.sid.prefix, 20614520Snw141292 res->id.idmap_id_u.sid.rid, 20624520Snw141292 req->id2name.idmap_utf8str_val, 20634520Snw141292 req->id2domain.idmap_utf8str_val, 20644520Snw141292 (req->id1.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 20654520Snw141292 20664520Snw141292 if (sql == NULL) { 20674520Snw141292 retcode = IDMAP_ERR_INTERNAL; 20684520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 20694520Snw141292 goto out; 20704520Snw141292 } 20714520Snw141292 20724520Snw141292 retcode = sql_exec_no_cb(cache, sql); 20734520Snw141292 20744520Snw141292 out: 20754864Sbaban if (sql != NULL) 20764520Snw141292 sqlite_freemem(sql); 20774520Snw141292 return (retcode); 20784520Snw141292 } 20794520Snw141292 20804520Snw141292 idmap_retcode 20814520Snw141292 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 20824520Snw141292 idmap_mapping *req, idmap_id_res *res) { 20834520Snw141292 char *sql = NULL; 20844520Snw141292 idmap_retcode retcode; 20854520Snw141292 int is_eph_user; 20864520Snw141292 20874520Snw141292 /* Check if we need to cache anything */ 20884520Snw141292 if (req->direction == _IDMAP_F_DONE) 20894520Snw141292 return (IDMAP_SUCCESS); 20904520Snw141292 20914520Snw141292 /* We don't cache negative entries */ 20924520Snw141292 if (res->retcode != IDMAP_SUCCESS) 20934520Snw141292 return (IDMAP_SUCCESS); 20944520Snw141292 20954520Snw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 20964520Snw141292 is_eph_user = 1; 20974520Snw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 20984520Snw141292 is_eph_user = 0; 20994520Snw141292 else 21004520Snw141292 is_eph_user = -1; 21014520Snw141292 21024520Snw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 21034520Snw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 21044520Snw141292 "SET w2u = 0 WHERE " 21054520Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 21064520Snw141292 "pid >= 2147483648 AND is_user = %d;", 21074520Snw141292 req->id1.idmap_id_u.sid.prefix, 21084520Snw141292 req->id1.idmap_id_u.sid.rid, 21094520Snw141292 is_eph_user); 21104520Snw141292 if (sql == NULL) { 21114520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21124520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21134520Snw141292 goto out; 21144520Snw141292 } 21154520Snw141292 21164520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21174520Snw141292 if (retcode != IDMAP_SUCCESS) 21184520Snw141292 goto out; 21194520Snw141292 21204520Snw141292 sqlite_freemem(sql); 21214520Snw141292 sql = NULL; 21224520Snw141292 } 21234520Snw141292 21244520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 21254520Snw141292 "(sidprefix, rid, windomain, winname, pid, unixname, " 21264520Snw141292 "is_user, expiration, w2u, u2w) " 21274520Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, " 21284520Snw141292 "strftime('%%s','now') + 600, 1, %q); ", 21294520Snw141292 req->id1.idmap_id_u.sid.prefix, 21304520Snw141292 req->id1.idmap_id_u.sid.rid, 21314520Snw141292 req->id1domain.idmap_utf8str_val, 21324520Snw141292 req->id1name.idmap_utf8str_val, 21334520Snw141292 res->id.idmap_id_u.uid, 21344520Snw141292 req->id2name.idmap_utf8str_val, 21354520Snw141292 (res->id.idtype == IDMAP_UID)?1:0, 21364520Snw141292 (res->direction == 0)?"1":NULL); 21374520Snw141292 21384520Snw141292 if (sql == NULL) { 21394520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21404520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21414520Snw141292 goto out; 21424520Snw141292 } 21434520Snw141292 21444520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21454520Snw141292 if (retcode != IDMAP_SUCCESS) 21464520Snw141292 goto out; 21474520Snw141292 21484520Snw141292 state->sid2pid_done = FALSE; 21494520Snw141292 sqlite_freemem(sql); 21504520Snw141292 sql = NULL; 21514520Snw141292 21524520Snw141292 /* If name2sid was found in the cache, no need to update namecache */ 21534520Snw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 21544520Snw141292 goto out; 21554520Snw141292 21564520Snw141292 if (req->id1name.idmap_utf8str_val == NULL) 21574520Snw141292 goto out; 21584520Snw141292 21594520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 21604520Snw141292 "(sidprefix, rid, name, domain, type, expiration) " 21614520Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 21624520Snw141292 req->id1.idmap_id_u.sid.prefix, 21634520Snw141292 req->id1.idmap_id_u.sid.rid, 21644520Snw141292 req->id1name.idmap_utf8str_val, 21654520Snw141292 req->id1domain.idmap_utf8str_val, 21664520Snw141292 (res->id.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); 21674520Snw141292 21684520Snw141292 if (sql == NULL) { 21694520Snw141292 retcode = IDMAP_ERR_INTERNAL; 21704520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 21714520Snw141292 goto out; 21724520Snw141292 } 21734520Snw141292 21744520Snw141292 retcode = sql_exec_no_cb(cache, sql); 21754520Snw141292 21764520Snw141292 out: 21774864Sbaban if (sql != NULL) 21784520Snw141292 sqlite_freemem(sql); 21794520Snw141292 return (retcode); 21804520Snw141292 } 21814520Snw141292 21824520Snw141292 static idmap_retcode 21834520Snw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 21844520Snw141292 int is_user, int getname) { 21854520Snw141292 char *end; 21864520Snw141292 char *sql = NULL; 21874520Snw141292 const char **values; 21884520Snw141292 sqlite_vm *vm = NULL; 21894520Snw141292 int ncol; 21904520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 21914520Snw141292 idmap_utf8str *str; 21924520Snw141292 time_t curtime; 21934520Snw141292 21944520Snw141292 /* Current time */ 21954520Snw141292 errno = 0; 21964520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 21974520Snw141292 idmapdlog(LOG_ERR, 21984520Snw141292 "Failed to get current time (%s)", 21994520Snw141292 strerror(errno)); 22004520Snw141292 retcode = IDMAP_ERR_INTERNAL; 22014520Snw141292 goto out; 22024520Snw141292 } 22034520Snw141292 22044520Snw141292 /* SQL to lookup the cache */ 22054520Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, winname, windomain, w2u " 22064520Snw141292 "FROM idmap_cache WHERE " 22074520Snw141292 "pid = %u AND u2w = 1 AND is_user = %d AND " 22084520Snw141292 "(pid >= 2147483648 OR " 22094520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 22104520Snw141292 "expiration > %d));", 22114520Snw141292 req->id1.idmap_id_u.uid, is_user, curtime); 22124520Snw141292 if (sql == NULL) { 22134520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22144520Snw141292 retcode = IDMAP_ERR_MEMORY; 22154520Snw141292 goto out; 22164520Snw141292 } 22174520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 22184520Snw141292 sqlite_freemem(sql); 22194520Snw141292 22204520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 22214520Snw141292 goto out; 22224520Snw141292 else if (retcode == IDMAP_SUCCESS) { 22234520Snw141292 /* sanity checks */ 22244520Snw141292 if (values[0] == NULL || values[1] == NULL) { 22254520Snw141292 retcode = IDMAP_ERR_CACHE; 22264520Snw141292 goto out; 22274520Snw141292 } 22284520Snw141292 22294520Snw141292 switch (req->id2.idtype) { 22304520Snw141292 case IDMAP_SID: 22314520Snw141292 res->id.idmap_id_u.sid.rid = 22324520Snw141292 strtoul(values[1], &end, 10); 22334520Snw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 22344520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 22354520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22364520Snw141292 retcode = IDMAP_ERR_MEMORY; 22374520Snw141292 goto out; 22384520Snw141292 } 22394520Snw141292 22404864Sbaban if (values[4] != NULL) 22414520Snw141292 res->direction = 22424644Sbaban (strtol(values[4], &end, 10) == 0)? 22434644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 22444520Snw141292 else 22454644Sbaban res->direction = IDMAP_DIRECTION_U2W; 22464520Snw141292 22474520Snw141292 if (getname == 0 || values[2] == NULL) 22484520Snw141292 break; 22494520Snw141292 str = &req->id2name; 22504520Snw141292 retcode = idmap_str2utf8(&str, values[2], 0); 22514520Snw141292 if (retcode != IDMAP_SUCCESS) { 22524520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22534520Snw141292 retcode = IDMAP_ERR_MEMORY; 22544520Snw141292 goto out; 22554520Snw141292 } 22564520Snw141292 22574520Snw141292 if (values[3] == NULL) 22584520Snw141292 break; 22594520Snw141292 str = &req->id2domain; 22604520Snw141292 retcode = idmap_str2utf8(&str, values[3], 0); 22614520Snw141292 if (retcode != IDMAP_SUCCESS) { 22624520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 22634520Snw141292 retcode = IDMAP_ERR_MEMORY; 22644520Snw141292 goto out; 22654520Snw141292 } 22664520Snw141292 break; 22674520Snw141292 default: 22684520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 22694520Snw141292 break; 22704520Snw141292 } 22714520Snw141292 } 22724520Snw141292 22734520Snw141292 out: 22744864Sbaban if (vm != NULL) 22754520Snw141292 (void) sqlite_finalize(vm, NULL); 22764520Snw141292 return (retcode); 22774520Snw141292 } 22784520Snw141292 22794520Snw141292 static idmap_retcode 22804520Snw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 22814520Snw141292 char **sidprefix, idmap_rid_t *rid, int *type) { 22824520Snw141292 char *end; 22834520Snw141292 char *sql = NULL; 22844520Snw141292 const char **values; 22854520Snw141292 sqlite_vm *vm = NULL; 22864520Snw141292 int ncol; 22874520Snw141292 time_t curtime; 22884520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 22894520Snw141292 22904520Snw141292 /* Get current time */ 22914520Snw141292 errno = 0; 22924520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 22934520Snw141292 idmapdlog(LOG_ERR, 22944520Snw141292 "Failed to get current time (%s)", 22954520Snw141292 strerror(errno)); 22964520Snw141292 retcode = IDMAP_ERR_INTERNAL; 22974520Snw141292 goto out; 22984520Snw141292 } 22994520Snw141292 23004520Snw141292 /* SQL to lookup the cache */ 23014520Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type FROM name_cache " 23024520Snw141292 "WHERE name = %Q AND domain = %Q AND " 23034520Snw141292 "(expiration = 0 OR expiration ISNULL OR " 23044520Snw141292 "expiration > %d);", 23054520Snw141292 name, domain, curtime); 23064520Snw141292 if (sql == NULL) { 23074520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 23084520Snw141292 retcode = IDMAP_ERR_MEMORY; 23094520Snw141292 goto out; 23104520Snw141292 } 23114520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 23124520Snw141292 sqlite_freemem(sql); 23134520Snw141292 23144520Snw141292 if (retcode == IDMAP_SUCCESS) { 23154864Sbaban if (type != NULL) { 23164520Snw141292 if (values[2] == NULL) { 23174520Snw141292 retcode = IDMAP_ERR_CACHE; 23184520Snw141292 goto out; 23194520Snw141292 } 23204520Snw141292 *type = strtol(values[2], &end, 10); 23214520Snw141292 } 23224520Snw141292 23234520Snw141292 if (values[0] == NULL || values[1] == NULL) { 23244520Snw141292 retcode = IDMAP_ERR_CACHE; 23254520Snw141292 goto out; 23264520Snw141292 } 23274520Snw141292 if ((*sidprefix = strdup(values[0])) == NULL) { 23284520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 23294520Snw141292 retcode = IDMAP_ERR_MEMORY; 23304520Snw141292 goto out; 23314520Snw141292 } 23324520Snw141292 *rid = strtoul(values[1], &end, 10); 23334520Snw141292 } 23344520Snw141292 23354520Snw141292 out: 23364864Sbaban if (vm != NULL) 23374520Snw141292 (void) sqlite_finalize(vm, NULL); 23384520Snw141292 return (retcode); 23394520Snw141292 } 23404520Snw141292 23414520Snw141292 static idmap_retcode 23424520Snw141292 lookup_win_name2sid(const char *name, const char *domain, char **sidprefix, 23434520Snw141292 idmap_rid_t *rid, int *type) { 23444520Snw141292 int ret; 23454520Snw141292 int retries = 0; 23464520Snw141292 idmap_query_state_t *qs = NULL; 23474520Snw141292 idmap_retcode rc, retcode; 23484520Snw141292 23494520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 23504520Snw141292 23514520Snw141292 retry: 23524520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 23534520Snw141292 if (ret != 0) { 23544520Snw141292 idmapdlog(LOG_ERR, 23554520Snw141292 "Failed to create name2sid batch for AD lookup"); 23564520Snw141292 return (IDMAP_ERR_INTERNAL); 23574520Snw141292 } 23584520Snw141292 23594520Snw141292 retcode = idmap_name2sid_batch_add1(qs, name, domain, sidprefix, 23604520Snw141292 rid, type, &rc); 23614520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 23624520Snw141292 goto out; 23634520Snw141292 23644520Snw141292 if (retcode != IDMAP_SUCCESS) { 23654520Snw141292 idmapdlog(LOG_ERR, 23664520Snw141292 "Failed to batch name2sid for AD lookup"); 2367*4884Sjp151216 idmap_lookup_release_batch(&qs); 23684520Snw141292 return (IDMAP_ERR_INTERNAL); 23694520Snw141292 } 23704520Snw141292 23714520Snw141292 out: 23724520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2373*4884Sjp151216 idmap_lookup_release_batch(&qs); 23744520Snw141292 else 23754520Snw141292 retcode = idmap_lookup_batch_end(&qs, NULL); 23764520Snw141292 23774520Snw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 23784520Snw141292 goto retry; 23794520Snw141292 23804520Snw141292 if (retcode != IDMAP_SUCCESS) { 23814520Snw141292 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 23824520Snw141292 "failed"); 23834520Snw141292 return (retcode); 23844520Snw141292 } else 23854520Snw141292 return (rc); 23864520Snw141292 /* NOTREACHED */ 23874520Snw141292 } 23884520Snw141292 23894520Snw141292 static idmap_retcode 23904520Snw141292 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 23914520Snw141292 int *is_user, char **sidprefix, idmap_rid_t *rid, 23924520Snw141292 idmap_mapping *req) { 23934520Snw141292 int type; 23944520Snw141292 idmap_retcode retcode; 23954520Snw141292 23964864Sbaban /* Lookup name@domain to sid in the well-known sids table */ 23974864Sbaban retcode = lookup_wksids_name2sid(name, sidprefix, rid, &type); 23984864Sbaban if (retcode == IDMAP_SUCCESS) { 23994864Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 24004864Sbaban goto out; 24014864Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 24024864Sbaban return (retcode); 24034864Sbaban } 24044864Sbaban 24054864Sbaban /* Lookup name@domain to sid in cache */ 24064520Snw141292 retcode = lookup_cache_name2sid(cache, name, domain, sidprefix, 24074520Snw141292 rid, &type); 24084520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 24094520Snw141292 /* Lookup Windows NT/AD to map name@domain to sid */ 24104520Snw141292 retcode = lookup_win_name2sid(name, domain, sidprefix, rid, 24114520Snw141292 &type); 24124520Snw141292 if (retcode != IDMAP_SUCCESS) 24134520Snw141292 return (retcode); 24144520Snw141292 req->direction |= _IDMAP_F_S2N_AD; 24154520Snw141292 } else if (retcode != IDMAP_SUCCESS) { 24164520Snw141292 return (retcode); 24174520Snw141292 } else { 24184520Snw141292 /* Set flag */ 24194520Snw141292 req->direction |= _IDMAP_F_S2N_CACHE; 24204520Snw141292 } 24214520Snw141292 24224864Sbaban out: 24234520Snw141292 /* 24244520Snw141292 * Entry found (cache or Windows lookup) 24254520Snw141292 * is_user is both input as well as output parameter 24264520Snw141292 */ 24274520Snw141292 if (*is_user == 1) { 24284520Snw141292 if (type != _IDMAP_T_USER) 24294520Snw141292 return (IDMAP_ERR_NOTUSER); 24304520Snw141292 } else if (*is_user == 0) { 24314520Snw141292 if (type != _IDMAP_T_GROUP) 24324520Snw141292 return (IDMAP_ERR_NOTGROUP); 24334520Snw141292 } else if (*is_user == -1) { 24344520Snw141292 /* Caller wants to know if its user or group */ 24354520Snw141292 if (type == _IDMAP_T_USER) 24364520Snw141292 *is_user = 1; 24374520Snw141292 else if (type == _IDMAP_T_GROUP) 24384520Snw141292 *is_user = 0; 24394520Snw141292 else 24404520Snw141292 return (IDMAP_ERR_SID); 24414520Snw141292 } 24424520Snw141292 24434520Snw141292 return (retcode); 24444520Snw141292 } 24454520Snw141292 24464520Snw141292 static idmap_retcode 24474520Snw141292 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 24484520Snw141292 int is_user, idmap_mapping *req, idmap_id_res *res) { 24494520Snw141292 const char *winname, *windomain; 24504520Snw141292 char *mapping_domain = NULL; 24514520Snw141292 char *sql = NULL, *errmsg = NULL; 24524520Snw141292 idmap_retcode retcode; 24534520Snw141292 char *end; 24544520Snw141292 const char **values; 24554520Snw141292 sqlite_vm *vm = NULL; 24564520Snw141292 idmap_utf8str *str; 2457*4884Sjp151216 int ncol, r; 24584520Snw141292 const char *me = "name_based_mapping_pid2sid"; 24594520Snw141292 24604520Snw141292 RDLOCK_CONFIG(); 24614864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 24624520Snw141292 mapping_domain = 24634520Snw141292 strdup(_idmapdstate.cfg->pgcfg.mapping_domain); 24644520Snw141292 if (mapping_domain == NULL) { 24654520Snw141292 UNLOCK_CONFIG(); 24664520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 24674520Snw141292 retcode = IDMAP_ERR_MEMORY; 24684520Snw141292 goto out; 24694520Snw141292 } 24704520Snw141292 } 24714520Snw141292 UNLOCK_CONFIG(); 24724520Snw141292 24734520Snw141292 sql = sqlite_mprintf( 24744520Snw141292 "SELECT winname, windomain, w2u_order FROM namerules WHERE " 24754520Snw141292 "u2w_order > 0 AND is_user = %d AND " 24764520Snw141292 "(unixname = %Q OR unixname = '*') " 24774520Snw141292 "ORDER BY u2w_order ASC;", 24784520Snw141292 is_user, unixname); 24794520Snw141292 if (sql == NULL) { 24804520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 24814520Snw141292 retcode = IDMAP_ERR_MEMORY; 24824520Snw141292 goto out; 24834520Snw141292 } 24844520Snw141292 24854520Snw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 24864520Snw141292 retcode = IDMAP_ERR_INTERNAL; 24874520Snw141292 idmapdlog(LOG_ERR, 24884520Snw141292 "%s: database error (%s)", 24894520Snw141292 me, CHECK_NULL(errmsg)); 24904520Snw141292 sqlite_freemem(errmsg); 24914520Snw141292 goto out; 24924520Snw141292 } 24934520Snw141292 2494*4884Sjp151216 for (;;) { 24954520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 2496*4884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 2497*4884Sjp151216 if (r == SQLITE_ROW) { 24984520Snw141292 if (ncol < 3) { 24994520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25004520Snw141292 goto out; 25014520Snw141292 } 25024520Snw141292 if (values[0] == NULL) { 25034520Snw141292 /* values [1] and [2] can be null */ 25044520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25054520Snw141292 goto out; 25064520Snw141292 } 25074520Snw141292 if (EMPTY_NAME(values[0])) { 25084520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 25094520Snw141292 goto out; 25104520Snw141292 } 25114520Snw141292 winname = (values[0][0] == '*')?unixname:values[0]; 25124864Sbaban if (values[1] != NULL) 25134520Snw141292 windomain = values[1]; 25144864Sbaban else if (mapping_domain != NULL) 25154520Snw141292 windomain = mapping_domain; 25164520Snw141292 else { 25174520Snw141292 idmapdlog(LOG_ERR, 25184520Snw141292 "%s: no domain", me); 25194520Snw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 25204520Snw141292 goto out; 25214520Snw141292 } 25224520Snw141292 /* Lookup winname@domain to sid */ 25234520Snw141292 retcode = lookup_name2sid(cache, winname, windomain, 25244520Snw141292 &is_user, &res->id.idmap_id_u.sid.prefix, 25254520Snw141292 &res->id.idmap_id_u.sid.rid, req); 25264520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 25274520Snw141292 if (winname == unixname) 25284520Snw141292 continue; 25294520Snw141292 else 25304520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 25314520Snw141292 } 25324520Snw141292 goto out; 25334520Snw141292 } else if (r == SQLITE_DONE) { 25344520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 25354520Snw141292 goto out; 25364520Snw141292 } else { 25374520Snw141292 (void) sqlite_finalize(vm, &errmsg); 25384520Snw141292 vm = NULL; 25394520Snw141292 idmapdlog(LOG_ERR, 25404520Snw141292 "%s: database error (%s)", 25414520Snw141292 me, CHECK_NULL(errmsg)); 25424520Snw141292 sqlite_freemem(errmsg); 25434520Snw141292 retcode = IDMAP_ERR_INTERNAL; 25444520Snw141292 goto out; 25454520Snw141292 } 25464520Snw141292 } 25474520Snw141292 25484520Snw141292 out: 25494864Sbaban if (sql != NULL) 25504520Snw141292 sqlite_freemem(sql); 25514520Snw141292 if (retcode == IDMAP_SUCCESS) { 25524864Sbaban if (values[2] != NULL) 25534520Snw141292 res->direction = 25544644Sbaban (strtol(values[2], &end, 10) == 0)? 25554644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 25564520Snw141292 else 25574644Sbaban res->direction = IDMAP_DIRECTION_U2W; 25584520Snw141292 str = &req->id2name; 25594520Snw141292 retcode = idmap_str2utf8(&str, winname, 0); 25604520Snw141292 if (retcode == IDMAP_SUCCESS) { 25614520Snw141292 str = &req->id2domain; 25624520Snw141292 if (windomain == mapping_domain) { 25634520Snw141292 (void) idmap_str2utf8(&str, windomain, 1); 25644520Snw141292 mapping_domain = NULL; 25654520Snw141292 } else 25664520Snw141292 retcode = idmap_str2utf8(&str, windomain, 0); 25674520Snw141292 } 25684520Snw141292 } 25694864Sbaban if (vm != NULL) 25704520Snw141292 (void) sqlite_finalize(vm, NULL); 25714864Sbaban if (mapping_domain != NULL) 25724520Snw141292 free(mapping_domain); 25734520Snw141292 return (retcode); 25744520Snw141292 } 25754520Snw141292 25764520Snw141292 idmap_retcode 25774520Snw141292 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 25784520Snw141292 idmap_mapping *req, idmap_id_res *res, int is_user, 25794520Snw141292 int getname) { 25804520Snw141292 char *unixname = NULL; 25814520Snw141292 struct passwd pwd; 25824520Snw141292 struct group grp; 25834520Snw141292 idmap_utf8str *str; 25844520Snw141292 char buf[1024]; 25854520Snw141292 int errnum; 25864520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 25874520Snw141292 const char *me = "pid2sid"; 25884520Snw141292 25894520Snw141292 req->direction = _IDMAP_F_DONE; 25904520Snw141292 res->id.idtype = req->id2.idtype; 25914520Snw141292 25924520Snw141292 /* Lookup well-known SIDs */ 25934520Snw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 25944520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 25954520Snw141292 goto out; 25964520Snw141292 25974520Snw141292 /* Lookup pid to sid in cache */ 25984520Snw141292 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 25994520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 26004520Snw141292 goto out; 26014520Snw141292 26024520Snw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 26034520Snw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 26044864Sbaban retcode = IDMAP_ERR_NOMAPPING; 26054520Snw141292 goto out; 26064520Snw141292 } 26074520Snw141292 26084520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 26094864Sbaban retcode = IDMAP_ERR_NOMAPPING; 26104520Snw141292 goto out; 26114520Snw141292 } 26124520Snw141292 26134520Snw141292 /* uid/gid to name */ 26144864Sbaban if (req->id1name.idmap_utf8str_val != NULL) { 26154520Snw141292 unixname = req->id1name.idmap_utf8str_val; 26164520Snw141292 } if (is_user) { 26174520Snw141292 errno = 0; 26184520Snw141292 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 26194520Snw141292 sizeof (buf)) == NULL) { 26204520Snw141292 errnum = errno; 26214520Snw141292 idmapdlog(LOG_WARNING, 26224520Snw141292 "%s: getpwuid_r(%u) failed (%s).", 26234520Snw141292 me, req->id1.idmap_id_u.uid, 26244520Snw141292 errnum?strerror(errnum):"not found"); 26254520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 26264520Snw141292 IDMAP_ERR_INTERNAL; 26274520Snw141292 goto fallback_localsid; 26284520Snw141292 } 26294520Snw141292 unixname = pwd.pw_name; 26304520Snw141292 } else { 26314520Snw141292 errno = 0; 26324520Snw141292 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 26334520Snw141292 sizeof (buf)) == NULL) { 26344520Snw141292 errnum = errno; 26354520Snw141292 idmapdlog(LOG_WARNING, 26364520Snw141292 "%s: getgrgid_r(%u) failed (%s).", 26374520Snw141292 me, req->id1.idmap_id_u.gid, 26384520Snw141292 errnum?strerror(errnum):"not found"); 26394520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 26404520Snw141292 IDMAP_ERR_INTERNAL; 26414520Snw141292 goto fallback_localsid; 26424520Snw141292 } 26434520Snw141292 unixname = grp.gr_name; 26444520Snw141292 } 26454520Snw141292 26464520Snw141292 /* Name-based mapping */ 26474520Snw141292 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 26484520Snw141292 req, res); 26494520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 26504520Snw141292 retcode = generate_localsid(req, res, is_user); 26514520Snw141292 goto out; 26524520Snw141292 } else if (retcode == IDMAP_SUCCESS) 26534520Snw141292 goto out; 26544520Snw141292 26554520Snw141292 fallback_localsid: 26564520Snw141292 /* 26574520Snw141292 * Here we generate localsid as fallback id on errors. Our 26584520Snw141292 * return status is the error that's been previously assigned. 26594520Snw141292 */ 26604520Snw141292 (void) generate_localsid(req, res, is_user); 26614520Snw141292 26624520Snw141292 out: 26634520Snw141292 if (retcode == IDMAP_SUCCESS) { 26644864Sbaban if (req->id1name.idmap_utf8str_val == NULL && 26654864Sbaban unixname != NULL) { 26664520Snw141292 str = &req->id1name; 26674520Snw141292 retcode = idmap_str2utf8(&str, unixname, 0); 26684520Snw141292 } 26694520Snw141292 } 26704520Snw141292 if (req->direction != _IDMAP_F_DONE) 26714520Snw141292 state->pid2sid_done = FALSE; 26724520Snw141292 res->retcode = idmap_stat4prot(retcode); 26734520Snw141292 return (retcode); 26744520Snw141292 } 26754520Snw141292 26764520Snw141292 static idmap_retcode 26774520Snw141292 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 26784520Snw141292 char **domain, int *type) { 26794520Snw141292 int ret; 26804520Snw141292 idmap_query_state_t *qs = NULL; 26814520Snw141292 idmap_retcode rc, retcode; 26824520Snw141292 26834520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 26844520Snw141292 26854520Snw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 26864520Snw141292 if (ret != 0) { 26874520Snw141292 idmapdlog(LOG_ERR, 26884520Snw141292 "Failed to create sid2name batch for AD lookup"); 26894520Snw141292 retcode = IDMAP_ERR_INTERNAL; 26904520Snw141292 goto out; 26914520Snw141292 } 26924520Snw141292 26934520Snw141292 ret = idmap_sid2name_batch_add1( 26944520Snw141292 qs, sidprefix, &rid, name, domain, type, &rc); 26954520Snw141292 if (ret != 0) { 26964520Snw141292 idmapdlog(LOG_ERR, 26974520Snw141292 "Failed to batch sid2name for AD lookup"); 26984520Snw141292 retcode = IDMAP_ERR_INTERNAL; 26994520Snw141292 goto out; 27004520Snw141292 } 27014520Snw141292 27024520Snw141292 out: 27034864Sbaban if (qs != NULL) { 27044520Snw141292 ret = idmap_lookup_batch_end(&qs, NULL); 27054520Snw141292 if (ret != 0) { 27064520Snw141292 idmapdlog(LOG_ERR, 27074520Snw141292 "Failed to execute sid2name AD lookup"); 27084520Snw141292 retcode = IDMAP_ERR_INTERNAL; 27094520Snw141292 } else 27104520Snw141292 retcode = rc; 27114520Snw141292 } 27124520Snw141292 27134520Snw141292 return (retcode); 27144520Snw141292 } 27154520Snw141292 27164644Sbaban static int 27174644Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 27184520Snw141292 { 27194644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 27204644Sbaban 27214520Snw141292 mapping->flag = request->flag; 27224520Snw141292 mapping->direction = request->direction; 27234644Sbaban mapping->id2.idtype = request->id2.idtype; 27244520Snw141292 27254520Snw141292 mapping->id1.idtype = request->id1.idtype; 27264520Snw141292 if (request->id1.idtype == IDMAP_SID) { 27274520Snw141292 mapping->id1.idmap_id_u.sid.rid = 27284520Snw141292 request->id1.idmap_id_u.sid.rid; 27294644Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 27304520Snw141292 mapping->id1.idmap_id_u.sid.prefix = 27314520Snw141292 strdup(request->id1.idmap_id_u.sid.prefix); 27324644Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 27334644Sbaban return (-1); 27344644Sbaban } 27354520Snw141292 } else { 27364520Snw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 27374520Snw141292 } 27384520Snw141292 27394520Snw141292 mapping->id1domain.idmap_utf8str_len = 27404520Snw141292 request->id1domain.idmap_utf8str_len; 27414644Sbaban if (mapping->id1domain.idmap_utf8str_len) { 27424520Snw141292 mapping->id1domain.idmap_utf8str_val = 27434520Snw141292 strdup(request->id1domain.idmap_utf8str_val); 27444644Sbaban if (mapping->id1domain.idmap_utf8str_val == NULL) 27454644Sbaban return (-1); 27464644Sbaban } 27474520Snw141292 27484520Snw141292 mapping->id1name.idmap_utf8str_len = 27494520Snw141292 request->id1name.idmap_utf8str_len; 27504644Sbaban if (mapping->id1name.idmap_utf8str_len) { 27514520Snw141292 mapping->id1name.idmap_utf8str_val = 27524520Snw141292 strdup(request->id1name.idmap_utf8str_val); 27534644Sbaban if (mapping->id1name.idmap_utf8str_val == NULL) 27544644Sbaban return (-1); 27554644Sbaban } 27564520Snw141292 27574644Sbaban /* We don't need the rest of the request i.e request->id2 */ 27584644Sbaban return (0); 27594644Sbaban 27604644Sbaban errout: 27614864Sbaban if (mapping->id1.idmap_id_u.sid.prefix != NULL) { 27624644Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 27634644Sbaban mapping->id1.idmap_id_u.sid.prefix = NULL; 27644520Snw141292 } 27654520Snw141292 27664864Sbaban if (mapping->id1domain.idmap_utf8str_val != NULL) { 27674644Sbaban free(mapping->id1domain.idmap_utf8str_val); 27684644Sbaban mapping->id1domain.idmap_utf8str_val = NULL; 27694644Sbaban mapping->id1domain.idmap_utf8str_len = 0; 27704644Sbaban } 27714520Snw141292 27724864Sbaban if (mapping->id1name.idmap_utf8str_val != NULL) { 27734644Sbaban free(mapping->id1name.idmap_utf8str_val); 27744644Sbaban mapping->id1name.idmap_utf8str_val = NULL; 27754644Sbaban mapping->id1name.idmap_utf8str_len = 0; 27764644Sbaban } 27774644Sbaban 27784644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 27794644Sbaban return (-1); 27804520Snw141292 } 27814520Snw141292 27824520Snw141292 27834520Snw141292 idmap_retcode 27844520Snw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 27854520Snw141292 idmap_mapping *mapping) { 27864520Snw141292 idmap_id_res idres; 27874520Snw141292 lookup_state_t state; 27884520Snw141292 idmap_utf8str *str; 27894520Snw141292 int is_user; 27904520Snw141292 idmap_retcode retcode; 27914520Snw141292 const char *winname, *windomain; 27924520Snw141292 27934520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 27944520Snw141292 (void) memset(&state, 0, sizeof (state)); 27954520Snw141292 27964520Snw141292 if (request->id2.idtype == IDMAP_UID) 27974520Snw141292 is_user = 1; 27984520Snw141292 else if (request->id2.idtype == IDMAP_GID) 27994520Snw141292 is_user = 0; 28004520Snw141292 else if (request->id2.idtype == IDMAP_POSIXID) 28014520Snw141292 is_user = -1; 28024520Snw141292 else { 28034520Snw141292 retcode = IDMAP_ERR_IDTYPE; 28044520Snw141292 goto out; 28054520Snw141292 } 28064520Snw141292 28074520Snw141292 /* Copy data from request to result */ 28084644Sbaban if (copy_mapping_request(mapping, request) < 0) { 28094644Sbaban retcode = IDMAP_ERR_MEMORY; 28104644Sbaban goto out; 28114644Sbaban } 28124520Snw141292 28134520Snw141292 winname = mapping->id1name.idmap_utf8str_val; 28144520Snw141292 windomain = mapping->id1domain.idmap_utf8str_val; 28154520Snw141292 28164864Sbaban if (winname == NULL && windomain != NULL) { 28174520Snw141292 retcode = IDMAP_ERR_ARG; 28184520Snw141292 goto out; 28194520Snw141292 } 28204520Snw141292 28214864Sbaban if (winname != NULL && windomain == NULL) { 28224520Snw141292 str = &mapping->id1domain; 28234520Snw141292 RDLOCK_CONFIG(); 28244864Sbaban if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { 28254520Snw141292 retcode = idmap_str2utf8(&str, 28264520Snw141292 _idmapdstate.cfg->pgcfg.mapping_domain, 0); 28274520Snw141292 if (retcode != IDMAP_SUCCESS) { 28284520Snw141292 UNLOCK_CONFIG(); 28294520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 28304520Snw141292 retcode = IDMAP_ERR_MEMORY; 28314520Snw141292 goto out; 28324520Snw141292 } 28334520Snw141292 } 28344520Snw141292 UNLOCK_CONFIG(); 28354520Snw141292 windomain = mapping->id1domain.idmap_utf8str_val; 28364520Snw141292 } 28374520Snw141292 28384864Sbaban if (winname != NULL && mapping->id1.idmap_id_u.sid.prefix == NULL) { 28394520Snw141292 retcode = lookup_name2sid(cache, winname, windomain, 28404520Snw141292 &is_user, &mapping->id1.idmap_id_u.sid.prefix, 28414520Snw141292 &mapping->id1.idmap_id_u.sid.rid, mapping); 28424520Snw141292 if (retcode != IDMAP_SUCCESS) 28434520Snw141292 goto out; 28444520Snw141292 if (mapping->id2.idtype == IDMAP_POSIXID) 28454520Snw141292 mapping->id2.idtype = is_user?IDMAP_UID:IDMAP_GID; 28464520Snw141292 } 28474520Snw141292 28484520Snw141292 state.sid2pid_done = TRUE; 28494520Snw141292 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 28504520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 28514520Snw141292 goto out; 28524520Snw141292 28534520Snw141292 if (state.ad_nqueries) { 28544520Snw141292 /* sid2name AD lookup */ 28554520Snw141292 retcode = lookup_win_sid2name( 28564520Snw141292 mapping->id1.idmap_id_u.sid.prefix, 28574520Snw141292 mapping->id1.idmap_id_u.sid.rid, 28584520Snw141292 &mapping->id1name.idmap_utf8str_val, 28594520Snw141292 &mapping->id1domain.idmap_utf8str_val, 28604520Snw141292 (int *)&idres.id.idtype); 28614520Snw141292 28624520Snw141292 idres.retcode = retcode; 28634520Snw141292 } 28644520Snw141292 28654520Snw141292 state.sid2pid_done = TRUE; 28664520Snw141292 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 28674520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 28684520Snw141292 goto out; 28694520Snw141292 28704520Snw141292 /* Update cache */ 28714520Snw141292 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 28724520Snw141292 28734520Snw141292 out: 28744520Snw141292 if (retcode == IDMAP_SUCCESS) { 28754520Snw141292 mapping->direction = idres.direction; 28764520Snw141292 mapping->id2 = idres.id; 28774520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 28784864Sbaban } else { 28794864Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 28804520Snw141292 } 28814520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 28824520Snw141292 return (retcode); 28834520Snw141292 } 28844520Snw141292 28854520Snw141292 idmap_retcode 28864520Snw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 28874520Snw141292 idmap_mapping *mapping, int is_user) { 28884520Snw141292 idmap_id_res idres; 28894520Snw141292 lookup_state_t state; 28904520Snw141292 struct passwd pwd; 28914520Snw141292 struct group grp; 28924520Snw141292 char buf[1024]; 28934520Snw141292 int errnum; 28944520Snw141292 idmap_retcode retcode; 28954520Snw141292 const char *unixname; 28964520Snw141292 const char *me = "get_u2w_mapping"; 28974520Snw141292 28984520Snw141292 /* 28994520Snw141292 * In order to re-use the pid2sid code, we convert 29004520Snw141292 * our input data into structs that are expected by 29014520Snw141292 * pid2sid_first_pass. 29024520Snw141292 */ 29034520Snw141292 29044520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 29054520Snw141292 (void) memset(&state, 0, sizeof (state)); 29064520Snw141292 29074520Snw141292 /* Copy data from request to result */ 29084644Sbaban if (copy_mapping_request(mapping, request) < 0) { 29094644Sbaban retcode = IDMAP_ERR_MEMORY; 29104644Sbaban goto out; 29114644Sbaban } 29124520Snw141292 29134520Snw141292 unixname = mapping->id1name.idmap_utf8str_val; 29144520Snw141292 29154520Snw141292 if (unixname == NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 29164520Snw141292 retcode = IDMAP_ERR_ARG; 29174520Snw141292 goto out; 29184520Snw141292 } 29194520Snw141292 29204864Sbaban if (unixname != NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 29214520Snw141292 /* Get uid/gid by name */ 29224520Snw141292 if (is_user) { 29234520Snw141292 errno = 0; 29244520Snw141292 if (getpwnam_r(unixname, &pwd, buf, 29254520Snw141292 sizeof (buf)) == NULL) { 29264520Snw141292 errnum = errno; 29274520Snw141292 idmapdlog(LOG_WARNING, 29284520Snw141292 "%s: getpwnam_r(%s) failed (%s).", 29294520Snw141292 me, unixname, 29304520Snw141292 errnum?strerror(errnum):"not found"); 29314520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 29324520Snw141292 IDMAP_ERR_INTERNAL; 29334520Snw141292 goto out; 29344520Snw141292 } 29354520Snw141292 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 29364520Snw141292 } else { 29374520Snw141292 errno = 0; 29384520Snw141292 if (getgrnam_r(unixname, &grp, buf, 29394520Snw141292 sizeof (buf)) == NULL) { 29404520Snw141292 errnum = errno; 29414520Snw141292 idmapdlog(LOG_WARNING, 29424520Snw141292 "%s: getgrnam_r(%s) failed (%s).", 29434520Snw141292 me, unixname, 29444520Snw141292 errnum?strerror(errnum):"not found"); 29454520Snw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 29464520Snw141292 IDMAP_ERR_INTERNAL; 29474520Snw141292 goto out; 29484520Snw141292 } 29494520Snw141292 mapping->id1.idmap_id_u.gid = grp.gr_gid; 29504520Snw141292 } 29514520Snw141292 } 29524520Snw141292 29534520Snw141292 state.pid2sid_done = TRUE; 29544520Snw141292 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 29554520Snw141292 is_user, 1); 29564520Snw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 29574520Snw141292 goto out; 29584520Snw141292 29594520Snw141292 /* Update cache */ 29604520Snw141292 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 29614520Snw141292 29624520Snw141292 out: 29634520Snw141292 mapping->direction = idres.direction; 29644520Snw141292 mapping->id2 = idres.id; 29654520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 29664520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 29674520Snw141292 return (retcode); 29684520Snw141292 } 2969