1c5c4113dSnw141292 /* 2c5c4113dSnw141292 * CDDL HEADER START 3c5c4113dSnw141292 * 4c5c4113dSnw141292 * The contents of this file are subject to the terms of the 5c5c4113dSnw141292 * Common Development and Distribution License (the "License"). 6c5c4113dSnw141292 * You may not use this file except in compliance with the License. 7c5c4113dSnw141292 * 8c5c4113dSnw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c5c4113dSnw141292 * or http://www.opensolaris.org/os/licensing. 10c5c4113dSnw141292 * See the License for the specific language governing permissions 11c5c4113dSnw141292 * and limitations under the License. 12c5c4113dSnw141292 * 13c5c4113dSnw141292 * When distributing Covered Code, include this CDDL HEADER in each 14c5c4113dSnw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c5c4113dSnw141292 * If applicable, add the following below this CDDL HEADER, with the 16c5c4113dSnw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17c5c4113dSnw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18c5c4113dSnw141292 * 19c5c4113dSnw141292 * CDDL HEADER END 20c5c4113dSnw141292 */ 21c5c4113dSnw141292 /* 22c5c4113dSnw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23c5c4113dSnw141292 * Use is subject to license terms. 24c5c4113dSnw141292 */ 25c5c4113dSnw141292 26c5c4113dSnw141292 #pragma ident "%Z%%M% %I% %E% SMI" 27c5c4113dSnw141292 28c5c4113dSnw141292 /* 29c5c4113dSnw141292 * Database related utility routines 30c5c4113dSnw141292 */ 31c5c4113dSnw141292 32c8e26105Sjp151216 #include <atomic.h> 33c5c4113dSnw141292 #include <stdio.h> 34c5c4113dSnw141292 #include <stdlib.h> 35c5c4113dSnw141292 #include <string.h> 36c5c4113dSnw141292 #include <errno.h> 37c5c4113dSnw141292 #include <sys/types.h> 38c5c4113dSnw141292 #include <sys/stat.h> 39c5c4113dSnw141292 #include <rpc/rpc.h> 40c5c4113dSnw141292 #include <sys/sid.h> 41c5c4113dSnw141292 #include <time.h> 42c5c4113dSnw141292 #include <pwd.h> 43c5c4113dSnw141292 #include <grp.h> 4484decf41Sjp151216 #include <pthread.h> 4584decf41Sjp151216 #include <assert.h> 46*cd37da74Snw141292 #include <sys/u8_textprep.h> 47c5c4113dSnw141292 48c5c4113dSnw141292 #include "idmapd.h" 49c5c4113dSnw141292 #include "adutils.h" 50c5c4113dSnw141292 #include "string.h" 51c5c4113dSnw141292 #include "idmap_priv.h" 52*cd37da74Snw141292 #include "schema.h" 53c5c4113dSnw141292 5484decf41Sjp151216 55c8e26105Sjp151216 static int degraded = 0; /* whether the FMRI has been marked degraded */ 56c8e26105Sjp151216 57c5c4113dSnw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 58c5c4113dSnw141292 sqlite_vm **, int *, int, const char ***); 59*cd37da74Snw141292 static idmap_retcode lookup_wksids_name2sid(const char *, char **, char **, 6062c60062Sbaban idmap_rid_t *, int *); 61c5c4113dSnw141292 62c5c4113dSnw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 63c5c4113dSnw141292 64c5c4113dSnw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 65c5c4113dSnw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 66c5c4113dSnw141292 67c5c4113dSnw141292 #define AVOID_NAMESERVICE(req)\ 68c5c4113dSnw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 69c5c4113dSnw141292 70c5c4113dSnw141292 #define IS_EPHEMERAL(pid) (pid > INT32_MAX) 71c5c4113dSnw141292 72c5c4113dSnw141292 #define LOCALRID_MIN 1000 73c5c4113dSnw141292 74c5c4113dSnw141292 75c5c4113dSnw141292 76c5c4113dSnw141292 typedef enum init_db_option { 77c5c4113dSnw141292 FAIL_IF_CORRUPT = 0, 78c5c4113dSnw141292 REMOVE_IF_CORRUPT = 1 79c5c4113dSnw141292 } init_db_option_t; 80c5c4113dSnw141292 8184decf41Sjp151216 /* 8284decf41Sjp151216 * Thread specfic data to hold the database handles so that the 8384decf41Sjp151216 * databaes are not opened and closed for every request. It also 8484decf41Sjp151216 * contains the sqlite busy handler structure. 8584decf41Sjp151216 */ 8684decf41Sjp151216 8784decf41Sjp151216 struct idmap_busy { 8884decf41Sjp151216 const char *name; 8984decf41Sjp151216 const int *delays; 9084decf41Sjp151216 int delay_size; 9184decf41Sjp151216 int total; 9284decf41Sjp151216 int sec; 9384decf41Sjp151216 }; 9484decf41Sjp151216 9584decf41Sjp151216 9684decf41Sjp151216 typedef struct idmap_tsd { 9784decf41Sjp151216 sqlite *db_db; 9884decf41Sjp151216 sqlite *cache_db; 9984decf41Sjp151216 struct idmap_busy cache_busy; 10084decf41Sjp151216 struct idmap_busy db_busy; 10184decf41Sjp151216 } idmap_tsd_t; 10284decf41Sjp151216 10384decf41Sjp151216 10484decf41Sjp151216 10584decf41Sjp151216 static const int cache_delay_table[] = 10684decf41Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 10784decf41Sjp151216 50, 50, 60, 70, 80, 90, 100}; 10884decf41Sjp151216 10984decf41Sjp151216 static const int db_delay_table[] = 11084decf41Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 11184decf41Sjp151216 11284decf41Sjp151216 11384decf41Sjp151216 static pthread_key_t idmap_tsd_key; 11484decf41Sjp151216 11584decf41Sjp151216 void 11684decf41Sjp151216 idmap_tsd_destroy(void *key) 11784decf41Sjp151216 { 11884decf41Sjp151216 11984decf41Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 12084decf41Sjp151216 if (tsd) { 12184decf41Sjp151216 if (tsd->db_db) 12284decf41Sjp151216 (void) sqlite_close(tsd->db_db); 12384decf41Sjp151216 if (tsd->cache_db) 12484decf41Sjp151216 (void) sqlite_close(tsd->cache_db); 12584decf41Sjp151216 free(tsd); 12684decf41Sjp151216 } 12784decf41Sjp151216 } 12884decf41Sjp151216 12984decf41Sjp151216 int 130*cd37da74Snw141292 idmap_init_tsd_key(void) 131*cd37da74Snw141292 { 13284decf41Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 13384decf41Sjp151216 } 13484decf41Sjp151216 13584decf41Sjp151216 13684decf41Sjp151216 13784decf41Sjp151216 idmap_tsd_t * 13884decf41Sjp151216 idmap_get_tsd(void) 13984decf41Sjp151216 { 14084decf41Sjp151216 idmap_tsd_t *tsd; 14184decf41Sjp151216 14284decf41Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 14384decf41Sjp151216 /* No thread specific data so create it */ 14484decf41Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 14584decf41Sjp151216 /* Initialize thread specific data */ 14684decf41Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 14784decf41Sjp151216 /* save the trhread specific data */ 14884decf41Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 14984decf41Sjp151216 /* Can't store key */ 15084decf41Sjp151216 free(tsd); 15184decf41Sjp151216 tsd = NULL; 15284decf41Sjp151216 } 15384decf41Sjp151216 } else { 15484decf41Sjp151216 tsd = NULL; 15584decf41Sjp151216 } 15684decf41Sjp151216 } 15784decf41Sjp151216 15884decf41Sjp151216 return (tsd); 15984decf41Sjp151216 } 16084decf41Sjp151216 161*cd37da74Snw141292 static 162*cd37da74Snw141292 const char * 163*cd37da74Snw141292 get_fmri(void) 164*cd37da74Snw141292 { 165*cd37da74Snw141292 static char *fmri = NULL; 166*cd37da74Snw141292 static char buf[60]; 167*cd37da74Snw141292 char *s; 168*cd37da74Snw141292 169*cd37da74Snw141292 membar_consumer(); 170*cd37da74Snw141292 s = fmri; 171*cd37da74Snw141292 if (s != NULL && *s == '\0') 172*cd37da74Snw141292 return (NULL); 173*cd37da74Snw141292 else if (s != NULL) 174*cd37da74Snw141292 return (s); 175*cd37da74Snw141292 176*cd37da74Snw141292 if ((s = getenv("SMF_FMRI")) == NULL || strlen(s) >= sizeof (buf)) 177*cd37da74Snw141292 buf[0] = '\0'; 178*cd37da74Snw141292 else 179*cd37da74Snw141292 (void) strlcpy(buf, s, sizeof (buf)); 180*cd37da74Snw141292 181*cd37da74Snw141292 membar_producer(); 182*cd37da74Snw141292 fmri = buf; 183*cd37da74Snw141292 184*cd37da74Snw141292 return (get_fmri()); 185*cd37da74Snw141292 } 186*cd37da74Snw141292 187c8e26105Sjp151216 /* 188c8e26105Sjp151216 * Wrappers for smf_degrade/restore_instance() 189c8e26105Sjp151216 * 190c8e26105Sjp151216 * smf_restore_instance() is too heavy duty to be calling every time we 191c8e26105Sjp151216 * have a successful AD name<->SID lookup. 192c8e26105Sjp151216 */ 193c8e26105Sjp151216 void 194c8e26105Sjp151216 degrade_svc(void) 195c8e26105Sjp151216 { 196*cd37da74Snw141292 const char *fmri; 197*cd37da74Snw141292 198*cd37da74Snw141292 if ((fmri = get_fmri()) == NULL) 199*cd37da74Snw141292 return; 200*cd37da74Snw141292 201c8e26105Sjp151216 membar_consumer(); 202c8e26105Sjp151216 if (degraded) 203c8e26105Sjp151216 return; 204*cd37da74Snw141292 205*cd37da74Snw141292 (void) smf_degrade_instance(fmri, 0); 206c8e26105Sjp151216 membar_producer(); 207c8e26105Sjp151216 degraded = 1; 208c8e26105Sjp151216 } 209c8e26105Sjp151216 210c8e26105Sjp151216 211c8e26105Sjp151216 void 212c8e26105Sjp151216 restore_svc(void) 213c8e26105Sjp151216 { 214*cd37da74Snw141292 const char *fmri; 215*cd37da74Snw141292 216*cd37da74Snw141292 if ((fmri = get_fmri()) == NULL) 217*cd37da74Snw141292 return; 218*cd37da74Snw141292 219c8e26105Sjp151216 membar_consumer(); 220c8e26105Sjp151216 if (!degraded) 221c8e26105Sjp151216 return; 222*cd37da74Snw141292 (void) smf_restore_instance(fmri); 223c8e26105Sjp151216 membar_producer(); 224c8e26105Sjp151216 degraded = 0; 225c8e26105Sjp151216 } 22684decf41Sjp151216 227*cd37da74Snw141292 /* 228*cd37da74Snw141292 * A simple wrapper around u8_textprep_str() that returns the Unicode 229*cd37da74Snw141292 * lower-case version of some string. The result must be freed. 230*cd37da74Snw141292 */ 231*cd37da74Snw141292 char * 232*cd37da74Snw141292 tolower_u8(const char *s) 233*cd37da74Snw141292 { 234*cd37da74Snw141292 char *res = NULL; 235*cd37da74Snw141292 char *outs; 236*cd37da74Snw141292 size_t inlen, outlen, inbytesleft, outbytesleft; 237*cd37da74Snw141292 int rc, err; 238*cd37da74Snw141292 239*cd37da74Snw141292 /* 240*cd37da74Snw141292 * u8_textprep_str() does not allocate memory. The input and 241*cd37da74Snw141292 * output buffers may differ in size (though that would be more 242*cd37da74Snw141292 * likely when normalization is done). We have to loop over it... 243*cd37da74Snw141292 * 244*cd37da74Snw141292 * To improve the chances that we can avoid looping we add 10 245*cd37da74Snw141292 * bytes of output buffer room the first go around. 246*cd37da74Snw141292 */ 247*cd37da74Snw141292 inlen = inbytesleft = strlen(s); 248*cd37da74Snw141292 outlen = outbytesleft = inlen + 10; 249*cd37da74Snw141292 if ((res = malloc(outlen)) == NULL) 250*cd37da74Snw141292 return (NULL); 251*cd37da74Snw141292 outs = res; 252*cd37da74Snw141292 253*cd37da74Snw141292 while ((rc = u8_textprep_str((char *)s, &inbytesleft, outs, 254*cd37da74Snw141292 &outbytesleft, U8_TEXTPREP_TOLOWER, U8_UNICODE_LATEST, &err)) < 0 && 255*cd37da74Snw141292 err == E2BIG) { 256*cd37da74Snw141292 if ((res = realloc(res, outlen + inbytesleft)) == NULL) 257*cd37da74Snw141292 return (NULL); 258*cd37da74Snw141292 /* adjust input/output buffer pointers */ 259*cd37da74Snw141292 s += (inlen - inbytesleft); 260*cd37da74Snw141292 outs = res + outlen - outbytesleft; 261*cd37da74Snw141292 /* adjust outbytesleft and outlen */ 262*cd37da74Snw141292 outlen += inbytesleft; 263*cd37da74Snw141292 outbytesleft += inbytesleft; 264*cd37da74Snw141292 } 265*cd37da74Snw141292 266*cd37da74Snw141292 if (rc < 0) { 267*cd37da74Snw141292 free(res); 268*cd37da74Snw141292 res = NULL; 269*cd37da74Snw141292 return (NULL); 270*cd37da74Snw141292 } 271*cd37da74Snw141292 272*cd37da74Snw141292 res[outlen - outbytesleft] = '\0'; 273*cd37da74Snw141292 274*cd37da74Snw141292 return (res); 275*cd37da74Snw141292 } 276*cd37da74Snw141292 277*cd37da74Snw141292 static int sql_exec_tran_no_cb(sqlite *db, char *sql, const char *dbname, 278*cd37da74Snw141292 const char *while_doing); 279*cd37da74Snw141292 280c5c4113dSnw141292 281c5c4113dSnw141292 /* 282c5c4113dSnw141292 * Initialize 'dbname' using 'sql' 283c5c4113dSnw141292 */ 284*cd37da74Snw141292 static 285*cd37da74Snw141292 int 286*cd37da74Snw141292 init_db_instance(const char *dbname, int version, 287*cd37da74Snw141292 const char *detect_version_sql, char * const *sql, 288*cd37da74Snw141292 init_db_option_t opt, int *created, int *upgraded) 289c5c4113dSnw141292 { 290*cd37da74Snw141292 int rc, curr_version; 291*cd37da74Snw141292 int tries = 1; 292*cd37da74Snw141292 int prio = LOG_NOTICE; 293c5c4113dSnw141292 sqlite *db = NULL; 294*cd37da74Snw141292 char *errmsg = NULL; 295c5c4113dSnw141292 296*cd37da74Snw141292 *created = 0; 297*cd37da74Snw141292 *upgraded = 0; 298c5c4113dSnw141292 299*cd37da74Snw141292 if (opt == REMOVE_IF_CORRUPT) 300*cd37da74Snw141292 tries = 3; 301*cd37da74Snw141292 302*cd37da74Snw141292 rinse_repeat: 303*cd37da74Snw141292 if (tries == 0) { 304*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to initialize db %s", dbname); 305c5c4113dSnw141292 return (-1); 306*cd37da74Snw141292 } 307*cd37da74Snw141292 if (tries-- == 1) 308*cd37da74Snw141292 /* Last try, log errors */ 309*cd37da74Snw141292 prio = LOG_ERR; 310c5c4113dSnw141292 311*cd37da74Snw141292 db = sqlite_open(dbname, 0600, &errmsg); 312*cd37da74Snw141292 if (db == NULL) { 313*cd37da74Snw141292 idmapdlog(prio, "Error creating database %s (%s)", 314*cd37da74Snw141292 dbname, CHECK_NULL(errmsg)); 315*cd37da74Snw141292 sqlite_freemem(errmsg); 316*cd37da74Snw141292 if (opt == REMOVE_IF_CORRUPT) 317c5c4113dSnw141292 (void) unlink(dbname); 318*cd37da74Snw141292 goto rinse_repeat; 319c5c4113dSnw141292 } 320c5c4113dSnw141292 321c5c4113dSnw141292 sqlite_busy_timeout(db, 3000); 322*cd37da74Snw141292 323*cd37da74Snw141292 /* Detect current version of schema in the db, if any */ 324*cd37da74Snw141292 curr_version = 0; 325*cd37da74Snw141292 if (detect_version_sql != NULL) { 326*cd37da74Snw141292 char *end, **results; 327*cd37da74Snw141292 int nrow; 328*cd37da74Snw141292 329*cd37da74Snw141292 #ifdef IDMAPD_DEBUG 330*cd37da74Snw141292 (void) fprintf(stderr, "Schema version detection SQL: %s\n", 331*cd37da74Snw141292 detect_version_sql); 332*cd37da74Snw141292 #endif /* IDMAPD_DEBUG */ 333*cd37da74Snw141292 rc = sqlite_get_table(db, detect_version_sql, &results, 334*cd37da74Snw141292 &nrow, NULL, &errmsg); 335*cd37da74Snw141292 if (rc != SQLITE_OK) { 336*cd37da74Snw141292 idmapdlog(prio, 337*cd37da74Snw141292 "Error detecting schema version of db %s (%s)", 338*cd37da74Snw141292 dbname, errmsg); 339*cd37da74Snw141292 sqlite_freemem(errmsg); 340*cd37da74Snw141292 sqlite_free_table(results); 341c5c4113dSnw141292 sqlite_close(db); 342*cd37da74Snw141292 return (-1); 343*cd37da74Snw141292 } 344*cd37da74Snw141292 if (nrow != 1) { 345*cd37da74Snw141292 idmapdlog(prio, 346*cd37da74Snw141292 "Error detecting schema version of db %s", dbname); 347*cd37da74Snw141292 sqlite_close(db); 348*cd37da74Snw141292 sqlite_free_table(results); 349*cd37da74Snw141292 return (-1); 350*cd37da74Snw141292 } 351*cd37da74Snw141292 curr_version = strtol(results[1], &end, 10); 352*cd37da74Snw141292 sqlite_free_table(results); 353c5c4113dSnw141292 } 354c5c4113dSnw141292 355*cd37da74Snw141292 if (curr_version < 0) { 356*cd37da74Snw141292 if (opt == REMOVE_IF_CORRUPT) 357*cd37da74Snw141292 (void) unlink(dbname); 358*cd37da74Snw141292 goto rinse_repeat; 359c5c4113dSnw141292 } 360c5c4113dSnw141292 361*cd37da74Snw141292 if (curr_version == version) 362*cd37da74Snw141292 goto done; 363*cd37da74Snw141292 364*cd37da74Snw141292 /* Install or upgrade schema */ 365*cd37da74Snw141292 #ifdef IDMAPD_DEBUG 366*cd37da74Snw141292 (void) fprintf(stderr, "Schema init/upgrade SQL: %s\n", 367*cd37da74Snw141292 sql[curr_version]); 368*cd37da74Snw141292 #endif /* IDMAPD_DEBUG */ 369*cd37da74Snw141292 rc = sql_exec_tran_no_cb(db, sql[curr_version], dbname, 370*cd37da74Snw141292 (curr_version == 0) ? "installing schema" : "upgrading schema"); 371*cd37da74Snw141292 if (rc != 0) { 372*cd37da74Snw141292 idmapdlog(prio, "Error %s schema for db %s", dbname, 373*cd37da74Snw141292 (curr_version == 0) ? "installing schema" : 374*cd37da74Snw141292 "upgrading schema"); 375*cd37da74Snw141292 if (opt == REMOVE_IF_CORRUPT) 376*cd37da74Snw141292 (void) unlink(dbname); 377*cd37da74Snw141292 goto rinse_repeat; 378c5c4113dSnw141292 } 379c5c4113dSnw141292 380*cd37da74Snw141292 *upgraded = (curr_version > 0); 381*cd37da74Snw141292 *created = (curr_version == 0); 382*cd37da74Snw141292 383*cd37da74Snw141292 done: 384c5c4113dSnw141292 (void) sqlite_close(db); 385*cd37da74Snw141292 return (0); 386c5c4113dSnw141292 } 387c5c4113dSnw141292 38884decf41Sjp151216 38984decf41Sjp151216 /* 39084decf41Sjp151216 * This is the SQLite database busy handler that retries the SQL 39184decf41Sjp151216 * operation until it is successful. 39284decf41Sjp151216 */ 39384decf41Sjp151216 int 39484decf41Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 39584decf41Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 39684decf41Sjp151216 { 39784decf41Sjp151216 struct idmap_busy *busy = arg; 39884decf41Sjp151216 int delay; 39984decf41Sjp151216 struct timespec rqtp; 40084decf41Sjp151216 40184decf41Sjp151216 if (count == 1) { 40284decf41Sjp151216 busy->total = 0; 40384decf41Sjp151216 busy->sec = 2; 40484decf41Sjp151216 } 40584decf41Sjp151216 if (busy->total > 1000 * busy->sec) { 40684decf41Sjp151216 idmapdlog(LOG_ERR, 40784decf41Sjp151216 "Thread %d waited %d sec for the %s database", 40884decf41Sjp151216 pthread_self(), busy->sec, busy->name); 40984decf41Sjp151216 busy->sec++; 41084decf41Sjp151216 } 41184decf41Sjp151216 41284decf41Sjp151216 if (count <= busy->delay_size) { 41384decf41Sjp151216 delay = busy->delays[count-1]; 41484decf41Sjp151216 } else { 41584decf41Sjp151216 delay = busy->delays[busy->delay_size - 1]; 41684decf41Sjp151216 } 41784decf41Sjp151216 busy->total += delay; 41884decf41Sjp151216 rqtp.tv_sec = 0; 41984decf41Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 42084decf41Sjp151216 (void) nanosleep(&rqtp, NULL); 42184decf41Sjp151216 return (1); 42284decf41Sjp151216 } 42384decf41Sjp151216 42484decf41Sjp151216 425c5c4113dSnw141292 /* 426c5c4113dSnw141292 * Get the database handle 427c5c4113dSnw141292 */ 428c5c4113dSnw141292 idmap_retcode 429*cd37da74Snw141292 get_db_handle(sqlite **db) 430*cd37da74Snw141292 { 431c5c4113dSnw141292 char *errmsg; 43284decf41Sjp151216 idmap_tsd_t *tsd; 433c5c4113dSnw141292 434c5c4113dSnw141292 /* 43584decf41Sjp151216 * Retrieve the db handle from thread-specific storage 436c5c4113dSnw141292 * If none exists, open and store in thread-specific storage. 437c5c4113dSnw141292 */ 43884decf41Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 43984decf41Sjp151216 idmapdlog(LOG_ERR, 440*cd37da74Snw141292 "Error getting thread specific data for %s", IDMAP_DBNAME); 44184decf41Sjp151216 return (IDMAP_ERR_MEMORY); 44284decf41Sjp151216 } 443c5c4113dSnw141292 44484decf41Sjp151216 if (tsd->db_db == NULL) { 44584decf41Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 44684decf41Sjp151216 if (tsd->db_db == NULL) { 447*cd37da74Snw141292 idmapdlog(LOG_ERR, "Error opening database %s (%s)", 448c5c4113dSnw141292 IDMAP_DBNAME, CHECK_NULL(errmsg)); 449c5c4113dSnw141292 sqlite_freemem(errmsg); 450*cd37da74Snw141292 return (IDMAP_ERR_DB); 451c5c4113dSnw141292 } 452*cd37da74Snw141292 45384decf41Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 45484decf41Sjp151216 tsd->db_busy.delays = db_delay_table; 45584decf41Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 45684decf41Sjp151216 sizeof (int); 45784decf41Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 45884decf41Sjp151216 &tsd->db_busy); 45984decf41Sjp151216 } 46084decf41Sjp151216 *db = tsd->db_db; 461c5c4113dSnw141292 return (IDMAP_SUCCESS); 462c5c4113dSnw141292 } 463c5c4113dSnw141292 464c5c4113dSnw141292 /* 465c5c4113dSnw141292 * Get the cache handle 466c5c4113dSnw141292 */ 467c5c4113dSnw141292 idmap_retcode 468*cd37da74Snw141292 get_cache_handle(sqlite **cache) 469*cd37da74Snw141292 { 470c5c4113dSnw141292 char *errmsg; 47184decf41Sjp151216 idmap_tsd_t *tsd; 472c5c4113dSnw141292 473c5c4113dSnw141292 /* 47484decf41Sjp151216 * Retrieve the db handle from thread-specific storage 475c5c4113dSnw141292 * If none exists, open and store in thread-specific storage. 476c5c4113dSnw141292 */ 47784decf41Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 478*cd37da74Snw141292 idmapdlog(LOG_ERR, "Error getting thread specific data for %s", 47984decf41Sjp151216 IDMAP_DBNAME); 48084decf41Sjp151216 return (IDMAP_ERR_MEMORY); 48184decf41Sjp151216 } 482c5c4113dSnw141292 48384decf41Sjp151216 if (tsd->cache_db == NULL) { 48484decf41Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 48584decf41Sjp151216 if (tsd->cache_db == NULL) { 486*cd37da74Snw141292 idmapdlog(LOG_ERR, "Error opening database %s (%s)", 487c5c4113dSnw141292 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 488c5c4113dSnw141292 sqlite_freemem(errmsg); 489*cd37da74Snw141292 return (IDMAP_ERR_DB); 490c5c4113dSnw141292 } 491*cd37da74Snw141292 49284decf41Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 49384decf41Sjp151216 tsd->cache_busy.delays = cache_delay_table; 49484decf41Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 49584decf41Sjp151216 sizeof (int); 49684decf41Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 49784decf41Sjp151216 &tsd->cache_busy); 49884decf41Sjp151216 } 49984decf41Sjp151216 *cache = tsd->cache_db; 500c5c4113dSnw141292 return (IDMAP_SUCCESS); 501c5c4113dSnw141292 } 502c5c4113dSnw141292 503c5c4113dSnw141292 /* 504c5c4113dSnw141292 * Initialize cache and db 505c5c4113dSnw141292 */ 506c5c4113dSnw141292 int 507*cd37da74Snw141292 init_dbs() 508*cd37da74Snw141292 { 509*cd37da74Snw141292 char *sql[2]; 510*cd37da74Snw141292 int created, upgraded; 511*cd37da74Snw141292 512c5c4113dSnw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 513*cd37da74Snw141292 sql[0] = DB_INSTALL_SQL; 514*cd37da74Snw141292 sql[1] = DB_UPGRADE_FROM_v1_SQL; 515*cd37da74Snw141292 516*cd37da74Snw141292 if (init_db_instance(IDMAP_DBNAME, DB_VERSION, DB_VERSION_SQL, sql, 517*cd37da74Snw141292 FAIL_IF_CORRUPT, &created, &upgraded) < 0) 518c5c4113dSnw141292 return (-1); 519c5c4113dSnw141292 520c5c4113dSnw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 521*cd37da74Snw141292 sql[0] = CACHE_INSTALL_SQL; 522*cd37da74Snw141292 sql[1] = CACHE_UPGRADE_FROM_v1_SQL; 523*cd37da74Snw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_VERSION, CACHE_VERSION_SQL, 524*cd37da74Snw141292 sql, REMOVE_IF_CORRUPT, &created, &upgraded) < 0) 525c5c4113dSnw141292 return (-1); 526c5c4113dSnw141292 527*cd37da74Snw141292 _idmapdstate.new_eph_db = (created || upgraded) ? 1 : 0; 528*cd37da74Snw141292 529c5c4113dSnw141292 return (0); 530c5c4113dSnw141292 } 531c5c4113dSnw141292 532c5c4113dSnw141292 /* 533c5c4113dSnw141292 * Finalize databases 534c5c4113dSnw141292 */ 535c5c4113dSnw141292 void 536*cd37da74Snw141292 fini_dbs() 537*cd37da74Snw141292 { 538c5c4113dSnw141292 } 539c5c4113dSnw141292 540c5c4113dSnw141292 /* 541c5c4113dSnw141292 * This table is a listing of status codes that will returned to the 542c5c4113dSnw141292 * client when a SQL command fails with the corresponding error message. 543c5c4113dSnw141292 */ 544c5c4113dSnw141292 static msg_table_t sqlmsgtable[] = { 54562c60062Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 546c5c4113dSnw141292 "columns unixname, is_user, u2w_order are not unique"}, 54762c60062Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 548*cd37da74Snw141292 "columns winname, windomain, is_user, is_wuser, w2u_order are not" 549*cd37da74Snw141292 " unique"}, 550*cd37da74Snw141292 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, "Conflicting w2u namerules"}, 551c5c4113dSnw141292 {-1, NULL} 552c5c4113dSnw141292 }; 553c5c4113dSnw141292 554c5c4113dSnw141292 /* 555c5c4113dSnw141292 * idmapd's version of string2stat to map SQLite messages to 556c5c4113dSnw141292 * status codes 557c5c4113dSnw141292 */ 558c5c4113dSnw141292 idmap_retcode 559*cd37da74Snw141292 idmapd_string2stat(const char *msg) 560*cd37da74Snw141292 { 561c5c4113dSnw141292 int i; 562c5c4113dSnw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 563c5c4113dSnw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 564c5c4113dSnw141292 return (sqlmsgtable[i].retcode); 565c5c4113dSnw141292 } 566c5c4113dSnw141292 return (IDMAP_ERR_OTHER); 567c5c4113dSnw141292 } 568c5c4113dSnw141292 569c5c4113dSnw141292 /* 570*cd37da74Snw141292 * Executes some SQL in a transaction. 571*cd37da74Snw141292 * 572*cd37da74Snw141292 * Returns 0 on success, -1 if it failed but the rollback succeeded, -2 573*cd37da74Snw141292 * if the rollback failed. 574*cd37da74Snw141292 */ 575*cd37da74Snw141292 static 576*cd37da74Snw141292 int 577*cd37da74Snw141292 sql_exec_tran_no_cb(sqlite *db, char *sql, const char *dbname, 578*cd37da74Snw141292 const char *while_doing) 579*cd37da74Snw141292 { 580*cd37da74Snw141292 char *errmsg = NULL; 581*cd37da74Snw141292 int rc; 582*cd37da74Snw141292 583*cd37da74Snw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg); 584*cd37da74Snw141292 if (rc != SQLITE_OK) { 585*cd37da74Snw141292 idmapdlog(LOG_ERR, "Begin transaction failed (%s) " 586*cd37da74Snw141292 "while %s (%s)", errmsg, while_doing, dbname); 587*cd37da74Snw141292 sqlite_freemem(errmsg); 588*cd37da74Snw141292 return (-1); 589*cd37da74Snw141292 } 590*cd37da74Snw141292 591*cd37da74Snw141292 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 592*cd37da74Snw141292 if (rc != SQLITE_OK) { 593*cd37da74Snw141292 idmapdlog(LOG_ERR, "Database error (%s) while %s (%s)", errmsg, 594*cd37da74Snw141292 while_doing, dbname); 595*cd37da74Snw141292 sqlite_freemem(errmsg); 596*cd37da74Snw141292 errmsg = NULL; 597*cd37da74Snw141292 goto rollback; 598*cd37da74Snw141292 } 599*cd37da74Snw141292 600*cd37da74Snw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, &errmsg); 601*cd37da74Snw141292 if (rc == SQLITE_OK) { 602*cd37da74Snw141292 sqlite_freemem(errmsg); 603*cd37da74Snw141292 return (0); 604*cd37da74Snw141292 } 605*cd37da74Snw141292 606*cd37da74Snw141292 idmapdlog(LOG_ERR, "Database commit error (%s) while s (%s)", 607*cd37da74Snw141292 errmsg, while_doing, dbname); 608*cd37da74Snw141292 sqlite_freemem(errmsg); 609*cd37da74Snw141292 errmsg = NULL; 610*cd37da74Snw141292 611*cd37da74Snw141292 rollback: 612*cd37da74Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, &errmsg); 613*cd37da74Snw141292 if (rc != SQLITE_OK) { 614*cd37da74Snw141292 idmapdlog(LOG_ERR, "Rollback failed (%s) while %s (%s)", 615*cd37da74Snw141292 errmsg, while_doing, dbname); 616*cd37da74Snw141292 sqlite_freemem(errmsg); 617*cd37da74Snw141292 return (-2); 618*cd37da74Snw141292 } 619*cd37da74Snw141292 sqlite_freemem(errmsg); 620*cd37da74Snw141292 621*cd37da74Snw141292 return (-1); 622*cd37da74Snw141292 } 623*cd37da74Snw141292 624*cd37da74Snw141292 /* 625c5c4113dSnw141292 * Execute the given SQL statment without using any callbacks 626c5c4113dSnw141292 */ 627c5c4113dSnw141292 idmap_retcode 628*cd37da74Snw141292 sql_exec_no_cb(sqlite *db, char *sql) 629*cd37da74Snw141292 { 630c5c4113dSnw141292 char *errmsg = NULL; 63184decf41Sjp151216 int r; 632c5c4113dSnw141292 idmap_retcode retcode; 633c5c4113dSnw141292 634c5c4113dSnw141292 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 63584decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 636c5c4113dSnw141292 637c5c4113dSnw141292 if (r != SQLITE_OK) { 638*cd37da74Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 639*cd37da74Snw141292 CHECK_NULL(errmsg)); 640c5c4113dSnw141292 retcode = idmapd_string2stat(errmsg); 64162c60062Sbaban if (errmsg != NULL) 642c5c4113dSnw141292 sqlite_freemem(errmsg); 643c5c4113dSnw141292 return (retcode); 644c5c4113dSnw141292 } 645c5c4113dSnw141292 646c5c4113dSnw141292 return (IDMAP_SUCCESS); 647c5c4113dSnw141292 } 648c5c4113dSnw141292 649c5c4113dSnw141292 /* 650c5c4113dSnw141292 * Generate expression that can be used in WHERE statements. 651c5c4113dSnw141292 * Examples: 652c5c4113dSnw141292 * <prefix> <col> <op> <value> <suffix> 653c5c4113dSnw141292 * "" "unixuser" "=" "foo" "AND" 654c5c4113dSnw141292 */ 655c5c4113dSnw141292 idmap_retcode 656*cd37da74Snw141292 gen_sql_expr_from_rule(idmap_namerule *rule, char **out) 657*cd37da74Snw141292 { 658*cd37da74Snw141292 char *s_windomain = NULL, *s_winname = NULL; 659*cd37da74Snw141292 char *s_unixname = NULL; 660*cd37da74Snw141292 char *lower_winname; 661*cd37da74Snw141292 int retcode = IDMAP_SUCCESS; 662*cd37da74Snw141292 663c5c4113dSnw141292 if (out == NULL) 664c5c4113dSnw141292 return (IDMAP_ERR_ARG); 665c5c4113dSnw141292 666c5c4113dSnw141292 667*cd37da74Snw141292 if (!EMPTY_STRING(rule->windomain)) { 668*cd37da74Snw141292 s_windomain = sqlite_mprintf("AND windomain = %Q ", 669*cd37da74Snw141292 rule->windomain); 670*cd37da74Snw141292 if (s_windomain == NULL) { 671*cd37da74Snw141292 retcode = IDMAP_ERR_MEMORY; 672*cd37da74Snw141292 goto out; 673c5c4113dSnw141292 } 674*cd37da74Snw141292 } 675*cd37da74Snw141292 676*cd37da74Snw141292 if (!EMPTY_STRING(rule->winname)) { 677*cd37da74Snw141292 if ((lower_winname = tolower_u8(rule->winname)) == NULL) 678*cd37da74Snw141292 lower_winname = rule->winname; 679*cd37da74Snw141292 s_winname = sqlite_mprintf( 680*cd37da74Snw141292 "AND winname = %Q AND is_wuser = %d ", 681*cd37da74Snw141292 lower_winname, rule->is_wuser ? 1 : 0); 682*cd37da74Snw141292 if (lower_winname != rule->winname) 683*cd37da74Snw141292 free(lower_winname); 684*cd37da74Snw141292 if (s_winname == NULL) { 685*cd37da74Snw141292 retcode = IDMAP_ERR_MEMORY; 686*cd37da74Snw141292 goto out; 687*cd37da74Snw141292 } 688*cd37da74Snw141292 } 689*cd37da74Snw141292 690*cd37da74Snw141292 if (!EMPTY_STRING(rule->unixname)) { 691*cd37da74Snw141292 s_unixname = sqlite_mprintf( 692*cd37da74Snw141292 "AND unixname = %Q AND is_user = %d ", 693*cd37da74Snw141292 rule->unixname, rule->is_user ? 1 : 0); 694*cd37da74Snw141292 if (s_unixname == NULL) { 695*cd37da74Snw141292 retcode = IDMAP_ERR_MEMORY; 696*cd37da74Snw141292 goto out; 697*cd37da74Snw141292 } 698*cd37da74Snw141292 } 699*cd37da74Snw141292 700*cd37da74Snw141292 *out = sqlite_mprintf("%s %s %s", 701*cd37da74Snw141292 s_windomain ? s_windomain : "", 702*cd37da74Snw141292 s_winname ? s_winname : "", 703*cd37da74Snw141292 s_unixname ? s_unixname : ""); 704*cd37da74Snw141292 705*cd37da74Snw141292 if (*out == NULL) { 706*cd37da74Snw141292 retcode = IDMAP_ERR_MEMORY; 707*cd37da74Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 708*cd37da74Snw141292 goto out; 709*cd37da74Snw141292 } 710*cd37da74Snw141292 711*cd37da74Snw141292 out: 712*cd37da74Snw141292 if (s_windomain != NULL) 713*cd37da74Snw141292 sqlite_freemem(s_windomain); 714*cd37da74Snw141292 if (s_winname != NULL) 715*cd37da74Snw141292 sqlite_freemem(s_winname); 716*cd37da74Snw141292 if (s_unixname != NULL) 717*cd37da74Snw141292 sqlite_freemem(s_unixname); 718*cd37da74Snw141292 719*cd37da74Snw141292 return (retcode); 720*cd37da74Snw141292 } 721*cd37da74Snw141292 722*cd37da74Snw141292 723c5c4113dSnw141292 724c5c4113dSnw141292 /* 725c5c4113dSnw141292 * Generate and execute SQL statement for LIST RPC calls 726c5c4113dSnw141292 */ 727c5c4113dSnw141292 idmap_retcode 728c5c4113dSnw141292 process_list_svc_sql(sqlite *db, char *sql, uint64_t limit, 729*cd37da74Snw141292 list_svc_cb cb, void *result) 730*cd37da74Snw141292 { 731c5c4113dSnw141292 list_cb_data_t cb_data; 732c5c4113dSnw141292 char *errmsg = NULL; 73384decf41Sjp151216 int r; 734c5c4113dSnw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 735c5c4113dSnw141292 736c5c4113dSnw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 737c5c4113dSnw141292 cb_data.result = result; 738c5c4113dSnw141292 cb_data.limit = limit; 739c5c4113dSnw141292 74084decf41Sjp151216 741c5c4113dSnw141292 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 74284decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 743c5c4113dSnw141292 switch (r) { 744c5c4113dSnw141292 case SQLITE_OK: 745c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 74684decf41Sjp151216 break; 74784decf41Sjp151216 748c5c4113dSnw141292 default: 749c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 750*cd37da74Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 751*cd37da74Snw141292 CHECK_NULL(errmsg)); 75284decf41Sjp151216 break; 753c5c4113dSnw141292 } 75462c60062Sbaban if (errmsg != NULL) 755c5c4113dSnw141292 sqlite_freemem(errmsg); 756c5c4113dSnw141292 return (retcode); 757c5c4113dSnw141292 } 758c5c4113dSnw141292 759c5c4113dSnw141292 /* 760c5c4113dSnw141292 * This routine is called by callbacks that process the results of 761c5c4113dSnw141292 * LIST RPC calls to validate data and to allocate memory for 762c5c4113dSnw141292 * the result array. 763c5c4113dSnw141292 */ 764c5c4113dSnw141292 idmap_retcode 765c5c4113dSnw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 766*cd37da74Snw141292 int ncol, uchar_t **list, size_t valsize) 767*cd37da74Snw141292 { 768c5c4113dSnw141292 size_t nsize; 769c5c4113dSnw141292 void *tmplist; 770c5c4113dSnw141292 771c5c4113dSnw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 772c5c4113dSnw141292 return (IDMAP_NEXT); 773c5c4113dSnw141292 774c5c4113dSnw141292 if (argc < ncol || argv == NULL) { 775c5c4113dSnw141292 idmapdlog(LOG_ERR, "Invalid data"); 776c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 777c5c4113dSnw141292 } 778c5c4113dSnw141292 779c5c4113dSnw141292 /* alloc in bulk to reduce number of reallocs */ 780c5c4113dSnw141292 if (cb_data->next >= cb_data->len) { 781c5c4113dSnw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 782c5c4113dSnw141292 tmplist = realloc(*list, nsize); 783c5c4113dSnw141292 if (tmplist == NULL) { 784c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 785c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 786c5c4113dSnw141292 } 787c5c4113dSnw141292 *list = tmplist; 788c5c4113dSnw141292 (void) memset(*list + (cb_data->len * valsize), 0, 789c5c4113dSnw141292 SIZE_INCR * valsize); 790c5c4113dSnw141292 cb_data->len += SIZE_INCR; 791c5c4113dSnw141292 } 792c5c4113dSnw141292 return (IDMAP_SUCCESS); 793c5c4113dSnw141292 } 794c5c4113dSnw141292 795*cd37da74Snw141292 static 796*cd37da74Snw141292 idmap_retcode 797c5c4113dSnw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 798*cd37da74Snw141292 int direction, int is_diagonal, int *w2u_order, int *u2w_order) 799*cd37da74Snw141292 { 800c5c4113dSnw141292 *w2u_order = 0; 801c5c4113dSnw141292 *u2w_order = 0; 802c5c4113dSnw141292 803c5c4113dSnw141292 /* 804c5c4113dSnw141292 * Windows to UNIX lookup order: 805c5c4113dSnw141292 * 1. winname@domain (or winname) to "" 806c5c4113dSnw141292 * 2. winname@domain (or winname) to unixname 807c5c4113dSnw141292 * 3. winname@* to "" 808c5c4113dSnw141292 * 4. winname@* to unixname 809c5c4113dSnw141292 * 5. *@domain (or *) to * 810c5c4113dSnw141292 * 6. *@domain (or *) to "" 811c5c4113dSnw141292 * 7. *@domain (or *) to unixname 812c5c4113dSnw141292 * 8. *@* to * 813c5c4113dSnw141292 * 9. *@* to "" 814c5c4113dSnw141292 * 10. *@* to unixname 815c5c4113dSnw141292 * 816c5c4113dSnw141292 * winname is a special case of winname@domain when domain is the 817c5c4113dSnw141292 * default domain. Similarly * is a special case of *@domain when 818c5c4113dSnw141292 * domain is the default domain. 819c5c4113dSnw141292 * 820c5c4113dSnw141292 * Note that "" has priority over specific names because "" inhibits 821c5c4113dSnw141292 * mappings and traditionally deny rules always had higher priority. 822c5c4113dSnw141292 */ 823651c0131Sbaban if (direction != IDMAP_DIRECTION_U2W) { 824651c0131Sbaban /* bi-directional or from windows to unix */ 825c5c4113dSnw141292 if (winname == NULL) 826c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 827c5c4113dSnw141292 else if (unixname == NULL) 828c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 829c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 830c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 831c5c4113dSnw141292 else if (*winname == '*' && windomain && *windomain == '*') { 832c5c4113dSnw141292 if (*unixname == '*') 833c5c4113dSnw141292 *w2u_order = 8; 834c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 835c5c4113dSnw141292 *w2u_order = 9; 836c5c4113dSnw141292 else /* unixname == name */ 837c5c4113dSnw141292 *w2u_order = 10; 838c5c4113dSnw141292 } else if (*winname == '*') { 839c5c4113dSnw141292 if (*unixname == '*') 840c5c4113dSnw141292 *w2u_order = 5; 841c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 842c5c4113dSnw141292 *w2u_order = 6; 843c5c4113dSnw141292 else /* name */ 844c5c4113dSnw141292 *w2u_order = 7; 84562c60062Sbaban } else if (windomain != NULL && *windomain == '*') { 846c5c4113dSnw141292 /* winname == name */ 847c5c4113dSnw141292 if (*unixname == '*') 848c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 849c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 850c5c4113dSnw141292 *w2u_order = 3; 851c5c4113dSnw141292 else /* name */ 852c5c4113dSnw141292 *w2u_order = 4; 853c5c4113dSnw141292 } else { 854c5c4113dSnw141292 /* winname == name && windomain == null or name */ 855c5c4113dSnw141292 if (*unixname == '*') 856c5c4113dSnw141292 return (IDMAP_ERR_W2U_NAMERULE); 857c5c4113dSnw141292 else if (EMPTY_NAME(unixname)) 858c5c4113dSnw141292 *w2u_order = 1; 859c5c4113dSnw141292 else /* name */ 860c5c4113dSnw141292 *w2u_order = 2; 861c5c4113dSnw141292 } 862*cd37da74Snw141292 863c5c4113dSnw141292 } 864c5c4113dSnw141292 865c5c4113dSnw141292 /* 866*cd37da74Snw141292 * 1. unixname to "", non-diagonal 867*cd37da74Snw141292 * 2. unixname to winname@domain (or winname), non-diagonal 868*cd37da74Snw141292 * 3. unixname to "", diagonal 869*cd37da74Snw141292 * 4. unixname to winname@domain (or winname), diagonal 870*cd37da74Snw141292 * 5. * to *@domain (or *), non-diagonal 871*cd37da74Snw141292 * 5. * to *@domain (or *), diagonal 872*cd37da74Snw141292 * 7. * to "" 873*cd37da74Snw141292 * 8. * to winname@domain (or winname) 874*cd37da74Snw141292 * 9. * to "", non-diagonal 875*cd37da74Snw141292 * 10. * to winname@domain (or winname), diagonal 876c5c4113dSnw141292 */ 877651c0131Sbaban if (direction != IDMAP_DIRECTION_W2U) { 878*cd37da74Snw141292 int diagonal = is_diagonal ? 1 : 0; 879*cd37da74Snw141292 880651c0131Sbaban /* bi-directional or from unix to windows */ 881c5c4113dSnw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 882c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 883c5c4113dSnw141292 else if (winname == NULL) 884c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 88562c60062Sbaban else if (windomain != NULL && *windomain == '*') 886651c0131Sbaban return (IDMAP_ERR_U2W_NAMERULE); 887c5c4113dSnw141292 else if (*unixname == '*') { 888c5c4113dSnw141292 if (*winname == '*') 889*cd37da74Snw141292 *u2w_order = 5 + diagonal; 890c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 891*cd37da74Snw141292 *u2w_order = 7 + 2 * diagonal; 892c5c4113dSnw141292 else 893*cd37da74Snw141292 *u2w_order = 8 + 2 * diagonal; 894c5c4113dSnw141292 } else { 895c5c4113dSnw141292 if (*winname == '*') 896c5c4113dSnw141292 return (IDMAP_ERR_U2W_NAMERULE); 897c5c4113dSnw141292 else if (EMPTY_NAME(winname)) 898*cd37da74Snw141292 *u2w_order = 1 + 2 * diagonal; 899c5c4113dSnw141292 else 900*cd37da74Snw141292 *u2w_order = 2 + 2 * diagonal; 901c5c4113dSnw141292 } 902c5c4113dSnw141292 } 903c5c4113dSnw141292 return (IDMAP_SUCCESS); 904c5c4113dSnw141292 } 905c5c4113dSnw141292 906c5c4113dSnw141292 /* 907c5c4113dSnw141292 * Generate and execute SQL statement to add name-based mapping rule 908c5c4113dSnw141292 */ 909c5c4113dSnw141292 idmap_retcode 910*cd37da74Snw141292 add_namerule(sqlite *db, idmap_namerule *rule) 911*cd37da74Snw141292 { 912c5c4113dSnw141292 char *sql = NULL; 913c5c4113dSnw141292 idmap_stat retcode; 9148e228215Sdm199847 char *dom = NULL; 915c5c4113dSnw141292 int w2u_order, u2w_order; 916c5c4113dSnw141292 char w2ubuf[11], u2wbuf[11]; 917c5c4113dSnw141292 9188e228215Sdm199847 retcode = get_namerule_order(rule->winname, rule->windomain, 919*cd37da74Snw141292 rule->unixname, rule->direction, 920*cd37da74Snw141292 rule->is_user == rule->is_wuser ? 0 : 1, &w2u_order, &u2w_order); 921c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 922c5c4113dSnw141292 goto out; 923c5c4113dSnw141292 924c5c4113dSnw141292 if (w2u_order) 925c5c4113dSnw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 926c5c4113dSnw141292 if (u2w_order) 927c5c4113dSnw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 928c5c4113dSnw141292 92962c60062Sbaban /* 93062c60062Sbaban * For the triggers on namerules table to work correctly: 93162c60062Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 93262c60062Sbaban * 2) Use "" instead of NULL for "no domain" 93362c60062Sbaban */ 93462c60062Sbaban 9358e228215Sdm199847 if (rule->windomain != NULL) 9368e228215Sdm199847 dom = rule->windomain; 937*cd37da74Snw141292 else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL, NULL) 93862c60062Sbaban == IDMAP_SUCCESS) { 93962c60062Sbaban /* well-known SIDs don't need domain */ 94062c60062Sbaban dom = ""; 94162c60062Sbaban } 942c5c4113dSnw141292 943c5c4113dSnw141292 RDLOCK_CONFIG(); 94462c60062Sbaban if (dom == NULL) { 945c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain) 946c8e26105Sjp151216 dom = _idmapdstate.cfg->pgcfg.default_domain; 947c5c4113dSnw141292 else 948c5c4113dSnw141292 dom = ""; 94962c60062Sbaban } 95084decf41Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 951*cd37da74Snw141292 "(is_user, is_wuser, windomain, winname_display, is_nt4, " 952c5c4113dSnw141292 "unixname, w2u_order, u2w_order) " 953*cd37da74Snw141292 "VALUES(%d, %d, %Q, %Q, %d, %Q, %q, %q);", 954*cd37da74Snw141292 rule->is_user ? 1 : 0, rule->is_wuser ? 1 : 0, dom, 955*cd37da74Snw141292 rule->winname, rule->is_nt4 ? 1 : 0, rule->unixname, 956*cd37da74Snw141292 w2u_order ? w2ubuf : NULL, u2w_order ? u2wbuf : NULL); 957c5c4113dSnw141292 UNLOCK_CONFIG(); 958c5c4113dSnw141292 959c5c4113dSnw141292 if (sql == NULL) { 960c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 961c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 962c5c4113dSnw141292 goto out; 963c5c4113dSnw141292 } 964c5c4113dSnw141292 965c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 966c5c4113dSnw141292 967c5c4113dSnw141292 if (retcode == IDMAP_ERR_OTHER) 968c5c4113dSnw141292 retcode = IDMAP_ERR_CFG; 969c5c4113dSnw141292 970c5c4113dSnw141292 out: 97162c60062Sbaban if (sql != NULL) 972c5c4113dSnw141292 sqlite_freemem(sql); 973c5c4113dSnw141292 return (retcode); 974c5c4113dSnw141292 } 975c5c4113dSnw141292 976c5c4113dSnw141292 /* 977c5c4113dSnw141292 * Flush name-based mapping rules 978c5c4113dSnw141292 */ 979c5c4113dSnw141292 idmap_retcode 980*cd37da74Snw141292 flush_namerules(sqlite *db) 981*cd37da74Snw141292 { 982c5c4113dSnw141292 idmap_stat retcode; 983c5c4113dSnw141292 984*cd37da74Snw141292 retcode = sql_exec_no_cb(db, "DELETE FROM namerules;"); 985c5c4113dSnw141292 986c5c4113dSnw141292 return (retcode); 987c5c4113dSnw141292 } 988c5c4113dSnw141292 989c5c4113dSnw141292 /* 990c5c4113dSnw141292 * Generate and execute SQL statement to remove a name-based mapping rule 991c5c4113dSnw141292 */ 992c5c4113dSnw141292 idmap_retcode 993*cd37da74Snw141292 rm_namerule(sqlite *db, idmap_namerule *rule) 994*cd37da74Snw141292 { 995c5c4113dSnw141292 char *sql = NULL; 996c5c4113dSnw141292 idmap_stat retcode; 997c5c4113dSnw141292 char buf[80]; 998*cd37da74Snw141292 char *expr = NULL; 999c5c4113dSnw141292 10008e228215Sdm199847 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 10018e228215Sdm199847 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 1002c5c4113dSnw141292 return (IDMAP_SUCCESS); 1003c5c4113dSnw141292 1004c5c4113dSnw141292 buf[0] = 0; 1005*cd37da74Snw141292 1006*cd37da74Snw141292 if (rule->direction == IDMAP_DIRECTION_BI) 1007c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 1008c5c4113dSnw141292 " AND u2w_order > 0"); 1009*cd37da74Snw141292 else if (rule->direction == IDMAP_DIRECTION_W2U) 1010c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND w2u_order > 0" 1011c5c4113dSnw141292 " AND (u2w_order = 0 OR u2w_order ISNULL)"); 1012*cd37da74Snw141292 else if (rule->direction == IDMAP_DIRECTION_U2W) 1013c5c4113dSnw141292 (void) snprintf(buf, sizeof (buf), "AND u2w_order > 0" 1014c5c4113dSnw141292 " AND (w2u_order = 0 OR w2u_order ISNULL)"); 1015c5c4113dSnw141292 1016*cd37da74Snw141292 retcode = gen_sql_expr_from_rule(rule, &expr); 1017*cd37da74Snw141292 if (retcode != IDMAP_SUCCESS) 1018c5c4113dSnw141292 goto out; 1019c5c4113dSnw141292 1020*cd37da74Snw141292 sql = sqlite_mprintf("DELETE FROM namerules WHERE 1 %s %s;", expr, 1021c5c4113dSnw141292 buf); 1022c5c4113dSnw141292 1023c5c4113dSnw141292 if (sql == NULL) { 1024c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1025c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1026c5c4113dSnw141292 goto out; 1027c5c4113dSnw141292 } 1028c5c4113dSnw141292 1029*cd37da74Snw141292 1030c5c4113dSnw141292 retcode = sql_exec_no_cb(db, sql); 1031c5c4113dSnw141292 1032c5c4113dSnw141292 out: 1033*cd37da74Snw141292 if (expr != NULL) 1034*cd37da74Snw141292 sqlite_freemem(expr); 103562c60062Sbaban if (sql != NULL) 1036c5c4113dSnw141292 sqlite_freemem(sql); 1037c5c4113dSnw141292 return (retcode); 1038c5c4113dSnw141292 } 1039c5c4113dSnw141292 1040c5c4113dSnw141292 /* 1041c5c4113dSnw141292 * Compile the given SQL query and step just once. 1042c5c4113dSnw141292 * 1043c5c4113dSnw141292 * Input: 1044c5c4113dSnw141292 * db - db handle 1045c5c4113dSnw141292 * sql - SQL statement 1046c5c4113dSnw141292 * 1047c5c4113dSnw141292 * Output: 1048c5c4113dSnw141292 * vm - virtual SQL machine 1049c5c4113dSnw141292 * ncol - number of columns in the result 1050c5c4113dSnw141292 * values - column values 1051c5c4113dSnw141292 * 1052c5c4113dSnw141292 * Return values: 1053c5c4113dSnw141292 * IDMAP_SUCCESS 1054c5c4113dSnw141292 * IDMAP_ERR_NOTFOUND 1055c5c4113dSnw141292 * IDMAP_ERR_INTERNAL 1056c5c4113dSnw141292 */ 1057c5c4113dSnw141292 1058*cd37da74Snw141292 static 1059*cd37da74Snw141292 idmap_retcode 1060c5c4113dSnw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 1061*cd37da74Snw141292 int reqcol, const char ***values) 1062*cd37da74Snw141292 { 1063c5c4113dSnw141292 char *errmsg = NULL; 106484decf41Sjp151216 int r; 1065c5c4113dSnw141292 106684decf41Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 1067*cd37da74Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 1068*cd37da74Snw141292 CHECK_NULL(errmsg)); 1069c5c4113dSnw141292 sqlite_freemem(errmsg); 1070c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1071c5c4113dSnw141292 } 1072c5c4113dSnw141292 1073c5c4113dSnw141292 r = sqlite_step(*vm, ncol, values, NULL); 107484decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 1075c5c4113dSnw141292 107684decf41Sjp151216 if (r == SQLITE_ROW) { 107762c60062Sbaban if (ncol != NULL && *ncol < reqcol) { 1078c5c4113dSnw141292 (void) sqlite_finalize(*vm, NULL); 1079c5c4113dSnw141292 *vm = NULL; 1080c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1081c5c4113dSnw141292 } 1082c5c4113dSnw141292 /* Caller will call finalize after using the results */ 1083c5c4113dSnw141292 return (IDMAP_SUCCESS); 1084c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 1085c5c4113dSnw141292 (void) sqlite_finalize(*vm, NULL); 1086c5c4113dSnw141292 *vm = NULL; 1087c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1088c5c4113dSnw141292 } 1089c5c4113dSnw141292 1090c5c4113dSnw141292 (void) sqlite_finalize(*vm, &errmsg); 1091c5c4113dSnw141292 *vm = NULL; 1092*cd37da74Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 1093*cd37da74Snw141292 CHECK_NULL(errmsg)); 1094c5c4113dSnw141292 sqlite_freemem(errmsg); 1095c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1096c5c4113dSnw141292 } 1097c5c4113dSnw141292 109862c60062Sbaban /* 109962c60062Sbaban * Table for well-known SIDs. 110062c60062Sbaban * 110162c60062Sbaban * Background: 110262c60062Sbaban * 110376b27f93Sbaban * Some of the well-known principals are stored under: 110462c60062Sbaban * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain> 110562c60062Sbaban * They belong to objectClass "foreignSecurityPrincipal". They don't have 110662c60062Sbaban * "samAccountName" nor "userPrincipalName" attributes. Their names are 110762c60062Sbaban * available in "cn" and "name" attributes. Some of these principals have a 110862c60062Sbaban * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and 110962c60062Sbaban * these duplicate entries have the stringified SID in the "name" and "cn" 111062c60062Sbaban * attributes instead of the actual name. 111162c60062Sbaban * 111276b27f93Sbaban * Those of the form S-1-5-32-X are Builtin groups and are stored in the 111376b27f93Sbaban * cn=builtin container (except, Power Users which is not stored in AD) 111462c60062Sbaban * 111576b27f93Sbaban * These principals are and will remain constant. Therefore doing AD lookups 111676b27f93Sbaban * provides no benefit. Also, using hard-coded table (and thus avoiding AD 111776b27f93Sbaban * lookup) improves performance and avoids additional complexity in the 111876b27f93Sbaban * adutils.c code. Moreover these SIDs can be used when no Active Directory 111976b27f93Sbaban * is available (such as the CIFS server's "workgroup" mode). 112076b27f93Sbaban * 112176b27f93Sbaban * Notes: 112276b27f93Sbaban * 1. Currently we don't support localization of well-known SID names, 112362c60062Sbaban * unlike Windows. 112462c60062Sbaban * 112576b27f93Sbaban * 2. Other well-known SIDs i.e. S-1-5-<domain>-<w-k RID> are not stored 112676b27f93Sbaban * here. AD does have normal user/group objects for these objects and 112776b27f93Sbaban * can be looked up using the existing AD lookup code. 112862c60062Sbaban */ 112962c60062Sbaban static wksids_table_t wksids[] = { 113062c60062Sbaban {"S-1-1", 0, "Everyone", 0, SENTINEL_PID, -1}, 113162c60062Sbaban {"S-1-3", 0, "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 0}, 113262c60062Sbaban {"S-1-3", 1, "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0}, 113362c60062Sbaban {"S-1-3", 2, "Creator Owner Server", 1, SENTINEL_PID, -1}, 113462c60062Sbaban {"S-1-3", 3, "Creator Group Server", 0, SENTINEL_PID, -1}, 113576b27f93Sbaban {"S-1-3", 4, "Owner Rights", 0, SENTINEL_PID, -1}, 113662c60062Sbaban {"S-1-5", 1, "Dialup", 0, SENTINEL_PID, -1}, 113762c60062Sbaban {"S-1-5", 2, "Network", 0, SENTINEL_PID, -1}, 113862c60062Sbaban {"S-1-5", 3, "Batch", 0, SENTINEL_PID, -1}, 113962c60062Sbaban {"S-1-5", 4, "Interactive", 0, SENTINEL_PID, -1}, 114062c60062Sbaban {"S-1-5", 6, "Service", 0, SENTINEL_PID, -1}, 114162c60062Sbaban {"S-1-5", 7, "Anonymous Logon", 0, GID_NOBODY, 0}, 114262c60062Sbaban {"S-1-5", 8, "Proxy", 0, SENTINEL_PID, -1}, 114362c60062Sbaban {"S-1-5", 9, "Enterprise Domain Controllers", 0, SENTINEL_PID, -1}, 114462c60062Sbaban {"S-1-5", 10, "Self", 0, SENTINEL_PID, -1}, 114562c60062Sbaban {"S-1-5", 11, "Authenticated Users", 0, SENTINEL_PID, -1}, 114662c60062Sbaban {"S-1-5", 12, "Restricted Code", 0, SENTINEL_PID, -1}, 114762c60062Sbaban {"S-1-5", 13, "Terminal Server User", 0, SENTINEL_PID, -1}, 114862c60062Sbaban {"S-1-5", 14, "Remote Interactive Logon", 0, SENTINEL_PID, -1}, 114962c60062Sbaban {"S-1-5", 15, "This Organization", 0, SENTINEL_PID, -1}, 115076b27f93Sbaban {"S-1-5", 17, "IUSR", 0, SENTINEL_PID, -1}, 115162c60062Sbaban {"S-1-5", 18, "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0}, 115262c60062Sbaban {"S-1-5", 19, "Local Service", 0, SENTINEL_PID, -1}, 115362c60062Sbaban {"S-1-5", 20, "Network Service", 0, SENTINEL_PID, -1}, 115462c60062Sbaban {"S-1-5", 1000, "Other Organization", 0, SENTINEL_PID, -1}, 115576b27f93Sbaban {"S-1-5-32", 544, "Administrators", 0, SENTINEL_PID, -1}, 115676b27f93Sbaban {"S-1-5-32", 545, "Users", 0, SENTINEL_PID, -1}, 115776b27f93Sbaban {"S-1-5-32", 546, "Guests", 0, SENTINEL_PID, -1}, 115876b27f93Sbaban {"S-1-5-32", 547, "Power Users", 0, SENTINEL_PID, -1}, 115976b27f93Sbaban {"S-1-5-32", 548, "Account Operators", 0, SENTINEL_PID, -1}, 116076b27f93Sbaban {"S-1-5-32", 549, "Server Operators", 0, SENTINEL_PID, -1}, 116176b27f93Sbaban {"S-1-5-32", 550, "Print Operators", 0, SENTINEL_PID, -1}, 116276b27f93Sbaban {"S-1-5-32", 551, "Backup Operators", 0, SENTINEL_PID, -1}, 116376b27f93Sbaban {"S-1-5-32", 552, "Replicator", 0, SENTINEL_PID, -1}, 116476b27f93Sbaban {"S-1-5-32", 554, "Pre-Windows 2000 Compatible Access", 0, 116576b27f93Sbaban SENTINEL_PID, -1}, 116676b27f93Sbaban {"S-1-5-32", 555, "Remote Desktop Users", 0, SENTINEL_PID, -1}, 116776b27f93Sbaban {"S-1-5-32", 556, "Network Configuration Operators", 0, 116876b27f93Sbaban SENTINEL_PID, -1}, 116976b27f93Sbaban {"S-1-5-32", 557, "Incoming Forest Trust Builders", 0, 117076b27f93Sbaban SENTINEL_PID, -1}, 117176b27f93Sbaban {"S-1-5-32", 558, "Performance Monitor Users", 0, SENTINEL_PID, -1}, 117276b27f93Sbaban {"S-1-5-32", 559, "Performance Log Users", 0, SENTINEL_PID, -1}, 117376b27f93Sbaban {"S-1-5-32", 560, "Windows Authorization Access Group", 0, 117476b27f93Sbaban SENTINEL_PID, -1}, 117576b27f93Sbaban {"S-1-5-32", 561, "Terminal Server License Servers", 0, 117676b27f93Sbaban SENTINEL_PID, -1}, 117776b27f93Sbaban {"S-1-5-32", 561, "Distributed COM Users", 0, SENTINEL_PID, -1}, 117876b27f93Sbaban {"S-1-5-32", 568, "IIS_IUSRS", 0, SENTINEL_PID, -1}, 117976b27f93Sbaban {"S-1-5-32", 569, "Cryptograhic Operators", 0, SENTINEL_PID, -1}, 118076b27f93Sbaban {"S-1-5-32", 573, "Event Log Readers", 0, SENTINEL_PID, -1}, 118176b27f93Sbaban {"S-1-5-32", 574, "Certificate Service DCOM Access", 0, 118276b27f93Sbaban SENTINEL_PID, -1}, 118362c60062Sbaban {"S-1-5-64", 21, "Digest Authentication", 0, SENTINEL_PID, -1}, 118462c60062Sbaban {"S-1-5-64", 10, "NTLM Authentication", 0, SENTINEL_PID, -1}, 118562c60062Sbaban {"S-1-5-64", 14, "SChannel Authentication", 0, SENTINEL_PID, -1}, 118662c60062Sbaban {NULL, UINT32_MAX, NULL, -1, SENTINEL_PID, -1} 1187c5c4113dSnw141292 }; 1188c5c4113dSnw141292 1189*cd37da74Snw141292 static 1190*cd37da74Snw141292 idmap_retcode 1191*cd37da74Snw141292 lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res) 1192*cd37da74Snw141292 { 1193c5c4113dSnw141292 int i; 119462c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 119562c60062Sbaban if (wksids[i].rid == req->id1.idmap_id_u.sid.rid && 119662c60062Sbaban (strcasecmp(wksids[i].sidprefix, 119762c60062Sbaban req->id1.idmap_id_u.sid.prefix) == 0)) { 119862c60062Sbaban 119962c60062Sbaban if (wksids[i].pid == SENTINEL_PID) 120062c60062Sbaban /* Not mapped, break */ 120162c60062Sbaban break; 120262c60062Sbaban else if (wksids[i].direction == IDMAP_DIRECTION_U2W) 120362c60062Sbaban continue; 120462c60062Sbaban 1205c5c4113dSnw141292 switch (req->id2.idtype) { 1206c5c4113dSnw141292 case IDMAP_UID: 120762c60062Sbaban if (wksids[i].is_user == 0) 120862c60062Sbaban continue; 120962c60062Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 121062c60062Sbaban res->direction = wksids[i].direction; 1211c5c4113dSnw141292 return (IDMAP_SUCCESS); 1212c5c4113dSnw141292 case IDMAP_GID: 121362c60062Sbaban if (wksids[i].is_user == 1) 121462c60062Sbaban continue; 121562c60062Sbaban res->id.idmap_id_u.gid = wksids[i].pid; 121662c60062Sbaban res->direction = wksids[i].direction; 1217c5c4113dSnw141292 return (IDMAP_SUCCESS); 1218c5c4113dSnw141292 case IDMAP_POSIXID: 121962c60062Sbaban res->id.idmap_id_u.uid = wksids[i].pid; 122062c60062Sbaban res->id.idtype = (!wksids[i].is_user) ? 1221c5c4113dSnw141292 IDMAP_GID : IDMAP_UID; 122262c60062Sbaban res->direction = wksids[i].direction; 1223c5c4113dSnw141292 return (IDMAP_SUCCESS); 1224c5c4113dSnw141292 default: 1225c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1226c5c4113dSnw141292 } 1227c5c4113dSnw141292 } 1228c5c4113dSnw141292 } 1229c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1230c5c4113dSnw141292 } 1231c5c4113dSnw141292 1232*cd37da74Snw141292 1233*cd37da74Snw141292 static 1234*cd37da74Snw141292 idmap_retcode 1235*cd37da74Snw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) 1236*cd37da74Snw141292 { 1237c5c4113dSnw141292 int i; 1238*cd37da74Snw141292 if (!IS_REQUEST_SID(*req, 2)) 123962c60062Sbaban return (IDMAP_ERR_NOTSUPPORTED); 124062c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 124162c60062Sbaban if (wksids[i].pid == req->id1.idmap_id_u.uid && 124262c60062Sbaban wksids[i].is_user == is_user && 124362c60062Sbaban wksids[i].direction != IDMAP_DIRECTION_W2U) { 124462c60062Sbaban res->id.idmap_id_u.sid.rid = wksids[i].rid; 1245c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = 124662c60062Sbaban strdup(wksids[i].sidprefix); 1247c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 1248c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1249c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 1250c5c4113dSnw141292 } 125162c60062Sbaban res->direction = wksids[i].direction; 1252c5c4113dSnw141292 return (IDMAP_SUCCESS); 1253c5c4113dSnw141292 } 1254c5c4113dSnw141292 } 125562c60062Sbaban return (IDMAP_ERR_NOTFOUND); 125662c60062Sbaban } 125762c60062Sbaban 1258*cd37da74Snw141292 static 1259*cd37da74Snw141292 idmap_retcode 126062c60062Sbaban lookup_wksids_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 1261*cd37da74Snw141292 int *type) 1262*cd37da74Snw141292 { 126362c60062Sbaban int i; 126462c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 126562c60062Sbaban if ((strcasecmp(wksids[i].sidprefix, sidprefix) == 0) && 126662c60062Sbaban wksids[i].rid == rid) { 126762c60062Sbaban if ((*name = strdup(wksids[i].winname)) == NULL) { 126862c60062Sbaban idmapdlog(LOG_ERR, "Out of memory"); 126962c60062Sbaban return (IDMAP_ERR_MEMORY); 127062c60062Sbaban } 127162c60062Sbaban *type = (wksids[i].is_user)? 127262c60062Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 127362c60062Sbaban return (IDMAP_SUCCESS); 127462c60062Sbaban } 127562c60062Sbaban } 127662c60062Sbaban return (IDMAP_ERR_NOTFOUND); 127762c60062Sbaban } 127862c60062Sbaban 1279*cd37da74Snw141292 static 1280*cd37da74Snw141292 idmap_retcode 1281*cd37da74Snw141292 lookup_wksids_name2sid(const char *name, char **canonname, char **sidprefix, 1282*cd37da74Snw141292 idmap_rid_t *rid, int *type) 1283*cd37da74Snw141292 { 128462c60062Sbaban int i; 1285*cd37da74Snw141292 128662c60062Sbaban for (i = 0; wksids[i].sidprefix != NULL; i++) { 128762c60062Sbaban if (strcasecmp(wksids[i].winname, name) == 0) { 128862c60062Sbaban if (sidprefix != NULL && (*sidprefix = 128962c60062Sbaban strdup(wksids[i].sidprefix)) == NULL) { 129062c60062Sbaban idmapdlog(LOG_ERR, "Out of memory"); 129162c60062Sbaban return (IDMAP_ERR_MEMORY); 129262c60062Sbaban } 1293*cd37da74Snw141292 if (canonname != NULL && 1294*cd37da74Snw141292 (*canonname = strdup(wksids[i].winname)) == NULL) { 1295*cd37da74Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 1296*cd37da74Snw141292 return (IDMAP_ERR_MEMORY); 1297*cd37da74Snw141292 } 129862c60062Sbaban if (type != NULL) 129962c60062Sbaban *type = (wksids[i].is_user)? 130062c60062Sbaban _IDMAP_T_USER:_IDMAP_T_GROUP; 130162c60062Sbaban if (rid != NULL) 130262c60062Sbaban *rid = wksids[i].rid; 130362c60062Sbaban return (IDMAP_SUCCESS); 130462c60062Sbaban } 1305c5c4113dSnw141292 } 1306c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1307c5c4113dSnw141292 } 1308c5c4113dSnw141292 1309*cd37da74Snw141292 static 1310*cd37da74Snw141292 idmap_retcode 1311*cd37da74Snw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) 1312*cd37da74Snw141292 { 1313c5c4113dSnw141292 char *end; 1314c5c4113dSnw141292 char *sql = NULL; 1315c5c4113dSnw141292 const char **values; 1316c5c4113dSnw141292 sqlite_vm *vm = NULL; 1317c5c4113dSnw141292 int ncol, is_user; 1318c5c4113dSnw141292 uid_t pid; 1319c5c4113dSnw141292 time_t curtime, exp; 1320c5c4113dSnw141292 idmap_retcode retcode; 1321*cd37da74Snw141292 char *is_user_string; 1322c5c4113dSnw141292 1323c5c4113dSnw141292 /* Current time */ 1324c5c4113dSnw141292 errno = 0; 1325c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 1326*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 1327c5c4113dSnw141292 strerror(errno)); 1328c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1329c5c4113dSnw141292 goto out; 1330c5c4113dSnw141292 } 1331c5c4113dSnw141292 1332*cd37da74Snw141292 switch (req->id2.idtype) { 1333*cd37da74Snw141292 case IDMAP_UID: 1334*cd37da74Snw141292 is_user_string = "1"; 1335*cd37da74Snw141292 break; 1336*cd37da74Snw141292 case IDMAP_GID: 1337*cd37da74Snw141292 is_user_string = "0"; 1338*cd37da74Snw141292 break; 1339*cd37da74Snw141292 case IDMAP_POSIXID: 1340*cd37da74Snw141292 /* the non-diagonal mapping */ 1341*cd37da74Snw141292 is_user_string = "is_wuser"; 1342*cd37da74Snw141292 break; 1343*cd37da74Snw141292 default: 1344*cd37da74Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 1345*cd37da74Snw141292 goto out; 1346*cd37da74Snw141292 } 1347*cd37da74Snw141292 1348c5c4113dSnw141292 /* SQL to lookup the cache */ 1349c5c4113dSnw141292 sql = sqlite_mprintf("SELECT pid, is_user, expiration, unixname, u2w " 1350*cd37da74Snw141292 "FROM idmap_cache WHERE is_user = %s AND " 1351c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 1352c5c4113dSnw141292 "(pid >= 2147483648 OR " 1353c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 1354c5c4113dSnw141292 "expiration > %d));", 1355*cd37da74Snw141292 is_user_string, 1356c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 1357c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 1358c5c4113dSnw141292 curtime); 1359c5c4113dSnw141292 if (sql == NULL) { 1360c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1361c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1362c5c4113dSnw141292 goto out; 1363c5c4113dSnw141292 } 1364c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 1365c5c4113dSnw141292 sqlite_freemem(sql); 1366c5c4113dSnw141292 1367c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 1368c5c4113dSnw141292 goto out; 1369c5c4113dSnw141292 } else if (retcode == IDMAP_SUCCESS) { 1370c5c4113dSnw141292 /* sanity checks */ 1371c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 1372c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 1373c5c4113dSnw141292 goto out; 1374c5c4113dSnw141292 } 1375c5c4113dSnw141292 1376c5c4113dSnw141292 pid = strtoul(values[0], &end, 10); 1377c5c4113dSnw141292 is_user = strncmp(values[1], "0", 2)?1:0; 1378c5c4113dSnw141292 1379*cd37da74Snw141292 if (is_user) { 1380*cd37da74Snw141292 res->id.idtype = IDMAP_UID; 1381*cd37da74Snw141292 res->id.idmap_id_u.uid = pid; 1382*cd37da74Snw141292 } else { 1383*cd37da74Snw141292 res->id.idtype = IDMAP_GID; 1384*cd37da74Snw141292 res->id.idmap_id_u.gid = pid; 1385*cd37da74Snw141292 } 1386*cd37da74Snw141292 1387c5c4113dSnw141292 /* 1388c5c4113dSnw141292 * We may have an expired ephemeral mapping. Consider 1389c5c4113dSnw141292 * the expired entry as valid if we are not going to 1390c5c4113dSnw141292 * perform name-based mapping. But do not renew the 1391c5c4113dSnw141292 * expiration. 1392c5c4113dSnw141292 * If we will be doing name-based mapping then store the 1393c5c4113dSnw141292 * ephemeral pid in the result so that we can use it 1394c5c4113dSnw141292 * if we end up doing dynamic mapping again. 1395c5c4113dSnw141292 */ 1396c5c4113dSnw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 1397*cd37da74Snw141292 !AVOID_NAMESERVICE(req) && 1398*cd37da74Snw141292 IS_EPHEMERAL(pid) && values[2] != NULL) { 1399c5c4113dSnw141292 exp = strtoll(values[2], &end, 10); 1400c5c4113dSnw141292 if (exp && exp <= curtime) { 1401c5c4113dSnw141292 /* Store the ephemeral pid */ 1402651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 1403*cd37da74Snw141292 req->direction |= is_user 1404*cd37da74Snw141292 ? _IDMAP_F_EXP_EPH_UID 1405*cd37da74Snw141292 : _IDMAP_F_EXP_EPH_GID; 1406c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 1407c5c4113dSnw141292 } 1408c5c4113dSnw141292 } 1409c5c4113dSnw141292 } 1410c5c4113dSnw141292 1411c5c4113dSnw141292 out: 1412c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 141362c60062Sbaban if (values[4] != NULL) 1414c5c4113dSnw141292 res->direction = 1415651c0131Sbaban (strtol(values[4], &end, 10) == 0)? 1416651c0131Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 1417c5c4113dSnw141292 else 1418651c0131Sbaban res->direction = IDMAP_DIRECTION_W2U; 1419c5c4113dSnw141292 142062c60062Sbaban if (values[3] != NULL) { 14218e228215Sdm199847 req->id2name = strdup(values[3]); 14228e228215Sdm199847 if (req->id2name == NULL) { 1423c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1424c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1425c5c4113dSnw141292 } 1426c5c4113dSnw141292 } 1427c5c4113dSnw141292 } 142862c60062Sbaban if (vm != NULL) 1429c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1430c5c4113dSnw141292 return (retcode); 1431c5c4113dSnw141292 } 1432c5c4113dSnw141292 1433*cd37da74Snw141292 static 1434*cd37da74Snw141292 idmap_retcode 143562c60062Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 1436*cd37da74Snw141292 char **name, char **domain, int *type) 1437*cd37da74Snw141292 { 1438c5c4113dSnw141292 char *end; 1439c5c4113dSnw141292 char *sql = NULL; 1440c5c4113dSnw141292 const char **values; 1441c5c4113dSnw141292 sqlite_vm *vm = NULL; 1442c5c4113dSnw141292 int ncol; 1443c5c4113dSnw141292 time_t curtime; 1444c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 1445c5c4113dSnw141292 1446c5c4113dSnw141292 /* Get current time */ 1447c5c4113dSnw141292 errno = 0; 1448c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 1449*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 1450c5c4113dSnw141292 strerror(errno)); 1451c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 1452c5c4113dSnw141292 goto out; 1453c5c4113dSnw141292 } 1454c5c4113dSnw141292 1455c5c4113dSnw141292 /* SQL to lookup the cache */ 1456*cd37da74Snw141292 sql = sqlite_mprintf("SELECT canon_name, domain, type " 1457*cd37da74Snw141292 "FROM name_cache WHERE " 1458c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND " 1459c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 1460c5c4113dSnw141292 "expiration > %d);", 1461c5c4113dSnw141292 sidprefix, rid, curtime); 1462c5c4113dSnw141292 if (sql == NULL) { 1463c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1464c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1465c5c4113dSnw141292 goto out; 1466c5c4113dSnw141292 } 1467c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 1468c5c4113dSnw141292 sqlite_freemem(sql); 1469c5c4113dSnw141292 1470c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 147162c60062Sbaban if (type != NULL) { 1472c5c4113dSnw141292 if (values[2] == NULL) { 1473c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 1474c5c4113dSnw141292 goto out; 1475c5c4113dSnw141292 } 1476c5c4113dSnw141292 *type = strtol(values[2], &end, 10); 1477c5c4113dSnw141292 } 1478c5c4113dSnw141292 147962c60062Sbaban if (name != NULL && values[0] != NULL) { 1480c5c4113dSnw141292 if ((*name = strdup(values[0])) == NULL) { 1481c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1482c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1483c5c4113dSnw141292 goto out; 1484c5c4113dSnw141292 } 1485c5c4113dSnw141292 } 1486c5c4113dSnw141292 148762c60062Sbaban if (domain != NULL && values[1] != NULL) { 1488c5c4113dSnw141292 if ((*domain = strdup(values[1])) == NULL) { 148962c60062Sbaban if (name != NULL && *name) { 1490c5c4113dSnw141292 free(*name); 1491c5c4113dSnw141292 *name = NULL; 1492c5c4113dSnw141292 } 1493c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1494c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 1495c5c4113dSnw141292 goto out; 1496c5c4113dSnw141292 } 1497c5c4113dSnw141292 } 1498c5c4113dSnw141292 } 1499c5c4113dSnw141292 1500c5c4113dSnw141292 out: 150162c60062Sbaban if (vm != NULL) 1502c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 1503c5c4113dSnw141292 return (retcode); 1504c5c4113dSnw141292 } 1505c5c4113dSnw141292 1506c5c4113dSnw141292 /* 150762c60062Sbaban * Lookup sid to name locally 1508c5c4113dSnw141292 */ 1509*cd37da74Snw141292 static 1510*cd37da74Snw141292 idmap_retcode 1511*cd37da74Snw141292 lookup_local_sid2name(sqlite *cache, idmap_mapping *req) 1512*cd37da74Snw141292 { 1513c5c4113dSnw141292 int type = -1; 1514c5c4113dSnw141292 idmap_retcode retcode; 1515c5c4113dSnw141292 char *sidprefix; 1516c5c4113dSnw141292 idmap_rid_t rid; 1517c5c4113dSnw141292 char *name = NULL, *domain = NULL; 1518c5c4113dSnw141292 1519c5c4113dSnw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 1520c5c4113dSnw141292 rid = req->id1.idmap_id_u.sid.rid; 1521c5c4113dSnw141292 152262c60062Sbaban /* Lookup sids to name in well-known sids table */ 152362c60062Sbaban retcode = lookup_wksids_sid2name(sidprefix, rid, &name, &type); 152462c60062Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 152562c60062Sbaban goto out; 152662c60062Sbaban 1527c5c4113dSnw141292 /* Lookup sid to name in cache */ 152862c60062Sbaban retcode = lookup_cache_sid2name(cache, sidprefix, rid, &name, 1529c5c4113dSnw141292 &domain, &type); 1530c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 1531c5c4113dSnw141292 goto out; 1532c5c4113dSnw141292 153362c60062Sbaban out: 153462c60062Sbaban if (retcode == IDMAP_SUCCESS) { 1535*cd37da74Snw141292 req->id1.idtype = type == _IDMAP_T_USER 1536*cd37da74Snw141292 ? IDMAP_USID : IDMAP_GSID; 1537c5c4113dSnw141292 1538c5c4113dSnw141292 /* update state in 'req' */ 15398e228215Sdm199847 if (name != NULL) 15408e228215Sdm199847 req->id1name = name; 15418e228215Sdm199847 if (domain != NULL) 15428e228215Sdm199847 req->id1domain = domain; 1543c5c4113dSnw141292 } else { 154462c60062Sbaban if (name != NULL) 1545c5c4113dSnw141292 free(name); 154662c60062Sbaban if (domain != NULL) 1547c5c4113dSnw141292 free(domain); 1548c5c4113dSnw141292 } 1549c5c4113dSnw141292 return (retcode); 1550c5c4113dSnw141292 } 1551c5c4113dSnw141292 1552c5c4113dSnw141292 idmap_retcode 1553c5c4113dSnw141292 lookup_win_batch_sid2name(lookup_state_t *state, idmap_mapping_batch *batch, 1554*cd37da74Snw141292 idmap_ids_res *result) 1555*cd37da74Snw141292 { 1556c5c4113dSnw141292 idmap_retcode retcode; 1557c5c4113dSnw141292 int ret, i; 1558c5c4113dSnw141292 int retries = 0; 1559c5c4113dSnw141292 idmap_mapping *req; 1560c5c4113dSnw141292 idmap_id_res *res; 1561c5c4113dSnw141292 1562c5c4113dSnw141292 if (state->ad_nqueries == 0) 1563c5c4113dSnw141292 return (IDMAP_SUCCESS); 1564c5c4113dSnw141292 1565c5c4113dSnw141292 retry: 1566c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries, 1567c5c4113dSnw141292 &state->ad_lookup); 1568c5c4113dSnw141292 if (ret != 0) { 1569c8e26105Sjp151216 degrade_svc(); 1570c5c4113dSnw141292 idmapdlog(LOG_ERR, 1571c5c4113dSnw141292 "Failed to create sid2name batch for AD lookup"); 1572c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1573c5c4113dSnw141292 } 1574c5c4113dSnw141292 1575c8e26105Sjp151216 restore_svc(); 1576c8e26105Sjp151216 1577c5c4113dSnw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 1578c5c4113dSnw141292 req = &batch->idmap_mapping_batch_val[i]; 1579c5c4113dSnw141292 res = &result->ids.ids_val[i]; 1580c5c4113dSnw141292 1581*cd37da74Snw141292 if (IS_REQUEST_SID(*req, 1) && 158262c60062Sbaban req->direction & _IDMAP_F_S2N_AD) { 1583c5c4113dSnw141292 if (retries == 0) 1584c5c4113dSnw141292 res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 1585c5c4113dSnw141292 else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 1586c5c4113dSnw141292 continue; 1587c5c4113dSnw141292 retcode = idmap_sid2name_batch_add1( 1588*cd37da74Snw141292 state->ad_lookup, req->id1.idmap_id_u.sid.prefix, 1589*cd37da74Snw141292 &req->id1.idmap_id_u.sid.rid, &req->id1name, 1590*cd37da74Snw141292 &req->id1domain, (int *)&res->id.idtype, 1591c5c4113dSnw141292 &res->retcode); 1592c5c4113dSnw141292 1593c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1594c5c4113dSnw141292 break; 1595c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 1596c5c4113dSnw141292 goto out; 1597c5c4113dSnw141292 } 1598c5c4113dSnw141292 } 1599c5c4113dSnw141292 1600c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 160184decf41Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 1602c5c4113dSnw141292 else 1603c5c4113dSnw141292 retcode = idmap_lookup_batch_end(&state->ad_lookup, NULL); 1604c5c4113dSnw141292 1605*cd37da74Snw141292 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 1606*cd37da74Snw141292 req = &batch->idmap_mapping_batch_val[i]; 1607*cd37da74Snw141292 res = &result->ids.ids_val[i]; 1608*cd37da74Snw141292 if (res->retcode != IDMAP_SUCCESS) 1609*cd37da74Snw141292 continue; 1610*cd37da74Snw141292 1611*cd37da74Snw141292 if (!(IS_REQUEST_SID(*req, 1))) 1612*cd37da74Snw141292 continue; 1613*cd37da74Snw141292 if (!(req->direction & _IDMAP_F_S2N_AD)) 1614*cd37da74Snw141292 continue; 1615*cd37da74Snw141292 /* 1616*cd37da74Snw141292 * Map from type values known to adutils to type values 1617*cd37da74Snw141292 * understood everywhere else in idmapd/libidmap/idmap. 1618*cd37da74Snw141292 */ 1619*cd37da74Snw141292 if (res->id.idtype == _IDMAP_T_USER) { 1620*cd37da74Snw141292 req->id1.idtype = IDMAP_USID; 1621*cd37da74Snw141292 res->id.idtype = IDMAP_UID; 1622*cd37da74Snw141292 } else if (res->id.idtype == _IDMAP_T_GROUP) { 1623*cd37da74Snw141292 req->id1.idtype = IDMAP_GSID; 1624*cd37da74Snw141292 res->id.idtype = IDMAP_GID; 1625*cd37da74Snw141292 } else { 1626*cd37da74Snw141292 res->retcode = IDMAP_ERR_SID; 1627*cd37da74Snw141292 } 1628*cd37da74Snw141292 1629*cd37da74Snw141292 if (res->retcode == IDMAP_SUCCESS && 1630*cd37da74Snw141292 req->id2.idtype == IDMAP_POSIXID) 1631*cd37da74Snw141292 req->id2.idtype = res->id.idtype; 1632*cd37da74Snw141292 } 1633*cd37da74Snw141292 1634c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 1635c5c4113dSnw141292 goto retry; 1636c8e26105Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 1637c8e26105Sjp151216 degrade_svc(); 1638c5c4113dSnw141292 1639c5c4113dSnw141292 return (retcode); 1640c5c4113dSnw141292 1641c5c4113dSnw141292 out: 1642c5c4113dSnw141292 idmapdlog(LOG_NOTICE, "Windows SID to user/group name lookup failed"); 164384decf41Sjp151216 idmap_lookup_release_batch(&state->ad_lookup); 1644c5c4113dSnw141292 return (retcode); 1645c5c4113dSnw141292 } 1646c5c4113dSnw141292 1647*cd37da74Snw141292 /* 1648*cd37da74Snw141292 * Convention when processing win2unix requests: 1649*cd37da74Snw141292 * 1650*cd37da74Snw141292 * Windows identity: 1651*cd37da74Snw141292 * req->id1name = 1652*cd37da74Snw141292 * winname if given otherwise winname found will be placed 1653*cd37da74Snw141292 * here. 1654*cd37da74Snw141292 * req->id1domain = 1655*cd37da74Snw141292 * windomain if given otherwise windomain found will be 1656*cd37da74Snw141292 * placed here. 1657*cd37da74Snw141292 * req->id1.idtype = 1658*cd37da74Snw141292 * Either IDMAP_SID/USID/GSID. If this is IDMAP_SID then it'll 1659*cd37da74Snw141292 * be set to IDMAP_USID/GSID depending upon whether the 1660*cd37da74Snw141292 * given SID is user or group respectively. The user/group-ness 1661*cd37da74Snw141292 * is determined either when looking up well-known SIDs table OR 1662*cd37da74Snw141292 * if the SID is found in namecache OR by ad_lookup() OR by 1663*cd37da74Snw141292 * ad_lookup_batch(). 1664*cd37da74Snw141292 * req->id1..sid.[prefix, rid] = 1665*cd37da74Snw141292 * SID if given otherwise SID found will be placed here. 1666*cd37da74Snw141292 * 1667*cd37da74Snw141292 * Unix identity: 1668*cd37da74Snw141292 * req->id2name = 1669*cd37da74Snw141292 * unixname found will be placed here. 1670*cd37da74Snw141292 * req->id2domain = 1671*cd37da74Snw141292 * NOT USED 1672*cd37da74Snw141292 * res->id.idtype = 1673*cd37da74Snw141292 * Target type initialized from req->id2.idtype. If 1674*cd37da74Snw141292 * it is IDMAP_POSIXID then actual type (IDMAP_UID/GID) found 1675*cd37da74Snw141292 * will be placed here. 1676*cd37da74Snw141292 * res->id..[uid or gid] = 1677*cd37da74Snw141292 * UID/GID found will be placed here. 1678*cd37da74Snw141292 * 1679*cd37da74Snw141292 * Others: 1680*cd37da74Snw141292 * res->retcode = 1681*cd37da74Snw141292 * Return status for this request will be placed here. 1682*cd37da74Snw141292 * res->direction = 1683*cd37da74Snw141292 * Direction found will be placed here. Direction 1684*cd37da74Snw141292 * meaning whether the resultant mapping is valid 1685*cd37da74Snw141292 * only from win2unix or bi-directional. 1686*cd37da74Snw141292 * req->direction = 1687*cd37da74Snw141292 * INTERNAL USE. Used by idmapd to set various 1688*cd37da74Snw141292 * flags (_IDMAP_F_xxxx) to aid in processing 1689*cd37da74Snw141292 * of the request. 1690*cd37da74Snw141292 * req->id2.idtype = 1691*cd37da74Snw141292 * INTERNAL USE. Initially this is the requested target 1692*cd37da74Snw141292 * type and is used to initialize res->id.idtype. 1693*cd37da74Snw141292 * ad_lookup_batch() uses this field temporarily to store 1694*cd37da74Snw141292 * sid_type obtained by the batched AD lookups and after 1695*cd37da74Snw141292 * use resets it to IDMAP_NONE to prevent xdr from 1696*cd37da74Snw141292 * mis-interpreting the contents of req->id2. 1697*cd37da74Snw141292 * req->id2..[uid or gid or sid] = 1698*cd37da74Snw141292 * NOT USED 1699*cd37da74Snw141292 */ 1700*cd37da74Snw141292 1701*cd37da74Snw141292 /* 1702*cd37da74Snw141292 * This function does the following: 1703*cd37da74Snw141292 * 1. Lookup well-known SIDs table. 1704*cd37da74Snw141292 * 2. Check if the given SID is a local-SID and if so extract UID/GID from it. 1705*cd37da74Snw141292 * 3. Lookup cache. 1706*cd37da74Snw141292 * 4. Check if the client does not want new mapping to be allocated 1707*cd37da74Snw141292 * in which case this pass is the final pass. 1708*cd37da74Snw141292 * 5. Set AD lookup flag if it determines that the next stage needs 1709*cd37da74Snw141292 * to do AD lookup. 1710*cd37da74Snw141292 */ 1711c5c4113dSnw141292 idmap_retcode 1712c5c4113dSnw141292 sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, 1713*cd37da74Snw141292 idmap_id_res *res) 1714*cd37da74Snw141292 { 1715c5c4113dSnw141292 idmap_retcode retcode; 1716c5c4113dSnw141292 1717c5c4113dSnw141292 /* 1718c5c4113dSnw141292 * The req->direction field is used to maintain state of the 1719c5c4113dSnw141292 * sid2pid request. 1720c5c4113dSnw141292 */ 1721c5c4113dSnw141292 req->direction = _IDMAP_F_DONE; 1722c5c4113dSnw141292 1723cf5b5989Sdm199847 if (EMPTY_STRING(req->id1.idmap_id_u.sid.prefix)) { 1724c5c4113dSnw141292 retcode = IDMAP_ERR_SID; 1725c5c4113dSnw141292 goto out; 1726c5c4113dSnw141292 } 1727c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 1728c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 1729c5c4113dSnw141292 173062c60062Sbaban /* Lookup well-known sid to pid mapping */ 1731c5c4113dSnw141292 retcode = lookup_wksids_sid2pid(req, res); 1732c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 1733c5c4113dSnw141292 goto out; 1734c5c4113dSnw141292 1735c5c4113dSnw141292 /* Lookup sid to pid in cache */ 1736c5c4113dSnw141292 retcode = lookup_cache_sid2pid(cache, req, res); 1737c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 1738c5c4113dSnw141292 goto out; 1739c5c4113dSnw141292 1740c5c4113dSnw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 1741c5c4113dSnw141292 res->id.idmap_id_u.uid = SENTINEL_PID; 1742c5c4113dSnw141292 goto out; 1743c5c4113dSnw141292 } 1744c5c4113dSnw141292 1745c5c4113dSnw141292 /* 1746c5c4113dSnw141292 * Failed to find non-expired entry in cache. Tell the caller 1747c5c4113dSnw141292 * that we are not done yet. 1748c5c4113dSnw141292 */ 1749c5c4113dSnw141292 state->sid2pid_done = FALSE; 1750c5c4113dSnw141292 1751c5c4113dSnw141292 /* 1752c5c4113dSnw141292 * Our next step is name-based mapping. To lookup name-based 1753c5c4113dSnw141292 * mapping rules, we need the windows name and domain-name 1754c5c4113dSnw141292 * associated with the SID. 1755c5c4113dSnw141292 */ 1756c5c4113dSnw141292 1757c5c4113dSnw141292 /* 1758c5c4113dSnw141292 * Check if we already have the name (i.e name2pid lookups) 1759c5c4113dSnw141292 */ 1760cf5b5989Sdm199847 if (!EMPTY_STRING(req->id1name) && 1761cf5b5989Sdm199847 !EMPTY_STRING(req->id1domain)) { 1762c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 1763c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_CACHE; 1764c5c4113dSnw141292 goto out; 1765c5c4113dSnw141292 } 1766c5c4113dSnw141292 176762c60062Sbaban /* Lookup sid to winname@domain locally first */ 1768*cd37da74Snw141292 retcode = lookup_local_sid2name(cache, req); 176962c60062Sbaban if (retcode == IDMAP_SUCCESS) { 177062c60062Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 177162c60062Sbaban } else if (retcode == IDMAP_ERR_NOTFOUND) { 1772c5c4113dSnw141292 /* Batch sid to name AD lookup request */ 1773c5c4113dSnw141292 retcode = IDMAP_SUCCESS; 1774c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_AD; 1775c5c4113dSnw141292 state->ad_nqueries++; 1776c5c4113dSnw141292 goto out; 1777c5c4113dSnw141292 } 1778c5c4113dSnw141292 1779c5c4113dSnw141292 1780c5c4113dSnw141292 out: 1781c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 1782c5c4113dSnw141292 return (retcode); 1783c5c4113dSnw141292 } 1784c5c4113dSnw141292 1785c5c4113dSnw141292 /* 1786c5c4113dSnw141292 * Generate SID using the following convention 1787c5c4113dSnw141292 * <machine-sid-prefix>-<1000 + uid> 1788c5c4113dSnw141292 * <machine-sid-prefix>-<2^31 + gid> 1789c5c4113dSnw141292 */ 1790*cd37da74Snw141292 static 1791*cd37da74Snw141292 idmap_retcode 1792*cd37da74Snw141292 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) 1793*cd37da74Snw141292 { 179462c60062Sbaban if (_idmapdstate.cfg->pgcfg.machine_sid != NULL) { 1795c5c4113dSnw141292 /* Skip 1000 UIDs */ 1796c5c4113dSnw141292 if (is_user && req->id1.idmap_id_u.uid > 1797c5c4113dSnw141292 (INT32_MAX - LOCALRID_MIN)) 179862c60062Sbaban return (IDMAP_ERR_NOMAPPING); 1799c5c4113dSnw141292 1800c5c4113dSnw141292 RDLOCK_CONFIG(); 1801c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = 1802c5c4113dSnw141292 strdup(_idmapdstate.cfg->pgcfg.machine_sid); 1803c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 1804c5c4113dSnw141292 UNLOCK_CONFIG(); 1805c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 1806c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 1807c5c4113dSnw141292 } 1808c5c4113dSnw141292 UNLOCK_CONFIG(); 1809c5c4113dSnw141292 res->id.idmap_id_u.sid.rid = 1810c5c4113dSnw141292 (is_user) ? req->id1.idmap_id_u.uid + LOCALRID_MIN : 1811c5c4113dSnw141292 req->id1.idmap_id_u.gid + INT32_MAX + 1; 1812651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 1813c5c4113dSnw141292 1814c5c4113dSnw141292 /* 1815c5c4113dSnw141292 * Don't update name_cache because local sids don't have 1816c5c4113dSnw141292 * valid windows names. 1817c5c4113dSnw141292 * We mark the entry as being found in the namecache so that 1818c5c4113dSnw141292 * the cache update routine doesn't update namecache. 1819c5c4113dSnw141292 */ 1820c5c4113dSnw141292 req->direction = _IDMAP_F_S2N_CACHE; 1821947c7bc0Sbaban return (IDMAP_SUCCESS); 1822c5c4113dSnw141292 } 1823c5c4113dSnw141292 182462c60062Sbaban return (IDMAP_ERR_NOMAPPING); 1825c5c4113dSnw141292 } 1826c5c4113dSnw141292 1827*cd37da74Snw141292 static 1828*cd37da74Snw141292 idmap_retcode 1829*cd37da74Snw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) 1830*cd37da74Snw141292 { 1831c5c4113dSnw141292 char *sidprefix; 1832c5c4113dSnw141292 uint32_t rid; 1833c5c4113dSnw141292 int s; 1834c5c4113dSnw141292 1835c5c4113dSnw141292 /* 1836c5c4113dSnw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 1837c5c4113dSnw141292 * GID = last RID - 2^31. 1838c5c4113dSnw141292 */ 1839c5c4113dSnw141292 sidprefix = req->id1.idmap_id_u.sid.prefix; 1840c5c4113dSnw141292 rid = req->id1.idmap_id_u.sid.rid; 1841c5c4113dSnw141292 1842c5c4113dSnw141292 RDLOCK_CONFIG(); 1843c5c4113dSnw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid) ? 1844*cd37da74Snw141292 strcasecmp(sidprefix, _idmapdstate.cfg->pgcfg.machine_sid) : 1; 1845c5c4113dSnw141292 UNLOCK_CONFIG(); 1846c5c4113dSnw141292 1847c5c4113dSnw141292 if (s == 0) { 1848c5c4113dSnw141292 switch (req->id2.idtype) { 1849c5c4113dSnw141292 case IDMAP_UID: 1850c5c4113dSnw141292 if (rid > INT32_MAX) { 1851*cd37da74Snw141292 return (IDMAP_ERR_NOTFOUND); 1852c5c4113dSnw141292 } else if (rid < LOCALRID_MIN) { 1853c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1854c5c4113dSnw141292 } 1855c5c4113dSnw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1856c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1857c5c4113dSnw141292 break; 1858c5c4113dSnw141292 case IDMAP_GID: 1859c5c4113dSnw141292 if (rid <= INT32_MAX) { 1860*cd37da74Snw141292 return (IDMAP_ERR_NOTFOUND); 1861c5c4113dSnw141292 } 1862c5c4113dSnw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 1863c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1864c5c4113dSnw141292 break; 1865c5c4113dSnw141292 case IDMAP_POSIXID: 1866c5c4113dSnw141292 if (rid > INT32_MAX) { 1867*cd37da74Snw141292 res->id.idmap_id_u.gid = rid - INT32_MAX - 1; 1868c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1869c5c4113dSnw141292 } else if (rid < LOCALRID_MIN) { 1870c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1871c5c4113dSnw141292 } else { 1872c5c4113dSnw141292 res->id.idmap_id_u.uid = rid - LOCALRID_MIN; 1873c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1874c5c4113dSnw141292 } 1875c5c4113dSnw141292 break; 1876c5c4113dSnw141292 default: 1877c5c4113dSnw141292 return (IDMAP_ERR_NOTSUPPORTED); 1878c5c4113dSnw141292 } 1879c5c4113dSnw141292 return (IDMAP_SUCCESS); 1880c5c4113dSnw141292 } 1881c5c4113dSnw141292 1882c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1883c5c4113dSnw141292 } 1884c5c4113dSnw141292 1885*cd37da74Snw141292 static 1886*cd37da74Snw141292 idmap_retcode 1887*cd37da74Snw141292 ns_lookup_byname(int is_user, const char *name, const char *lower_name, 1888*cd37da74Snw141292 idmap_id_res *res) 1889*cd37da74Snw141292 { 1890*cd37da74Snw141292 struct passwd pwd, *pwdp; 1891*cd37da74Snw141292 struct group grp, *grpp; 1892c5c4113dSnw141292 char buf[1024]; 1893c5c4113dSnw141292 int errnum; 1894c5c4113dSnw141292 const char *me = "ns_lookup_byname"; 1895c5c4113dSnw141292 1896c5c4113dSnw141292 if (is_user) { 1897*cd37da74Snw141292 pwdp = getpwnam_r(name, &pwd, buf, sizeof (buf)); 1898*cd37da74Snw141292 if (pwdp == NULL && lower_name != NULL && 1899*cd37da74Snw141292 name != lower_name && strcmp(name, lower_name) != 0) 1900*cd37da74Snw141292 pwdp = getpwnam_r(lower_name, &pwd, buf, sizeof (buf)); 1901*cd37da74Snw141292 1902*cd37da74Snw141292 if (pwdp == NULL) { 1903c5c4113dSnw141292 errnum = errno; 1904c5c4113dSnw141292 idmapdlog(LOG_WARNING, 1905c5c4113dSnw141292 "%s: getpwnam_r(%s) failed (%s).", 1906*cd37da74Snw141292 me, name, errnum ? strerror(errnum) : "not found"); 1907c5c4113dSnw141292 if (errnum == 0) 1908c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1909c5c4113dSnw141292 else 1910c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1911c5c4113dSnw141292 } 1912c5c4113dSnw141292 res->id.idmap_id_u.uid = pwd.pw_uid; 1913c5c4113dSnw141292 res->id.idtype = IDMAP_UID; 1914c5c4113dSnw141292 } else { 1915*cd37da74Snw141292 grpp = getgrnam_r(name, &grp, buf, sizeof (buf)); 1916*cd37da74Snw141292 if (grpp == NULL && lower_name != NULL && 1917*cd37da74Snw141292 name != lower_name && strcmp(name, lower_name) != 0) 1918*cd37da74Snw141292 grpp = getgrnam_r(lower_name, &grp, buf, sizeof (buf)); 1919*cd37da74Snw141292 if (grpp == NULL) { 1920c5c4113dSnw141292 errnum = errno; 1921c5c4113dSnw141292 idmapdlog(LOG_WARNING, 1922c5c4113dSnw141292 "%s: getgrnam_r(%s) failed (%s).", 1923*cd37da74Snw141292 me, name, errnum ? strerror(errnum) : "not found"); 1924c5c4113dSnw141292 if (errnum == 0) 1925c5c4113dSnw141292 return (IDMAP_ERR_NOTFOUND); 1926c5c4113dSnw141292 else 1927c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 1928c5c4113dSnw141292 } 1929c5c4113dSnw141292 res->id.idmap_id_u.gid = grp.gr_gid; 1930c5c4113dSnw141292 res->id.idtype = IDMAP_GID; 1931c5c4113dSnw141292 } 1932c5c4113dSnw141292 return (IDMAP_SUCCESS); 1933c5c4113dSnw141292 } 1934c5c4113dSnw141292 1935c5c4113dSnw141292 /* 1936c5c4113dSnw141292 * Name-based mapping 1937c5c4113dSnw141292 * 1938c5c4113dSnw141292 * Case 1: If no rule matches do ephemeral 1939c5c4113dSnw141292 * 1940c5c4113dSnw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 1941c5c4113dSnw141292 * 1942c5c4113dSnw141292 * Case 3: If rule matches and unixname is specified then lookup name 1943c5c4113dSnw141292 * service using the unixname. If unixname not found then return no mapping. 1944c5c4113dSnw141292 * 1945c5c4113dSnw141292 * Case 4: If rule matches and unixname is * then lookup name service 1946c5c4113dSnw141292 * using winname as the unixname. If unixname not found then process 1947c5c4113dSnw141292 * other rules using the lookup order. If no other rule matches then do 1948c5c4113dSnw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 1949c5c4113dSnw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 1950c5c4113dSnw141292 * instead of the default behaviour of doing ephemeral mapping. 1951c5c4113dSnw141292 * 1952c5c4113dSnw141292 * Example 1: 1953c5c4113dSnw141292 * *@sfbay == * 1954c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1955c5c4113dSnw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 1956c5c4113dSnw141292 * 1957c5c4113dSnw141292 * Example 2: 1958c5c4113dSnw141292 * *@sfbay == * 1959c5c4113dSnw141292 * *@sfbay => guest 1960c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1961c5c4113dSnw141292 * the name service then foo@sfbay will be mapped to guest. 1962c5c4113dSnw141292 * 1963c5c4113dSnw141292 * Example 3: 1964c5c4113dSnw141292 * *@sfbay == * 1965c5c4113dSnw141292 * *@sfbay => "" 1966c5c4113dSnw141292 * If looking up windows users foo@sfbay and foo does not exists in 1967c5c4113dSnw141292 * the name service then we will return no mapping for foo@sfbay. 1968c5c4113dSnw141292 * 1969c5c4113dSnw141292 */ 1970*cd37da74Snw141292 static 1971*cd37da74Snw141292 idmap_retcode 1972*cd37da74Snw141292 name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) 1973*cd37da74Snw141292 { 1974*cd37da74Snw141292 const char *unixname, *windomain; 1975*cd37da74Snw141292 char *sql = NULL, *errmsg = NULL, *lower_winname = NULL; 1976c5c4113dSnw141292 idmap_retcode retcode; 1977*cd37da74Snw141292 char *end, *lower_unixname, *winname; 1978c5c4113dSnw141292 const char **values; 1979c5c4113dSnw141292 sqlite_vm *vm = NULL; 1980*cd37da74Snw141292 int ncol, r, i, is_user, is_wuser; 1981c5c4113dSnw141292 const char *me = "name_based_mapping_sid2pid"; 1982c5c4113dSnw141292 19838e228215Sdm199847 winname = req->id1name; 19848e228215Sdm199847 windomain = req->id1domain; 1985*cd37da74Snw141292 1986*cd37da74Snw141292 switch (req->id1.idtype) { 1987*cd37da74Snw141292 case IDMAP_USID: 1988*cd37da74Snw141292 is_wuser = 1; 1989*cd37da74Snw141292 break; 1990*cd37da74Snw141292 case IDMAP_GSID: 1991*cd37da74Snw141292 is_wuser = 0; 1992*cd37da74Snw141292 break; 1993*cd37da74Snw141292 default: 1994*cd37da74Snw141292 idmapdlog(LOG_ERR, "Idmapd internal error: userness of the " 1995*cd37da74Snw141292 "winname undetermined."); 1996*cd37da74Snw141292 return (IDMAP_ERR_INTERNAL); 1997*cd37da74Snw141292 break; 1998*cd37da74Snw141292 } 1999*cd37da74Snw141292 2000*cd37da74Snw141292 switch (req->id2.idtype) { 2001*cd37da74Snw141292 case IDMAP_UID: 2002*cd37da74Snw141292 is_user = 1; 2003*cd37da74Snw141292 break; 2004*cd37da74Snw141292 case IDMAP_GID: 2005*cd37da74Snw141292 is_user = 0; 2006*cd37da74Snw141292 break; 2007*cd37da74Snw141292 case IDMAP_POSIXID: 2008*cd37da74Snw141292 is_user = is_wuser; 2009*cd37da74Snw141292 res->id.idtype = is_user ? IDMAP_UID : IDMAP_GID; 2010*cd37da74Snw141292 break; 2011*cd37da74Snw141292 } 2012c5c4113dSnw141292 2013c5c4113dSnw141292 i = 0; 201462c60062Sbaban if (windomain == NULL) { 201562c60062Sbaban windomain = ""; 201662c60062Sbaban } else { 201762c60062Sbaban RDLOCK_CONFIG(); 2018c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2019c8e26105Sjp151216 if (strcasecmp(_idmapdstate.cfg->pgcfg.default_domain, 2020c5c4113dSnw141292 windomain) == 0) 2021c5c4113dSnw141292 i = 1; 2022c5c4113dSnw141292 } 2023c5c4113dSnw141292 UNLOCK_CONFIG(); 202462c60062Sbaban } 2025c5c4113dSnw141292 2026*cd37da74Snw141292 if ((lower_winname = tolower_u8(winname)) == NULL) 2027*cd37da74Snw141292 lower_winname = winname; /* hope for the best */ 2028c5c4113dSnw141292 sql = sqlite_mprintf( 2029c5c4113dSnw141292 "SELECT unixname, u2w_order FROM namerules WHERE " 2030*cd37da74Snw141292 "w2u_order > 0 AND is_user = %d AND is_wuser = %d AND " 2031c5c4113dSnw141292 "(winname = %Q OR winname = '*') AND " 2032c5c4113dSnw141292 "(windomain = %Q OR windomain = '*' %s) " 2033c5c4113dSnw141292 "ORDER BY w2u_order ASC;", 2034*cd37da74Snw141292 is_user, is_wuser, lower_winname, windomain, 203562c60062Sbaban i ? "OR windomain ISNULL OR windomain = ''" : ""); 2036c5c4113dSnw141292 if (sql == NULL) { 2037c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2038c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2039c5c4113dSnw141292 goto out; 2040c5c4113dSnw141292 } 2041c5c4113dSnw141292 2042c5c4113dSnw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 2043c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2044*cd37da74Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2045*cd37da74Snw141292 CHECK_NULL(errmsg)); 2046c5c4113dSnw141292 sqlite_freemem(errmsg); 2047c5c4113dSnw141292 goto out; 2048c5c4113dSnw141292 } 2049c5c4113dSnw141292 205084decf41Sjp151216 for (; ; ) { 2051c5c4113dSnw141292 r = sqlite_step(vm, &ncol, &values, NULL); 205284decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 2053c5c4113dSnw141292 205484decf41Sjp151216 if (r == SQLITE_ROW) { 2055c5c4113dSnw141292 if (ncol < 2) { 2056c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2057c5c4113dSnw141292 goto out; 2058c5c4113dSnw141292 } 2059c5c4113dSnw141292 if (values[0] == NULL) { 2060c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2061c5c4113dSnw141292 goto out; 2062c5c4113dSnw141292 } 2063c5c4113dSnw141292 2064c5c4113dSnw141292 if (EMPTY_NAME(values[0])) { 2065c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2066c5c4113dSnw141292 goto out; 2067c5c4113dSnw141292 } 2068c5c4113dSnw141292 unixname = (values[0][0] == '*') ? winname : values[0]; 2069*cd37da74Snw141292 lower_unixname = (values[0][0] == '*') ? 2070*cd37da74Snw141292 lower_winname : NULL; 2071*cd37da74Snw141292 retcode = ns_lookup_byname(is_user, unixname, 2072*cd37da74Snw141292 lower_unixname, res); 2073c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2074c5c4113dSnw141292 if (unixname == winname) 2075c5c4113dSnw141292 /* Case 4 */ 2076c5c4113dSnw141292 continue; 2077c5c4113dSnw141292 else 2078c5c4113dSnw141292 /* Case 3 */ 2079c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2080c5c4113dSnw141292 } 2081c5c4113dSnw141292 goto out; 2082c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 2083c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2084c5c4113dSnw141292 goto out; 2085c5c4113dSnw141292 } else { 2086c5c4113dSnw141292 (void) sqlite_finalize(vm, &errmsg); 2087c5c4113dSnw141292 vm = NULL; 2088*cd37da74Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2089*cd37da74Snw141292 CHECK_NULL(errmsg)); 2090c5c4113dSnw141292 sqlite_freemem(errmsg); 2091c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2092c5c4113dSnw141292 goto out; 2093c5c4113dSnw141292 } 2094c5c4113dSnw141292 } 2095c5c4113dSnw141292 2096c5c4113dSnw141292 out: 2097c5c4113dSnw141292 sqlite_freemem(sql); 2098c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 209962c60062Sbaban if (values[1] != NULL) 2100c5c4113dSnw141292 res->direction = 2101651c0131Sbaban (strtol(values[1], &end, 10) == 0)? 2102651c0131Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 2103c5c4113dSnw141292 else 2104651c0131Sbaban res->direction = IDMAP_DIRECTION_W2U; 21058e228215Sdm199847 req->id2name = strdup(unixname); 2106c5c4113dSnw141292 } 2107*cd37da74Snw141292 if (lower_winname != NULL && lower_winname != winname) 2108*cd37da74Snw141292 free(lower_winname); 210962c60062Sbaban if (vm != NULL) 2110c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2111c5c4113dSnw141292 return (retcode); 2112c5c4113dSnw141292 } 2113c5c4113dSnw141292 2114c5c4113dSnw141292 static 2115c5c4113dSnw141292 int 2116c5c4113dSnw141292 get_next_eph_uid(uid_t *next_uid) 2117c5c4113dSnw141292 { 2118c5c4113dSnw141292 uid_t uid; 2119c5c4113dSnw141292 gid_t gid; 2120c5c4113dSnw141292 int err; 2121c5c4113dSnw141292 2122c5c4113dSnw141292 *next_uid = (uid_t)-1; 2123c5c4113dSnw141292 uid = _idmapdstate.next_uid++; 2124c5c4113dSnw141292 if (uid >= _idmapdstate.limit_uid) { 2125c5c4113dSnw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 2126c5c4113dSnw141292 return (err); 2127c5c4113dSnw141292 2128c5c4113dSnw141292 _idmapdstate.limit_uid = uid + 8192; 2129c5c4113dSnw141292 _idmapdstate.next_uid = uid; 2130c5c4113dSnw141292 } 2131c5c4113dSnw141292 *next_uid = uid; 2132c5c4113dSnw141292 2133c5c4113dSnw141292 return (0); 2134c5c4113dSnw141292 } 2135c5c4113dSnw141292 2136c5c4113dSnw141292 static 2137c5c4113dSnw141292 int 2138c5c4113dSnw141292 get_next_eph_gid(gid_t *next_gid) 2139c5c4113dSnw141292 { 2140c5c4113dSnw141292 uid_t uid; 2141c5c4113dSnw141292 gid_t gid; 2142c5c4113dSnw141292 int err; 2143c5c4113dSnw141292 2144c5c4113dSnw141292 *next_gid = (uid_t)-1; 2145c5c4113dSnw141292 gid = _idmapdstate.next_gid++; 2146c5c4113dSnw141292 if (gid >= _idmapdstate.limit_gid) { 2147c5c4113dSnw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 2148c5c4113dSnw141292 return (err); 2149c5c4113dSnw141292 2150c5c4113dSnw141292 _idmapdstate.limit_gid = gid + 8192; 2151c5c4113dSnw141292 _idmapdstate.next_gid = gid; 2152c5c4113dSnw141292 } 2153c5c4113dSnw141292 *next_gid = gid; 2154c5c4113dSnw141292 2155c5c4113dSnw141292 return (0); 2156c5c4113dSnw141292 } 2157c5c4113dSnw141292 215862c60062Sbaban static 215962c60062Sbaban int 2160*cd37da74Snw141292 gethash(const char *str, uint32_t num, uint_t htsize) 2161*cd37da74Snw141292 { 216262c60062Sbaban uint_t hval, i, len; 216362c60062Sbaban 216462c60062Sbaban if (str == NULL) 216562c60062Sbaban return (0); 216662c60062Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 216762c60062Sbaban hval += str[i]; 216862c60062Sbaban hval += (hval << 10); 216962c60062Sbaban hval ^= (hval >> 6); 217062c60062Sbaban } 217162c60062Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 217262c60062Sbaban hval += str[i]; 217362c60062Sbaban hval += (hval << 10); 217462c60062Sbaban hval ^= (hval >> 6); 217562c60062Sbaban } 217662c60062Sbaban hval += (hval << 3); 217762c60062Sbaban hval ^= (hval >> 11); 217862c60062Sbaban hval += (hval << 15); 217962c60062Sbaban return (hval % htsize); 218062c60062Sbaban } 218162c60062Sbaban 218262c60062Sbaban static 218362c60062Sbaban int 218462c60062Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 2185*cd37da74Snw141292 uid_t *pid) 2186*cd37da74Snw141292 { 218762c60062Sbaban uint_t next, key; 218862c60062Sbaban uint_t htsize = state->sid_history_size; 218962c60062Sbaban idmap_sid *sid; 219062c60062Sbaban 219162c60062Sbaban next = gethash(prefix, rid, htsize); 219262c60062Sbaban while (next != htsize) { 219362c60062Sbaban key = state->sid_history[next].key; 219462c60062Sbaban if (key == htsize) 219562c60062Sbaban return (0); 219662c60062Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 219762c60062Sbaban idmap_id_u.sid; 219862c60062Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 219962c60062Sbaban *pid = state->result->ids.ids_val[key].id. 220062c60062Sbaban idmap_id_u.uid; 220162c60062Sbaban return (1); 220262c60062Sbaban } 220362c60062Sbaban next = state->sid_history[next].next; 220462c60062Sbaban } 220562c60062Sbaban return (0); 220662c60062Sbaban } 220762c60062Sbaban 220862c60062Sbaban static 220962c60062Sbaban void 2210*cd37da74Snw141292 add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) 2211*cd37da74Snw141292 { 221262c60062Sbaban uint_t hash, next; 221362c60062Sbaban uint_t htsize = state->sid_history_size; 221462c60062Sbaban 221562c60062Sbaban hash = next = gethash(prefix, rid, htsize); 221662c60062Sbaban while (state->sid_history[next].key != htsize) { 221762c60062Sbaban next++; 221862c60062Sbaban next %= htsize; 221962c60062Sbaban } 222062c60062Sbaban state->sid_history[next].key = state->curpos; 222162c60062Sbaban if (hash == next) 222262c60062Sbaban return; 222362c60062Sbaban state->sid_history[next].next = state->sid_history[hash].next; 222462c60062Sbaban state->sid_history[hash].next = next; 222562c60062Sbaban } 2226c5c4113dSnw141292 2227c5c4113dSnw141292 /* ARGSUSED */ 2228c5c4113dSnw141292 static 2229c5c4113dSnw141292 idmap_retcode 223062c60062Sbaban dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, 2231*cd37da74Snw141292 idmap_mapping *req, idmap_id_res *res) 2232*cd37da74Snw141292 { 2233c5c4113dSnw141292 2234c5c4113dSnw141292 uid_t next_pid; 2235c5c4113dSnw141292 2236651c0131Sbaban res->direction = IDMAP_DIRECTION_BI; 223762c60062Sbaban 223862c60062Sbaban if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) 223962c60062Sbaban return (IDMAP_SUCCESS); 224062c60062Sbaban 224162c60062Sbaban if (state->sid_history != NULL && 224262c60062Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 224362c60062Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 224462c60062Sbaban res->id.idmap_id_u.uid = next_pid; 224562c60062Sbaban return (IDMAP_SUCCESS); 224662c60062Sbaban } 224762c60062Sbaban 224862c60062Sbaban if (res->id.idtype == IDMAP_UID) { 2249c5c4113dSnw141292 if (get_next_eph_uid(&next_pid) != 0) 2250c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2251c5c4113dSnw141292 res->id.idmap_id_u.uid = next_pid; 2252c5c4113dSnw141292 } else { 2253c5c4113dSnw141292 if (get_next_eph_gid(&next_pid) != 0) 2254c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2255c5c4113dSnw141292 res->id.idmap_id_u.gid = next_pid; 2256c5c4113dSnw141292 } 2257c5c4113dSnw141292 225862c60062Sbaban if (state->sid_history != NULL) 225962c60062Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 226062c60062Sbaban req->id1.idmap_id_u.sid.rid); 226162c60062Sbaban 2262c5c4113dSnw141292 return (IDMAP_SUCCESS); 2263c5c4113dSnw141292 } 2264c5c4113dSnw141292 2265c5c4113dSnw141292 idmap_retcode 2266c5c4113dSnw141292 sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 2267*cd37da74Snw141292 idmap_mapping *req, idmap_id_res *res) 2268*cd37da74Snw141292 { 2269c5c4113dSnw141292 idmap_retcode retcode; 2270c5c4113dSnw141292 2271c5c4113dSnw141292 /* 2272c5c4113dSnw141292 * The req->direction field is used to maintain state of the 2273c5c4113dSnw141292 * sid2pid request. 2274c5c4113dSnw141292 */ 2275c5c4113dSnw141292 2276c5c4113dSnw141292 /* Check if second pass is needed */ 2277c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 2278c5c4113dSnw141292 return (res->retcode); 2279c5c4113dSnw141292 2280c5c4113dSnw141292 /* Get status from previous pass */ 2281c5c4113dSnw141292 retcode = (res->retcode == IDMAP_NEXT) ? IDMAP_SUCCESS : res->retcode; 2282c5c4113dSnw141292 2283c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2284c5c4113dSnw141292 /* Reset return type */ 2285c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 2286c5c4113dSnw141292 res->id.idmap_id_u.uid = UID_NOBODY; 2287c5c4113dSnw141292 2288c5c4113dSnw141292 /* Check if this is a localsid */ 2289c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND && 2290c5c4113dSnw141292 _idmapdstate.cfg->pgcfg.machine_sid) { 2291c5c4113dSnw141292 retcode = lookup_localsid2pid(req, res); 2292c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 2293c5c4113dSnw141292 state->sid2pid_done = FALSE; 2294c5c4113dSnw141292 req->direction = _IDMAP_F_S2N_CACHE; 2295c5c4113dSnw141292 } 2296c5c4113dSnw141292 } 2297c5c4113dSnw141292 goto out; 2298c5c4113dSnw141292 } 2299c5c4113dSnw141292 2300c5c4113dSnw141292 /* Name-based mapping */ 2301c5c4113dSnw141292 retcode = name_based_mapping_sid2pid(db, req, res); 2302c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) 2303c5c4113dSnw141292 /* If not found, do ephemeral mapping */ 2304c5c4113dSnw141292 goto ephemeral; 2305c5c4113dSnw141292 else if (retcode != IDMAP_SUCCESS) 2306c5c4113dSnw141292 goto out; 2307c5c4113dSnw141292 2308c5c4113dSnw141292 state->sid2pid_done = FALSE; 2309c5c4113dSnw141292 goto out; 2310c5c4113dSnw141292 2311c5c4113dSnw141292 2312c5c4113dSnw141292 ephemeral: 231362c60062Sbaban retcode = dynamic_ephemeral_mapping(state, cache, req, res); 2314c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) 2315c5c4113dSnw141292 state->sid2pid_done = FALSE; 2316c5c4113dSnw141292 2317c5c4113dSnw141292 out: 2318c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 2319c5c4113dSnw141292 return (retcode); 2320c5c4113dSnw141292 } 2321c5c4113dSnw141292 2322c5c4113dSnw141292 idmap_retcode 2323c5c4113dSnw141292 update_cache_pid2sid(lookup_state_t *state, sqlite *cache, 2324*cd37da74Snw141292 idmap_mapping *req, idmap_id_res *res) 2325*cd37da74Snw141292 { 2326c5c4113dSnw141292 char *sql = NULL; 2327c5c4113dSnw141292 idmap_retcode retcode; 2328c5c4113dSnw141292 2329c5c4113dSnw141292 /* Check if we need to cache anything */ 2330c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 2331c5c4113dSnw141292 return (IDMAP_SUCCESS); 2332c5c4113dSnw141292 2333c5c4113dSnw141292 /* We don't cache negative entries */ 2334c5c4113dSnw141292 if (res->retcode != IDMAP_SUCCESS) 2335c5c4113dSnw141292 return (IDMAP_SUCCESS); 2336c5c4113dSnw141292 2337c5c4113dSnw141292 /* 2338c5c4113dSnw141292 * Using NULL for u2w instead of 0 so that our trigger allows 2339c5c4113dSnw141292 * the same pid to be the destination in multiple entries 2340c5c4113dSnw141292 */ 2341c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2342*cd37da74Snw141292 "(sidprefix, rid, windomain, canon_winname, pid, unixname, " 2343*cd37da74Snw141292 "is_user, is_wuser, expiration, w2u, u2w) " 2344*cd37da74Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " 2345c5c4113dSnw141292 "strftime('%%s','now') + 600, %q, 1); ", 2346*cd37da74Snw141292 res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, 2347*cd37da74Snw141292 req->id2domain, req->id2name, req->id1.idmap_id_u.uid, 2348*cd37da74Snw141292 req->id1name, (req->id1.idtype == IDMAP_UID) ? 1 : 0, 2349*cd37da74Snw141292 (req->id2.idtype == IDMAP_USID) ? 1 : 0, 2350c5c4113dSnw141292 (res->direction == 0) ? "1" : NULL); 2351c5c4113dSnw141292 2352c5c4113dSnw141292 if (sql == NULL) { 2353c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2354c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2355c5c4113dSnw141292 goto out; 2356c5c4113dSnw141292 } 2357c5c4113dSnw141292 2358c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2359c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2360c5c4113dSnw141292 goto out; 2361c5c4113dSnw141292 2362c5c4113dSnw141292 state->pid2sid_done = FALSE; 2363c5c4113dSnw141292 sqlite_freemem(sql); 2364c5c4113dSnw141292 sql = NULL; 2365c5c4113dSnw141292 2366c5c4113dSnw141292 /* If sid2name was found in the cache, no need to update namecache */ 2367c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 2368c5c4113dSnw141292 goto out; 2369c5c4113dSnw141292 23708e228215Sdm199847 if (req->id2name == NULL) 2371c5c4113dSnw141292 goto out; 2372c5c4113dSnw141292 2373c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2374*cd37da74Snw141292 "(sidprefix, rid, canon_name, domain, type, expiration) " 2375c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2376*cd37da74Snw141292 res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, 2377*cd37da74Snw141292 req->id2name, req->id2domain, 2378*cd37da74Snw141292 (req->id2.idtype == IDMAP_UID) ? _IDMAP_T_USER : _IDMAP_T_GROUP); 2379c5c4113dSnw141292 2380c5c4113dSnw141292 if (sql == NULL) { 2381c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2382c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2383c5c4113dSnw141292 goto out; 2384c5c4113dSnw141292 } 2385c5c4113dSnw141292 2386c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2387c5c4113dSnw141292 2388c5c4113dSnw141292 out: 238962c60062Sbaban if (sql != NULL) 2390c5c4113dSnw141292 sqlite_freemem(sql); 2391c5c4113dSnw141292 return (retcode); 2392c5c4113dSnw141292 } 2393c5c4113dSnw141292 2394c5c4113dSnw141292 idmap_retcode 2395c5c4113dSnw141292 update_cache_sid2pid(lookup_state_t *state, sqlite *cache, 2396*cd37da74Snw141292 idmap_mapping *req, idmap_id_res *res) 2397*cd37da74Snw141292 { 2398c5c4113dSnw141292 char *sql = NULL; 2399c5c4113dSnw141292 idmap_retcode retcode; 2400c5c4113dSnw141292 int is_eph_user; 2401c5c4113dSnw141292 2402c5c4113dSnw141292 /* Check if we need to cache anything */ 2403c5c4113dSnw141292 if (req->direction == _IDMAP_F_DONE) 2404c5c4113dSnw141292 return (IDMAP_SUCCESS); 2405c5c4113dSnw141292 2406c5c4113dSnw141292 /* We don't cache negative entries */ 2407c5c4113dSnw141292 if (res->retcode != IDMAP_SUCCESS) 2408c5c4113dSnw141292 return (IDMAP_SUCCESS); 2409c5c4113dSnw141292 2410c5c4113dSnw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 2411c5c4113dSnw141292 is_eph_user = 1; 2412c5c4113dSnw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 2413c5c4113dSnw141292 is_eph_user = 0; 2414c5c4113dSnw141292 else 2415c5c4113dSnw141292 is_eph_user = -1; 2416c5c4113dSnw141292 2417c5c4113dSnw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 2418c5c4113dSnw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 2419c5c4113dSnw141292 "SET w2u = 0 WHERE " 2420c5c4113dSnw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 2421c5c4113dSnw141292 "pid >= 2147483648 AND is_user = %d;", 2422c5c4113dSnw141292 req->id1.idmap_id_u.sid.prefix, 2423c5c4113dSnw141292 req->id1.idmap_id_u.sid.rid, 2424c5c4113dSnw141292 is_eph_user); 2425c5c4113dSnw141292 if (sql == NULL) { 2426c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2427c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2428c5c4113dSnw141292 goto out; 2429c5c4113dSnw141292 } 2430c5c4113dSnw141292 2431c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2432c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2433c5c4113dSnw141292 goto out; 2434c5c4113dSnw141292 2435c5c4113dSnw141292 sqlite_freemem(sql); 2436c5c4113dSnw141292 sql = NULL; 2437c5c4113dSnw141292 } 2438c5c4113dSnw141292 2439*cd37da74Snw141292 2440c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 2441*cd37da74Snw141292 "(sidprefix, rid, windomain, canon_winname, pid, unixname, " 2442*cd37da74Snw141292 "is_user, is_wuser, expiration, w2u, u2w) " 2443*cd37da74Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " 2444c5c4113dSnw141292 "strftime('%%s','now') + 600, 1, %q); ", 2445*cd37da74Snw141292 req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, 2446*cd37da74Snw141292 req->id1domain, req->id1name, res->id.idmap_id_u.uid, 2447*cd37da74Snw141292 req->id2name, (res->id.idtype == IDMAP_UID) ? 1 : 0, 2448*cd37da74Snw141292 (req->id1.idtype == IDMAP_USID) ? 1 : 0, 2449c5c4113dSnw141292 (res->direction == 0) ? "1" : NULL); 2450c5c4113dSnw141292 2451c5c4113dSnw141292 if (sql == NULL) { 2452c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2453c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2454c5c4113dSnw141292 goto out; 2455c5c4113dSnw141292 } 2456c5c4113dSnw141292 2457c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2458c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2459c5c4113dSnw141292 goto out; 2460c5c4113dSnw141292 2461c5c4113dSnw141292 state->sid2pid_done = FALSE; 2462c5c4113dSnw141292 sqlite_freemem(sql); 2463c5c4113dSnw141292 sql = NULL; 2464c5c4113dSnw141292 2465c5c4113dSnw141292 /* If name2sid was found in the cache, no need to update namecache */ 2466c5c4113dSnw141292 if (req->direction & _IDMAP_F_S2N_CACHE) 2467c5c4113dSnw141292 goto out; 2468c5c4113dSnw141292 2469cf5b5989Sdm199847 if (EMPTY_STRING(req->id1name)) 2470c5c4113dSnw141292 goto out; 2471c5c4113dSnw141292 2472c5c4113dSnw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 2473*cd37da74Snw141292 "(sidprefix, rid, canon_name, domain, type, expiration) " 2474c5c4113dSnw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 2475*cd37da74Snw141292 req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, 2476*cd37da74Snw141292 req->id1name, req->id1domain, 2477*cd37da74Snw141292 (req->id1.idtype == IDMAP_USID) ? _IDMAP_T_USER : _IDMAP_T_GROUP); 2478c5c4113dSnw141292 2479c5c4113dSnw141292 if (sql == NULL) { 2480c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2481c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2482c5c4113dSnw141292 goto out; 2483c5c4113dSnw141292 } 2484c5c4113dSnw141292 2485c5c4113dSnw141292 retcode = sql_exec_no_cb(cache, sql); 2486c5c4113dSnw141292 2487c5c4113dSnw141292 out: 248862c60062Sbaban if (sql != NULL) 2489c5c4113dSnw141292 sqlite_freemem(sql); 2490c5c4113dSnw141292 return (retcode); 2491c5c4113dSnw141292 } 2492c5c4113dSnw141292 2493*cd37da74Snw141292 static 2494*cd37da74Snw141292 idmap_retcode 2495c5c4113dSnw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 2496*cd37da74Snw141292 int is_user, int getname) 2497*cd37da74Snw141292 { 2498c5c4113dSnw141292 char *end; 2499c5c4113dSnw141292 char *sql = NULL; 2500c5c4113dSnw141292 const char **values; 2501c5c4113dSnw141292 sqlite_vm *vm = NULL; 2502c5c4113dSnw141292 int ncol; 2503c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2504c5c4113dSnw141292 time_t curtime; 2505c5c4113dSnw141292 2506c5c4113dSnw141292 /* Current time */ 2507c5c4113dSnw141292 errno = 0; 2508c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 2509*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 2510c5c4113dSnw141292 strerror(errno)); 2511c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2512c5c4113dSnw141292 goto out; 2513c5c4113dSnw141292 } 2514c5c4113dSnw141292 2515c5c4113dSnw141292 /* SQL to lookup the cache */ 2516*cd37da74Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, canon_winname, windomain, " 2517*cd37da74Snw141292 "w2u, is_wuser " 2518c5c4113dSnw141292 "FROM idmap_cache WHERE " 2519c5c4113dSnw141292 "pid = %u AND u2w = 1 AND is_user = %d AND " 2520c5c4113dSnw141292 "(pid >= 2147483648 OR " 2521c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 2522c5c4113dSnw141292 "expiration > %d));", 2523c5c4113dSnw141292 req->id1.idmap_id_u.uid, is_user, curtime); 2524c5c4113dSnw141292 if (sql == NULL) { 2525c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2526c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2527c5c4113dSnw141292 goto out; 2528c5c4113dSnw141292 } 2529c5c4113dSnw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); 2530c5c4113dSnw141292 sqlite_freemem(sql); 2531c5c4113dSnw141292 2532c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) 2533c5c4113dSnw141292 goto out; 2534c5c4113dSnw141292 else if (retcode == IDMAP_SUCCESS) { 2535c5c4113dSnw141292 /* sanity checks */ 2536c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 2537c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2538c5c4113dSnw141292 goto out; 2539c5c4113dSnw141292 } 2540c5c4113dSnw141292 2541c5c4113dSnw141292 switch (req->id2.idtype) { 2542c5c4113dSnw141292 case IDMAP_SID: 2543*cd37da74Snw141292 case IDMAP_USID: 2544*cd37da74Snw141292 case IDMAP_GSID: 2545*cd37da74Snw141292 res->id.idtype = 2546*cd37da74Snw141292 strtol(values[5], &end, 10) == 1 2547*cd37da74Snw141292 ? IDMAP_USID : IDMAP_GSID; 2548*cd37da74Snw141292 2549*cd37da74Snw141292 if (req->id2.idtype == IDMAP_USID && 2550*cd37da74Snw141292 res->id.idtype == IDMAP_GSID) { 2551*cd37da74Snw141292 retcode = IDMAP_ERR_NOTUSER; 2552*cd37da74Snw141292 goto out; 2553*cd37da74Snw141292 } else if (req->id2.idtype == IDMAP_GSID && 2554*cd37da74Snw141292 res->id.idtype == IDMAP_USID) { 2555*cd37da74Snw141292 retcode = IDMAP_ERR_NOTGROUP; 2556*cd37da74Snw141292 goto out; 2557*cd37da74Snw141292 } 2558*cd37da74Snw141292 2559c5c4113dSnw141292 res->id.idmap_id_u.sid.rid = 2560c5c4113dSnw141292 strtoul(values[1], &end, 10); 2561c5c4113dSnw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 2562c5c4113dSnw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 2563c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2564c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2565c5c4113dSnw141292 goto out; 2566c5c4113dSnw141292 } 2567c5c4113dSnw141292 256862c60062Sbaban if (values[4] != NULL) 2569c5c4113dSnw141292 res->direction = 2570651c0131Sbaban (strtol(values[4], &end, 10) == 0)? 2571651c0131Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2572c5c4113dSnw141292 else 2573651c0131Sbaban res->direction = IDMAP_DIRECTION_U2W; 2574c5c4113dSnw141292 2575c5c4113dSnw141292 if (getname == 0 || values[2] == NULL) 2576c5c4113dSnw141292 break; 25778e228215Sdm199847 req->id2name = strdup(values[2]); 25788e228215Sdm199847 if (req->id2name == NULL) { 2579c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2580c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2581c5c4113dSnw141292 goto out; 2582c5c4113dSnw141292 } 2583c5c4113dSnw141292 2584c5c4113dSnw141292 if (values[3] == NULL) 2585c5c4113dSnw141292 break; 25868e228215Sdm199847 req->id2domain = strdup(values[3]); 25878e228215Sdm199847 if (req->id2domain == NULL) { 2588c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2589c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2590c5c4113dSnw141292 goto out; 2591c5c4113dSnw141292 } 2592*cd37da74Snw141292 2593*cd37da74Snw141292 req->id2.idtype = res->id.idtype; 2594*cd37da74Snw141292 2595c5c4113dSnw141292 break; 2596c5c4113dSnw141292 default: 2597c5c4113dSnw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 2598c5c4113dSnw141292 break; 2599c5c4113dSnw141292 } 2600c5c4113dSnw141292 } 2601c5c4113dSnw141292 2602c5c4113dSnw141292 out: 260362c60062Sbaban if (vm != NULL) 2604c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2605c5c4113dSnw141292 return (retcode); 2606c5c4113dSnw141292 } 2607c5c4113dSnw141292 2608*cd37da74Snw141292 static 2609*cd37da74Snw141292 idmap_retcode 2610c5c4113dSnw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 2611*cd37da74Snw141292 char **canonname, char **sidprefix, idmap_rid_t *rid, int *type) 2612*cd37da74Snw141292 { 2613*cd37da74Snw141292 char *end, *lower_name; 2614c5c4113dSnw141292 char *sql = NULL; 2615c5c4113dSnw141292 const char **values; 2616c5c4113dSnw141292 sqlite_vm *vm = NULL; 2617c5c4113dSnw141292 int ncol; 2618c5c4113dSnw141292 time_t curtime; 2619c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 2620c5c4113dSnw141292 2621c5c4113dSnw141292 /* Get current time */ 2622c5c4113dSnw141292 errno = 0; 2623c5c4113dSnw141292 if ((curtime = time(NULL)) == (time_t)-1) { 2624*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 2625c5c4113dSnw141292 strerror(errno)); 2626c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2627c5c4113dSnw141292 goto out; 2628c5c4113dSnw141292 } 2629c5c4113dSnw141292 2630c5c4113dSnw141292 /* SQL to lookup the cache */ 2631*cd37da74Snw141292 if ((lower_name = tolower_u8(name)) == NULL) 2632*cd37da74Snw141292 lower_name = (char *)name; 2633*cd37da74Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type, canon_name " 2634*cd37da74Snw141292 "FROM name_cache WHERE name = %Q AND domain = %Q AND " 2635c5c4113dSnw141292 "(expiration = 0 OR expiration ISNULL OR " 2636*cd37da74Snw141292 "expiration > %d);", lower_name, domain, curtime); 2637*cd37da74Snw141292 if (lower_name != name) 2638*cd37da74Snw141292 free(lower_name); 2639c5c4113dSnw141292 if (sql == NULL) { 2640c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2641c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2642c5c4113dSnw141292 goto out; 2643c5c4113dSnw141292 } 2644*cd37da74Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 4, &values); 2645c5c4113dSnw141292 sqlite_freemem(sql); 2646c5c4113dSnw141292 2647c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 264862c60062Sbaban if (type != NULL) { 2649c5c4113dSnw141292 if (values[2] == NULL) { 2650c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2651c5c4113dSnw141292 goto out; 2652c5c4113dSnw141292 } 2653c5c4113dSnw141292 *type = strtol(values[2], &end, 10); 2654c5c4113dSnw141292 } 2655c5c4113dSnw141292 2656*cd37da74Snw141292 if (canonname != NULL) { 2657*cd37da74Snw141292 assert(values[3] != NULL); 2658*cd37da74Snw141292 if ((*canonname = strdup(values[3])) == NULL) { 2659*cd37da74Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 2660*cd37da74Snw141292 retcode = IDMAP_ERR_MEMORY; 2661*cd37da74Snw141292 goto out; 2662*cd37da74Snw141292 } 2663*cd37da74Snw141292 } 2664*cd37da74Snw141292 2665c5c4113dSnw141292 if (values[0] == NULL || values[1] == NULL) { 2666c5c4113dSnw141292 retcode = IDMAP_ERR_CACHE; 2667c5c4113dSnw141292 goto out; 2668c5c4113dSnw141292 } 2669c5c4113dSnw141292 if ((*sidprefix = strdup(values[0])) == NULL) { 2670c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2671c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2672c5c4113dSnw141292 goto out; 2673c5c4113dSnw141292 } 2674c5c4113dSnw141292 *rid = strtoul(values[1], &end, 10); 2675c5c4113dSnw141292 } 2676c5c4113dSnw141292 2677c5c4113dSnw141292 out: 267862c60062Sbaban if (vm != NULL) 2679c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2680c5c4113dSnw141292 return (retcode); 2681c5c4113dSnw141292 } 2682c5c4113dSnw141292 2683*cd37da74Snw141292 static 2684*cd37da74Snw141292 idmap_retcode 2685*cd37da74Snw141292 lookup_win_name2sid(const char *name, const char *domain, 2686*cd37da74Snw141292 char **canonname, char **sidprefix, idmap_rid_t *rid, 2687*cd37da74Snw141292 int *type) 2688*cd37da74Snw141292 { 2689c5c4113dSnw141292 int ret; 2690c5c4113dSnw141292 int retries = 0; 2691c5c4113dSnw141292 idmap_query_state_t *qs = NULL; 2692c5c4113dSnw141292 idmap_retcode rc, retcode; 2693c5c4113dSnw141292 2694c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2695c5c4113dSnw141292 2696c5c4113dSnw141292 retry: 2697c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 2698c5c4113dSnw141292 if (ret != 0) { 2699c8e26105Sjp151216 degrade_svc(); 2700c5c4113dSnw141292 idmapdlog(LOG_ERR, 2701c5c4113dSnw141292 "Failed to create name2sid batch for AD lookup"); 2702c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2703c5c4113dSnw141292 } 2704c5c4113dSnw141292 2705c8e26105Sjp151216 restore_svc(); 2706c8e26105Sjp151216 2707*cd37da74Snw141292 retcode = idmap_name2sid_batch_add1(qs, name, domain, canonname, 2708*cd37da74Snw141292 sidprefix, rid, type, &rc); 2709c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2710c5c4113dSnw141292 goto out; 2711c5c4113dSnw141292 2712c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2713*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to batch name2sid for AD lookup"); 271484decf41Sjp151216 idmap_lookup_release_batch(&qs); 2715c5c4113dSnw141292 return (IDMAP_ERR_INTERNAL); 2716c5c4113dSnw141292 } 2717c5c4113dSnw141292 2718c5c4113dSnw141292 out: 2719c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 272084decf41Sjp151216 idmap_lookup_release_batch(&qs); 2721c5c4113dSnw141292 else 2722c5c4113dSnw141292 retcode = idmap_lookup_batch_end(&qs, NULL); 2723c5c4113dSnw141292 2724c5c4113dSnw141292 if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && retries++ < 2) 2725c5c4113dSnw141292 goto retry; 2726c8e26105Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 2727c8e26105Sjp151216 degrade_svc(); 2728c5c4113dSnw141292 2729c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) { 2730c5c4113dSnw141292 idmapdlog(LOG_NOTICE, "Windows user/group name to SID lookup " 2731c5c4113dSnw141292 "failed"); 2732c5c4113dSnw141292 return (retcode); 2733c5c4113dSnw141292 } else 2734c5c4113dSnw141292 return (rc); 2735c5c4113dSnw141292 /* NOTREACHED */ 2736c5c4113dSnw141292 } 2737c5c4113dSnw141292 2738*cd37da74Snw141292 static 2739*cd37da74Snw141292 idmap_retcode 2740c5c4113dSnw141292 lookup_name2sid(sqlite *cache, const char *name, const char *domain, 2741*cd37da74Snw141292 int *is_wuser, char **canonname, char **sidprefix, 2742*cd37da74Snw141292 idmap_rid_t *rid, idmap_mapping *req) 2743*cd37da74Snw141292 { 2744c5c4113dSnw141292 int type; 2745c5c4113dSnw141292 idmap_retcode retcode; 2746c5c4113dSnw141292 2747*cd37da74Snw141292 *sidprefix = NULL; 2748*cd37da74Snw141292 *canonname = NULL; 2749*cd37da74Snw141292 275062c60062Sbaban /* Lookup name@domain to sid in the well-known sids table */ 2751*cd37da74Snw141292 retcode = lookup_wksids_name2sid(name, canonname, sidprefix, rid, 2752*cd37da74Snw141292 &type); 275362c60062Sbaban if (retcode == IDMAP_SUCCESS) { 275462c60062Sbaban req->direction |= _IDMAP_F_S2N_CACHE; 275562c60062Sbaban goto out; 275662c60062Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 275762c60062Sbaban return (retcode); 275862c60062Sbaban } 275962c60062Sbaban 276062c60062Sbaban /* Lookup name@domain to sid in cache */ 2761*cd37da74Snw141292 retcode = lookup_cache_name2sid(cache, name, domain, canonname, 2762*cd37da74Snw141292 sidprefix, rid, &type); 2763c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2764c5c4113dSnw141292 /* Lookup Windows NT/AD to map name@domain to sid */ 2765*cd37da74Snw141292 retcode = lookup_win_name2sid(name, domain, canonname, 2766*cd37da74Snw141292 sidprefix, rid, &type); 2767c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 2768c5c4113dSnw141292 return (retcode); 2769c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_AD; 2770c5c4113dSnw141292 } else if (retcode != IDMAP_SUCCESS) { 2771c5c4113dSnw141292 return (retcode); 2772c5c4113dSnw141292 } else { 2773c5c4113dSnw141292 /* Set flag */ 2774c5c4113dSnw141292 req->direction |= _IDMAP_F_S2N_CACHE; 2775c5c4113dSnw141292 } 2776c5c4113dSnw141292 277762c60062Sbaban out: 2778c5c4113dSnw141292 /* 2779c5c4113dSnw141292 * Entry found (cache or Windows lookup) 2780*cd37da74Snw141292 * is_wuser is both input as well as output parameter 2781c5c4113dSnw141292 */ 2782*cd37da74Snw141292 if (*is_wuser == 1) { 2783*cd37da74Snw141292 if (type != _IDMAP_T_USER) { 2784*cd37da74Snw141292 if (*sidprefix != NULL) { 2785*cd37da74Snw141292 free(*sidprefix); 2786*cd37da74Snw141292 *sidprefix = NULL; 2787*cd37da74Snw141292 } 2788*cd37da74Snw141292 if (*canonname != NULL) { 2789*cd37da74Snw141292 free(*canonname); 2790*cd37da74Snw141292 *canonname = NULL; 2791*cd37da74Snw141292 } 2792c5c4113dSnw141292 return (IDMAP_ERR_NOTUSER); 2793*cd37da74Snw141292 } 2794*cd37da74Snw141292 } else if (*is_wuser == 0) { 2795*cd37da74Snw141292 if (type != _IDMAP_T_GROUP) { 2796*cd37da74Snw141292 if (*sidprefix != NULL) { 2797*cd37da74Snw141292 free(*sidprefix); 2798*cd37da74Snw141292 *sidprefix = NULL; 2799*cd37da74Snw141292 } 2800*cd37da74Snw141292 if (*canonname != NULL) { 2801*cd37da74Snw141292 free(*canonname); 2802*cd37da74Snw141292 *canonname = NULL; 2803*cd37da74Snw141292 } 2804c5c4113dSnw141292 return (IDMAP_ERR_NOTGROUP); 2805*cd37da74Snw141292 } 2806*cd37da74Snw141292 } else if (*is_wuser == -1) { 2807c5c4113dSnw141292 /* Caller wants to know if its user or group */ 2808c5c4113dSnw141292 if (type == _IDMAP_T_USER) 2809*cd37da74Snw141292 *is_wuser = 1; 2810c5c4113dSnw141292 else if (type == _IDMAP_T_GROUP) 2811*cd37da74Snw141292 *is_wuser = 0; 2812*cd37da74Snw141292 else { 2813*cd37da74Snw141292 if (*sidprefix != NULL) { 2814*cd37da74Snw141292 free(*sidprefix); 2815*cd37da74Snw141292 *sidprefix = NULL; 2816*cd37da74Snw141292 } 2817*cd37da74Snw141292 if (*canonname != NULL) { 2818*cd37da74Snw141292 free(*canonname); 2819*cd37da74Snw141292 *canonname = NULL; 2820*cd37da74Snw141292 } 2821c5c4113dSnw141292 return (IDMAP_ERR_SID); 2822c5c4113dSnw141292 } 2823*cd37da74Snw141292 } 2824c5c4113dSnw141292 2825c5c4113dSnw141292 return (retcode); 2826c5c4113dSnw141292 } 2827c5c4113dSnw141292 2828*cd37da74Snw141292 static 2829*cd37da74Snw141292 idmap_retcode 2830c5c4113dSnw141292 name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, 2831*cd37da74Snw141292 int is_user, idmap_mapping *req, idmap_id_res *res) 2832*cd37da74Snw141292 { 2833c5c4113dSnw141292 const char *winname, *windomain; 2834*cd37da74Snw141292 char *canonname; 2835c8e26105Sjp151216 char *default_domain = NULL; 2836c5c4113dSnw141292 char *sql = NULL, *errmsg = NULL; 2837c5c4113dSnw141292 idmap_retcode retcode; 2838c5c4113dSnw141292 char *end; 2839c5c4113dSnw141292 const char **values; 2840c5c4113dSnw141292 sqlite_vm *vm = NULL; 2841*cd37da74Snw141292 int ncol, r, nrow; 2842c5c4113dSnw141292 const char *me = "name_based_mapping_pid2sid"; 2843*cd37da74Snw141292 int is_wuser; 2844c5c4113dSnw141292 2845c5c4113dSnw141292 RDLOCK_CONFIG(); 2846c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 2847c8e26105Sjp151216 default_domain = 2848c8e26105Sjp151216 strdup(_idmapdstate.cfg->pgcfg.default_domain); 2849c8e26105Sjp151216 if (default_domain == NULL) { 2850c5c4113dSnw141292 UNLOCK_CONFIG(); 2851c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2852c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2853c5c4113dSnw141292 goto out; 2854c5c4113dSnw141292 } 2855c5c4113dSnw141292 } 2856c5c4113dSnw141292 UNLOCK_CONFIG(); 2857c5c4113dSnw141292 2858c5c4113dSnw141292 sql = sqlite_mprintf( 2859*cd37da74Snw141292 "SELECT winname_display, windomain, w2u_order FROM namerules WHERE " 2860c5c4113dSnw141292 "u2w_order > 0 AND is_user = %d AND " 2861c5c4113dSnw141292 "(unixname = %Q OR unixname = '*') " 2862*cd37da74Snw141292 "ORDER BY u2w_order ASC;", is_user, unixname); 2863c5c4113dSnw141292 if (sql == NULL) { 2864c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 2865c5c4113dSnw141292 retcode = IDMAP_ERR_MEMORY; 2866c5c4113dSnw141292 goto out; 2867c5c4113dSnw141292 } 2868c5c4113dSnw141292 2869c5c4113dSnw141292 if (sqlite_compile(db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 2870c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2871*cd37da74Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2872*cd37da74Snw141292 CHECK_NULL(errmsg)); 2873c5c4113dSnw141292 sqlite_freemem(errmsg); 2874c5c4113dSnw141292 goto out; 2875c5c4113dSnw141292 } 2876c5c4113dSnw141292 2877*cd37da74Snw141292 for (nrow = 0; ; ) { 2878c5c4113dSnw141292 r = sqlite_step(vm, &ncol, &values, NULL); 287984decf41Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 288084decf41Sjp151216 if (r == SQLITE_ROW) { 2881*cd37da74Snw141292 nrow++; 2882c5c4113dSnw141292 if (ncol < 3) { 2883c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2884c5c4113dSnw141292 goto out; 2885c5c4113dSnw141292 } 2886c5c4113dSnw141292 if (values[0] == NULL) { 2887c5c4113dSnw141292 /* values [1] and [2] can be null */ 2888c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2889c5c4113dSnw141292 goto out; 2890c5c4113dSnw141292 } 2891c5c4113dSnw141292 if (EMPTY_NAME(values[0])) { 2892c5c4113dSnw141292 retcode = IDMAP_ERR_NOMAPPING; 2893c5c4113dSnw141292 goto out; 2894c5c4113dSnw141292 } 2895*cd37da74Snw141292 2896*cd37da74Snw141292 if (values[0][0] == '*') { 2897*cd37da74Snw141292 if (nrow > 1) { 2898*cd37da74Snw141292 /* 2899*cd37da74Snw141292 * There were non-wildcard rules where 2900*cd37da74Snw141292 * windows identity doesn't exist 2901*cd37da74Snw141292 */ 2902*cd37da74Snw141292 retcode = IDMAP_ERR_NOMAPPING; 2903*cd37da74Snw141292 goto out; 2904*cd37da74Snw141292 } 2905*cd37da74Snw141292 winname = unixname; 2906*cd37da74Snw141292 } else { 2907*cd37da74Snw141292 winname = values[0]; 2908*cd37da74Snw141292 } 2909*cd37da74Snw141292 291062c60062Sbaban if (values[1] != NULL) 2911c5c4113dSnw141292 windomain = values[1]; 2912c8e26105Sjp151216 else if (default_domain != NULL) 2913c8e26105Sjp151216 windomain = default_domain; 2914c5c4113dSnw141292 else { 2915*cd37da74Snw141292 idmapdlog(LOG_ERR, "%s: no domain", me); 2916c5c4113dSnw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 2917c5c4113dSnw141292 goto out; 2918c5c4113dSnw141292 } 2919c5c4113dSnw141292 /* Lookup winname@domain to sid */ 2920*cd37da74Snw141292 2921*cd37da74Snw141292 is_wuser = res->id.idtype == IDMAP_USID ? 1 2922*cd37da74Snw141292 : res->id.idtype == IDMAP_GSID ? 0 2923*cd37da74Snw141292 : -1; 2924*cd37da74Snw141292 2925c5c4113dSnw141292 retcode = lookup_name2sid(cache, winname, windomain, 2926*cd37da74Snw141292 &is_wuser, &canonname, 2927*cd37da74Snw141292 &res->id.idmap_id_u.sid.prefix, 2928c5c4113dSnw141292 &res->id.idmap_id_u.sid.rid, req); 2929c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 2930c5c4113dSnw141292 continue; 2931c5c4113dSnw141292 } 2932*cd37da74Snw141292 2933c5c4113dSnw141292 goto out; 2934c5c4113dSnw141292 } else if (r == SQLITE_DONE) { 2935c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 2936c5c4113dSnw141292 goto out; 2937c5c4113dSnw141292 } else { 2938c5c4113dSnw141292 (void) sqlite_finalize(vm, &errmsg); 2939c5c4113dSnw141292 vm = NULL; 2940*cd37da74Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 2941*cd37da74Snw141292 CHECK_NULL(errmsg)); 2942c5c4113dSnw141292 sqlite_freemem(errmsg); 2943c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 2944c5c4113dSnw141292 goto out; 2945c5c4113dSnw141292 } 2946c5c4113dSnw141292 } 2947c5c4113dSnw141292 2948c5c4113dSnw141292 out: 294962c60062Sbaban if (sql != NULL) 2950c5c4113dSnw141292 sqlite_freemem(sql); 2951c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 2952*cd37da74Snw141292 res->id.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID; 2953*cd37da74Snw141292 295462c60062Sbaban if (values[2] != NULL) 2955c5c4113dSnw141292 res->direction = 2956651c0131Sbaban (strtol(values[2], &end, 10) == 0)? 2957651c0131Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 2958c5c4113dSnw141292 else 2959651c0131Sbaban res->direction = IDMAP_DIRECTION_U2W; 29608e228215Sdm199847 2961*cd37da74Snw141292 req->id2.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID; 2962*cd37da74Snw141292 req->id2name = canonname; 29638e228215Sdm199847 if (req->id2name != NULL) { 2964c8e26105Sjp151216 if (windomain == default_domain) { 29658e228215Sdm199847 req->id2domain = (char *)windomain; 2966c8e26105Sjp151216 default_domain = NULL; 29678e228215Sdm199847 } else { 29688e228215Sdm199847 req->id2domain = strdup(windomain); 29698e228215Sdm199847 } 2970c5c4113dSnw141292 } 2971c5c4113dSnw141292 } 297262c60062Sbaban if (vm != NULL) 2973c5c4113dSnw141292 (void) sqlite_finalize(vm, NULL); 2974c8e26105Sjp151216 if (default_domain != NULL) 2975c8e26105Sjp151216 free(default_domain); 2976c5c4113dSnw141292 return (retcode); 2977c5c4113dSnw141292 } 2978c5c4113dSnw141292 2979*cd37da74Snw141292 /* 2980*cd37da74Snw141292 * Convention when processing unix2win requests: 2981*cd37da74Snw141292 * 2982*cd37da74Snw141292 * Unix identity: 2983*cd37da74Snw141292 * req->id1name = 2984*cd37da74Snw141292 * unixname if given otherwise unixname found will be placed 2985*cd37da74Snw141292 * here. 2986*cd37da74Snw141292 * req->id1domain = 2987*cd37da74Snw141292 * NOT USED 2988*cd37da74Snw141292 * req->id1.idtype = 2989*cd37da74Snw141292 * Given type (IDMAP_UID or IDMAP_GID) 2990*cd37da74Snw141292 * req->id1..[uid or gid] = 2991*cd37da74Snw141292 * UID/GID if given otherwise UID/GID found will be placed here. 2992*cd37da74Snw141292 * 2993*cd37da74Snw141292 * Windows identity: 2994*cd37da74Snw141292 * req->id2name = 2995*cd37da74Snw141292 * winname found will be placed here. 2996*cd37da74Snw141292 * req->id2domain = 2997*cd37da74Snw141292 * windomain found will be placed here. 2998*cd37da74Snw141292 * res->id.idtype = 2999*cd37da74Snw141292 * Target type initialized from req->id2.idtype. If 3000*cd37da74Snw141292 * it is IDMAP_SID then actual type (IDMAP_USID/GSID) found 3001*cd37da74Snw141292 * will be placed here. 3002*cd37da74Snw141292 * req->id..sid.[prefix, rid] = 3003*cd37da74Snw141292 * SID found will be placed here. 3004*cd37da74Snw141292 * 3005*cd37da74Snw141292 * Others: 3006*cd37da74Snw141292 * res->retcode = 3007*cd37da74Snw141292 * Return status for this request will be placed here. 3008*cd37da74Snw141292 * res->direction = 3009*cd37da74Snw141292 * Direction found will be placed here. Direction 3010*cd37da74Snw141292 * meaning whether the resultant mapping is valid 3011*cd37da74Snw141292 * only from unix2win or bi-directional. 3012*cd37da74Snw141292 * req->direction = 3013*cd37da74Snw141292 * INTERNAL USE. Used by idmapd to set various 3014*cd37da74Snw141292 * flags (_IDMAP_F_xxxx) to aid in processing 3015*cd37da74Snw141292 * of the request. 3016*cd37da74Snw141292 * req->id2.idtype = 3017*cd37da74Snw141292 * INTERNAL USE. Initially this is the requested target 3018*cd37da74Snw141292 * type and is used to initialize res->id.idtype. 3019*cd37da74Snw141292 * ad_lookup_batch() uses this field temporarily to store 3020*cd37da74Snw141292 * sid_type obtained by the batched AD lookups and after 3021*cd37da74Snw141292 * use resets it to IDMAP_NONE to prevent xdr from 3022*cd37da74Snw141292 * mis-interpreting the contents of req->id2. 3023*cd37da74Snw141292 * req->id2..[uid or gid or sid] = 3024*cd37da74Snw141292 * NOT USED 3025*cd37da74Snw141292 */ 3026*cd37da74Snw141292 3027*cd37da74Snw141292 /* 3028*cd37da74Snw141292 * This function does the following: 3029*cd37da74Snw141292 * 1. Lookup well-known SIDs table. 3030*cd37da74Snw141292 * 2. Lookup cache. 3031*cd37da74Snw141292 * 3. Check if the client does not want new mapping to be allocated 3032*cd37da74Snw141292 * in which case this pass is the final pass. 3033*cd37da74Snw141292 * 4. Set AD lookup flags if it determines that the next stage needs 3034*cd37da74Snw141292 * to do AD lookup. 3035*cd37da74Snw141292 */ 3036c5c4113dSnw141292 idmap_retcode 3037c5c4113dSnw141292 pid2sid_first_pass(lookup_state_t *state, sqlite *cache, sqlite *db, 3038c5c4113dSnw141292 idmap_mapping *req, idmap_id_res *res, int is_user, 3039*cd37da74Snw141292 int getname) 3040*cd37da74Snw141292 { 3041c5c4113dSnw141292 char *unixname = NULL; 3042c5c4113dSnw141292 struct passwd pwd; 3043c5c4113dSnw141292 struct group grp; 3044c5c4113dSnw141292 char buf[1024]; 3045c5c4113dSnw141292 int errnum; 3046c5c4113dSnw141292 idmap_retcode retcode = IDMAP_SUCCESS; 3047c5c4113dSnw141292 const char *me = "pid2sid"; 3048c5c4113dSnw141292 3049c5c4113dSnw141292 req->direction = _IDMAP_F_DONE; 3050c5c4113dSnw141292 res->id.idtype = req->id2.idtype; 3051c5c4113dSnw141292 3052c5c4113dSnw141292 /* Lookup well-known SIDs */ 3053c5c4113dSnw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 3054c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 3055c5c4113dSnw141292 goto out; 3056c5c4113dSnw141292 3057c5c4113dSnw141292 /* Lookup pid to sid in cache */ 3058c5c4113dSnw141292 retcode = lookup_cache_pid2sid(cache, req, res, is_user, getname); 3059c5c4113dSnw141292 if (retcode != IDMAP_ERR_NOTFOUND) 3060c5c4113dSnw141292 goto out; 3061c5c4113dSnw141292 3062c5c4113dSnw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 3063c5c4113dSnw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 306462c60062Sbaban retcode = IDMAP_ERR_NOMAPPING; 3065c5c4113dSnw141292 goto out; 3066c5c4113dSnw141292 } 3067c5c4113dSnw141292 3068c5c4113dSnw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 306962c60062Sbaban retcode = IDMAP_ERR_NOMAPPING; 3070c5c4113dSnw141292 goto out; 3071c5c4113dSnw141292 } 3072c5c4113dSnw141292 3073c5c4113dSnw141292 /* uid/gid to name */ 3074cf5b5989Sdm199847 if (!EMPTY_STRING(req->id1name)) { 30758e228215Sdm199847 unixname = req->id1name; 30768e228215Sdm199847 } else if (is_user) { 3077c5c4113dSnw141292 errno = 0; 3078c5c4113dSnw141292 if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, 3079c5c4113dSnw141292 sizeof (buf)) == NULL) { 3080c5c4113dSnw141292 errnum = errno; 3081c5c4113dSnw141292 idmapdlog(LOG_WARNING, 3082c5c4113dSnw141292 "%s: getpwuid_r(%u) failed (%s).", 3083c5c4113dSnw141292 me, req->id1.idmap_id_u.uid, 3084c5c4113dSnw141292 errnum ? strerror(errnum) : "not found"); 3085c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3086c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 3087c5c4113dSnw141292 goto fallback_localsid; 3088c5c4113dSnw141292 } 3089c5c4113dSnw141292 unixname = pwd.pw_name; 3090c5c4113dSnw141292 } else { 3091c5c4113dSnw141292 errno = 0; 3092c5c4113dSnw141292 if (getgrgid_r(req->id1.idmap_id_u.gid, &grp, buf, 3093c5c4113dSnw141292 sizeof (buf)) == NULL) { 3094c5c4113dSnw141292 errnum = errno; 3095c5c4113dSnw141292 idmapdlog(LOG_WARNING, 3096c5c4113dSnw141292 "%s: getgrgid_r(%u) failed (%s).", 3097c5c4113dSnw141292 me, req->id1.idmap_id_u.gid, 3098c5c4113dSnw141292 errnum ? strerror(errnum) : "not found"); 3099c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3100c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 3101c5c4113dSnw141292 goto fallback_localsid; 3102c5c4113dSnw141292 } 3103c5c4113dSnw141292 unixname = grp.gr_name; 3104c5c4113dSnw141292 } 3105c5c4113dSnw141292 3106c5c4113dSnw141292 /* Name-based mapping */ 3107c5c4113dSnw141292 retcode = name_based_mapping_pid2sid(db, cache, unixname, is_user, 3108c5c4113dSnw141292 req, res); 3109c5c4113dSnw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 3110c5c4113dSnw141292 retcode = generate_localsid(req, res, is_user); 3111c5c4113dSnw141292 goto out; 3112c5c4113dSnw141292 } else if (retcode == IDMAP_SUCCESS) 3113c5c4113dSnw141292 goto out; 3114c5c4113dSnw141292 3115c5c4113dSnw141292 fallback_localsid: 3116c5c4113dSnw141292 /* 3117c5c4113dSnw141292 * Here we generate localsid as fallback id on errors. Our 3118c5c4113dSnw141292 * return status is the error that's been previously assigned. 3119c5c4113dSnw141292 */ 3120c5c4113dSnw141292 (void) generate_localsid(req, res, is_user); 3121c5c4113dSnw141292 3122c5c4113dSnw141292 out: 3123cf5b5989Sdm199847 if (retcode == IDMAP_SUCCESS && EMPTY_STRING(req->id1name) && 312462c60062Sbaban unixname != NULL) { 3125cf5b5989Sdm199847 if (req->id1name != NULL) 3126cf5b5989Sdm199847 free(req->id1name); 31278e228215Sdm199847 req->id1name = strdup(unixname); 3128cf5b5989Sdm199847 if (req->id1name == NULL) 3129cf5b5989Sdm199847 retcode = IDMAP_ERR_MEMORY; 3130c5c4113dSnw141292 } 3131c5c4113dSnw141292 if (req->direction != _IDMAP_F_DONE) 3132c5c4113dSnw141292 state->pid2sid_done = FALSE; 3133c5c4113dSnw141292 res->retcode = idmap_stat4prot(retcode); 3134c5c4113dSnw141292 return (retcode); 3135c5c4113dSnw141292 } 3136c5c4113dSnw141292 3137*cd37da74Snw141292 static 3138*cd37da74Snw141292 idmap_retcode 3139c5c4113dSnw141292 lookup_win_sid2name(const char *sidprefix, idmap_rid_t rid, char **name, 3140*cd37da74Snw141292 char **domain, int *type) 3141*cd37da74Snw141292 { 3142c5c4113dSnw141292 int ret; 3143c5c4113dSnw141292 idmap_query_state_t *qs = NULL; 3144c5c4113dSnw141292 idmap_retcode rc, retcode; 3145c5c4113dSnw141292 3146c5c4113dSnw141292 retcode = IDMAP_ERR_NOTFOUND; 3147c5c4113dSnw141292 3148c5c4113dSnw141292 ret = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs); 3149c5c4113dSnw141292 if (ret != 0) { 3150c8e26105Sjp151216 degrade_svc(); 3151c5c4113dSnw141292 idmapdlog(LOG_ERR, 3152c5c4113dSnw141292 "Failed to create sid2name batch for AD lookup"); 3153c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 3154c5c4113dSnw141292 goto out; 3155c5c4113dSnw141292 } 3156c5c4113dSnw141292 3157c8e26105Sjp151216 restore_svc(); 3158c8e26105Sjp151216 3159*cd37da74Snw141292 ret = idmap_sid2name_batch_add1(qs, sidprefix, &rid, name, domain, 3160*cd37da74Snw141292 type, &rc); 3161c5c4113dSnw141292 if (ret != 0) { 3162*cd37da74Snw141292 idmapdlog(LOG_ERR, "Failed to batch sid2name for AD lookup"); 3163c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 3164c5c4113dSnw141292 goto out; 3165c5c4113dSnw141292 } 3166c5c4113dSnw141292 3167c5c4113dSnw141292 out: 316862c60062Sbaban if (qs != NULL) { 3169c5c4113dSnw141292 ret = idmap_lookup_batch_end(&qs, NULL); 3170c8e26105Sjp151216 if (ret == IDMAP_ERR_RETRIABLE_NET_ERR) 3171c8e26105Sjp151216 degrade_svc(); 3172c5c4113dSnw141292 if (ret != 0) { 3173c5c4113dSnw141292 idmapdlog(LOG_ERR, 3174c5c4113dSnw141292 "Failed to execute sid2name AD lookup"); 3175c5c4113dSnw141292 retcode = IDMAP_ERR_INTERNAL; 3176c5c4113dSnw141292 } else 3177c5c4113dSnw141292 retcode = rc; 3178c5c4113dSnw141292 } 3179c5c4113dSnw141292 3180c5c4113dSnw141292 return (retcode); 3181c5c4113dSnw141292 } 3182c5c4113dSnw141292 3183*cd37da74Snw141292 static 3184*cd37da74Snw141292 int 3185651c0131Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 3186c5c4113dSnw141292 { 3187651c0131Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 3188651c0131Sbaban 3189c5c4113dSnw141292 mapping->flag = request->flag; 3190c5c4113dSnw141292 mapping->direction = request->direction; 3191651c0131Sbaban mapping->id2.idtype = request->id2.idtype; 3192c5c4113dSnw141292 3193c5c4113dSnw141292 mapping->id1.idtype = request->id1.idtype; 3194*cd37da74Snw141292 if (IS_REQUEST_SID(*request, 1)) { 3195c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.rid = 3196c5c4113dSnw141292 request->id1.idmap_id_u.sid.rid; 3197651c0131Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 3198c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.prefix = 3199c5c4113dSnw141292 strdup(request->id1.idmap_id_u.sid.prefix); 3200651c0131Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 32018e228215Sdm199847 goto errout; 3202651c0131Sbaban } 3203c5c4113dSnw141292 } else { 3204c5c4113dSnw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 3205c5c4113dSnw141292 } 3206c5c4113dSnw141292 32078e228215Sdm199847 mapping->id1domain = strdup(request->id1domain); 32088e228215Sdm199847 if (mapping->id1domain == NULL) 32098e228215Sdm199847 goto errout; 3210c5c4113dSnw141292 32118e228215Sdm199847 mapping->id1name = strdup(request->id1name); 32128e228215Sdm199847 if (mapping->id1name == NULL) 32138e228215Sdm199847 goto errout; 3214c5c4113dSnw141292 3215651c0131Sbaban /* We don't need the rest of the request i.e request->id2 */ 3216651c0131Sbaban return (0); 3217c5c4113dSnw141292 3218651c0131Sbaban errout: 32198e228215Sdm199847 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 3220651c0131Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 32218e228215Sdm199847 if (mapping->id1domain != NULL) 32228e228215Sdm199847 free(mapping->id1domain); 32238e228215Sdm199847 if (mapping->id1name != NULL) 32248e228215Sdm199847 free(mapping->id1name); 3225651c0131Sbaban 3226651c0131Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 3227651c0131Sbaban return (-1); 3228c5c4113dSnw141292 } 3229c5c4113dSnw141292 3230c5c4113dSnw141292 3231c5c4113dSnw141292 idmap_retcode 3232c5c4113dSnw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 3233*cd37da74Snw141292 idmap_mapping *mapping) 3234*cd37da74Snw141292 { 3235c5c4113dSnw141292 idmap_id_res idres; 3236c5c4113dSnw141292 lookup_state_t state; 3237dd5829d1Sbaban char *cp; 3238*cd37da74Snw141292 int is_wuser; 3239c5c4113dSnw141292 idmap_retcode retcode; 3240c5c4113dSnw141292 const char *winname, *windomain; 3241*cd37da74Snw141292 char *canonname; 3242c5c4113dSnw141292 3243c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 3244c5c4113dSnw141292 (void) memset(&state, 0, sizeof (state)); 3245c5c4113dSnw141292 3246*cd37da74Snw141292 if (request->id1.idtype == IDMAP_USID) 3247*cd37da74Snw141292 is_wuser = 1; 3248*cd37da74Snw141292 else if (request->id1.idtype == IDMAP_GSID) 3249*cd37da74Snw141292 is_wuser = 0; 3250*cd37da74Snw141292 else if (request->id1.idtype == IDMAP_SID) 3251*cd37da74Snw141292 is_wuser = -1; 3252c5c4113dSnw141292 else { 3253c5c4113dSnw141292 retcode = IDMAP_ERR_IDTYPE; 3254c5c4113dSnw141292 goto out; 3255c5c4113dSnw141292 } 3256c5c4113dSnw141292 3257c5c4113dSnw141292 /* Copy data from request to result */ 3258651c0131Sbaban if (copy_mapping_request(mapping, request) < 0) { 3259651c0131Sbaban retcode = IDMAP_ERR_MEMORY; 3260651c0131Sbaban goto out; 3261651c0131Sbaban } 3262c5c4113dSnw141292 32638e228215Sdm199847 winname = mapping->id1name; 32648e228215Sdm199847 windomain = mapping->id1domain; 3265c5c4113dSnw141292 3266cf5b5989Sdm199847 if (EMPTY_STRING(winname) && !EMPTY_STRING(windomain)) { 3267c5c4113dSnw141292 retcode = IDMAP_ERR_ARG; 3268c5c4113dSnw141292 goto out; 3269c5c4113dSnw141292 } 3270c5c4113dSnw141292 3271cf5b5989Sdm199847 if (!EMPTY_STRING(winname) && EMPTY_STRING(windomain)) { 32728e228215Sdm199847 retcode = IDMAP_SUCCESS; 3273dd5829d1Sbaban if ((cp = strchr(winname, '@')) != NULL) { 3274dd5829d1Sbaban /* 3275dd5829d1Sbaban * if winname is qualified with a domain, use it. 3276dd5829d1Sbaban */ 3277dd5829d1Sbaban *cp = '\0'; 32788e228215Sdm199847 mapping->id1domain = strdup(cp + 1); 32798e228215Sdm199847 if (mapping->id1domain == NULL) 32808e228215Sdm199847 retcode = IDMAP_ERR_MEMORY; 32818e228215Sdm199847 } else { 32828e228215Sdm199847 RDLOCK_CONFIG(); 3283c8e26105Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 3284dd5829d1Sbaban /* 3285dd5829d1Sbaban * otherwise use the mapping domain 3286dd5829d1Sbaban */ 32878e228215Sdm199847 mapping->id1domain = 32888e228215Sdm199847 strdup(_idmapdstate.cfg-> 3289c8e26105Sjp151216 pgcfg.default_domain); 32908e228215Sdm199847 if (mapping->id1domain == NULL) 32918e228215Sdm199847 retcode = IDMAP_ERR_MEMORY; 32928e228215Sdm199847 } 3293c5c4113dSnw141292 UNLOCK_CONFIG(); 32948e228215Sdm199847 } 3295dd5829d1Sbaban 3296dd5829d1Sbaban if (retcode != IDMAP_SUCCESS) { 3297c5c4113dSnw141292 idmapdlog(LOG_ERR, "Out of memory"); 3298c5c4113dSnw141292 goto out; 3299c5c4113dSnw141292 } 33008e228215Sdm199847 windomain = mapping->id1domain; 3301c5c4113dSnw141292 } 3302c5c4113dSnw141292 3303cf5b5989Sdm199847 if (!EMPTY_STRING(winname) && 3304cf5b5989Sdm199847 EMPTY_STRING(mapping->id1.idmap_id_u.sid.prefix)) { 3305c5c4113dSnw141292 retcode = lookup_name2sid(cache, winname, windomain, 3306*cd37da74Snw141292 &is_wuser, &canonname, &mapping->id1.idmap_id_u.sid.prefix, 3307c5c4113dSnw141292 &mapping->id1.idmap_id_u.sid.rid, mapping); 3308c5c4113dSnw141292 if (retcode != IDMAP_SUCCESS) 3309c5c4113dSnw141292 goto out; 3310*cd37da74Snw141292 free(mapping->id1name); 3311*cd37da74Snw141292 mapping->id1name = canonname; 3312*cd37da74Snw141292 if (mapping->id1.idtype == IDMAP_SID) 3313*cd37da74Snw141292 mapping->id1.idtype = is_wuser ? 3314*cd37da74Snw141292 IDMAP_USID : IDMAP_GSID; 3315c5c4113dSnw141292 } 3316c5c4113dSnw141292 3317c5c4113dSnw141292 state.sid2pid_done = TRUE; 3318c5c4113dSnw141292 retcode = sid2pid_first_pass(&state, cache, mapping, &idres); 3319c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 3320c5c4113dSnw141292 goto out; 3321c5c4113dSnw141292 3322c5c4113dSnw141292 if (state.ad_nqueries) { 3323c5c4113dSnw141292 /* sid2name AD lookup */ 3324c5c4113dSnw141292 retcode = lookup_win_sid2name( 3325c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.prefix, 3326c5c4113dSnw141292 mapping->id1.idmap_id_u.sid.rid, 33278e228215Sdm199847 &mapping->id1name, 33288e228215Sdm199847 &mapping->id1domain, 3329c5c4113dSnw141292 (int *)&idres.id.idtype); 3330c5c4113dSnw141292 3331c5c4113dSnw141292 idres.retcode = retcode; 3332c5c4113dSnw141292 } 3333c5c4113dSnw141292 3334c5c4113dSnw141292 state.sid2pid_done = TRUE; 3335c5c4113dSnw141292 retcode = sid2pid_second_pass(&state, cache, db, mapping, &idres); 3336c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 3337c5c4113dSnw141292 goto out; 3338c5c4113dSnw141292 3339c5c4113dSnw141292 /* Update cache */ 3340c5c4113dSnw141292 (void) update_cache_sid2pid(&state, cache, mapping, &idres); 3341c5c4113dSnw141292 3342c5c4113dSnw141292 out: 3343c5c4113dSnw141292 if (retcode == IDMAP_SUCCESS) { 3344c5c4113dSnw141292 mapping->direction = idres.direction; 3345c5c4113dSnw141292 mapping->id2 = idres.id; 3346c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 334762c60062Sbaban } else { 334862c60062Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 3349c5c4113dSnw141292 } 3350c5c4113dSnw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 3351c5c4113dSnw141292 return (retcode); 3352c5c4113dSnw141292 } 3353c5c4113dSnw141292 3354c5c4113dSnw141292 idmap_retcode 3355c5c4113dSnw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 3356*cd37da74Snw141292 idmap_mapping *mapping, int is_user) 3357*cd37da74Snw141292 { 3358c5c4113dSnw141292 idmap_id_res idres; 3359c5c4113dSnw141292 lookup_state_t state; 3360c5c4113dSnw141292 struct passwd pwd; 3361c5c4113dSnw141292 struct group grp; 3362c5c4113dSnw141292 char buf[1024]; 3363c5c4113dSnw141292 int errnum; 3364c5c4113dSnw141292 idmap_retcode retcode; 3365c5c4113dSnw141292 const char *unixname; 3366c5c4113dSnw141292 const char *me = "get_u2w_mapping"; 3367c5c4113dSnw141292 3368c5c4113dSnw141292 /* 3369c5c4113dSnw141292 * In order to re-use the pid2sid code, we convert 3370c5c4113dSnw141292 * our input data into structs that are expected by 3371c5c4113dSnw141292 * pid2sid_first_pass. 3372c5c4113dSnw141292 */ 3373c5c4113dSnw141292 3374c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 3375c5c4113dSnw141292 (void) memset(&state, 0, sizeof (state)); 3376c5c4113dSnw141292 3377c5c4113dSnw141292 /* Copy data from request to result */ 3378651c0131Sbaban if (copy_mapping_request(mapping, request) < 0) { 3379651c0131Sbaban retcode = IDMAP_ERR_MEMORY; 3380651c0131Sbaban goto out; 3381651c0131Sbaban } 3382c5c4113dSnw141292 33838e228215Sdm199847 unixname = mapping->id1name; 3384c5c4113dSnw141292 3385cf5b5989Sdm199847 if (EMPTY_STRING(unixname) && 3386cf5b5989Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 3387c5c4113dSnw141292 retcode = IDMAP_ERR_ARG; 3388c5c4113dSnw141292 goto out; 3389c5c4113dSnw141292 } 3390c5c4113dSnw141292 3391cf5b5989Sdm199847 if (!EMPTY_STRING(unixname) && 3392cf5b5989Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 3393c5c4113dSnw141292 /* Get uid/gid by name */ 3394c5c4113dSnw141292 if (is_user) { 3395c5c4113dSnw141292 errno = 0; 3396c5c4113dSnw141292 if (getpwnam_r(unixname, &pwd, buf, 3397c5c4113dSnw141292 sizeof (buf)) == NULL) { 3398c5c4113dSnw141292 errnum = errno; 3399c5c4113dSnw141292 idmapdlog(LOG_WARNING, 3400c5c4113dSnw141292 "%s: getpwnam_r(%s) failed (%s).", 3401c5c4113dSnw141292 me, unixname, 3402c5c4113dSnw141292 errnum ? strerror(errnum) : "not found"); 3403c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3404c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 3405c5c4113dSnw141292 goto out; 3406c5c4113dSnw141292 } 3407c5c4113dSnw141292 mapping->id1.idmap_id_u.uid = pwd.pw_uid; 3408c5c4113dSnw141292 } else { 3409c5c4113dSnw141292 errno = 0; 3410c5c4113dSnw141292 if (getgrnam_r(unixname, &grp, buf, 3411c5c4113dSnw141292 sizeof (buf)) == NULL) { 3412c5c4113dSnw141292 errnum = errno; 3413c5c4113dSnw141292 idmapdlog(LOG_WARNING, 3414c5c4113dSnw141292 "%s: getgrnam_r(%s) failed (%s).", 3415c5c4113dSnw141292 me, unixname, 3416c5c4113dSnw141292 errnum ? strerror(errnum) : "not found"); 3417c5c4113dSnw141292 retcode = (errnum == 0)?IDMAP_ERR_NOTFOUND: 3418c5c4113dSnw141292 IDMAP_ERR_INTERNAL; 3419c5c4113dSnw141292 goto out; 3420c5c4113dSnw141292 } 3421c5c4113dSnw141292 mapping->id1.idmap_id_u.gid = grp.gr_gid; 3422c5c4113dSnw141292 } 3423c5c4113dSnw141292 } 3424c5c4113dSnw141292 3425c5c4113dSnw141292 state.pid2sid_done = TRUE; 3426c5c4113dSnw141292 retcode = pid2sid_first_pass(&state, cache, db, mapping, &idres, 3427c5c4113dSnw141292 is_user, 1); 3428c5c4113dSnw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 3429c5c4113dSnw141292 goto out; 3430c5c4113dSnw141292 3431c5c4113dSnw141292 /* Update cache */ 3432c5c4113dSnw141292 (void) update_cache_pid2sid(&state, cache, mapping, &idres); 3433c5c4113dSnw141292 3434c5c4113dSnw141292 out: 3435c5c4113dSnw141292 mapping->direction = idres.direction; 3436c5c4113dSnw141292 mapping->id2 = idres.id; 3437c5c4113dSnw141292 (void) memset(&idres, 0, sizeof (idres)); 3438c5c4113dSnw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 3439c5c4113dSnw141292 return (retcode); 3440c5c4113dSnw141292 } 3441