14520Snw141292 /* 24520Snw141292 * CDDL HEADER START 34520Snw141292 * 44520Snw141292 * The contents of this file are subject to the terms of the 54520Snw141292 * Common Development and Distribution License (the "License"). 64520Snw141292 * You may not use this file except in compliance with the License. 74520Snw141292 * 84520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94520Snw141292 * or http://www.opensolaris.org/os/licensing. 104520Snw141292 * See the License for the specific language governing permissions 114520Snw141292 * and limitations under the License. 124520Snw141292 * 134520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 144520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 164520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 174520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 184520Snw141292 * 194520Snw141292 * CDDL HEADER END 204520Snw141292 */ 214520Snw141292 /* 228671SJulian.Pullen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 234520Snw141292 * Use is subject to license terms. 244520Snw141292 */ 254520Snw141292 264520Snw141292 /* 274520Snw141292 * Database related utility routines 284520Snw141292 */ 294520Snw141292 304520Snw141292 #include <stdio.h> 314520Snw141292 #include <stdlib.h> 324520Snw141292 #include <string.h> 334520Snw141292 #include <errno.h> 344520Snw141292 #include <sys/types.h> 354520Snw141292 #include <sys/stat.h> 364520Snw141292 #include <rpc/rpc.h> 374520Snw141292 #include <sys/sid.h> 384520Snw141292 #include <time.h> 394520Snw141292 #include <pwd.h> 404520Snw141292 #include <grp.h> 414884Sjp151216 #include <pthread.h> 424884Sjp151216 #include <assert.h> 435696Snw141292 #include <sys/u8_textprep.h> 449132SJordan.Brown@Sun.COM #include <alloca.h> 454520Snw141292 464520Snw141292 #include "idmapd.h" 474520Snw141292 #include "adutils.h" 484520Snw141292 #include "string.h" 494520Snw141292 #include "idmap_priv.h" 505696Snw141292 #include "schema.h" 515731Sbaban #include "nldaputils.h" 524520Snw141292 534884Sjp151216 544520Snw141292 static idmap_retcode sql_compile_n_step_once(sqlite *, char *, 554520Snw141292 sqlite_vm **, int *, int, const char ***); 566616Sdm199847 static idmap_retcode ad_lookup_one(lookup_state_t *, idmap_mapping *, 576616Sdm199847 idmap_id_res *); 585731Sbaban static idmap_retcode lookup_localsid2pid(idmap_mapping *, idmap_id_res *); 595731Sbaban static idmap_retcode lookup_cache_name2sid(sqlite *, const char *, 605731Sbaban const char *, char **, char **, idmap_rid_t *, int *); 615731Sbaban 629422SAfshin.Ardakani@Sun.COM #define NELEM(a) (sizeof (a) / sizeof ((a)[0])) 634520Snw141292 644520Snw141292 #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) 654520Snw141292 664520Snw141292 #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ 674520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) 684520Snw141292 694520Snw141292 #define AVOID_NAMESERVICE(req)\ 704520Snw141292 (req->flag & IDMAP_REQ_FLG_NO_NAMESERVICE) 714520Snw141292 728040SBaban.Kenkre@Sun.COM #define ALLOW_WK_OR_LOCAL_SIDS_ONLY(req)\ 738040SBaban.Kenkre@Sun.COM (req->flag & IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY) 748040SBaban.Kenkre@Sun.COM 755731Sbaban #define IS_EPHEMERAL(pid) (pid > INT32_MAX && pid != SENTINEL_PID) 764520Snw141292 774520Snw141292 784520Snw141292 typedef enum init_db_option { 794520Snw141292 FAIL_IF_CORRUPT = 0, 804520Snw141292 REMOVE_IF_CORRUPT = 1 814520Snw141292 } init_db_option_t; 824520Snw141292 834884Sjp151216 /* 849422SAfshin.Ardakani@Sun.COM * Thread specific data to hold the database handles so that the 859422SAfshin.Ardakani@Sun.COM * databases are not opened and closed for every request. It also 864884Sjp151216 * contains the sqlite busy handler structure. 874884Sjp151216 */ 884884Sjp151216 894884Sjp151216 struct idmap_busy { 904884Sjp151216 const char *name; 914884Sjp151216 const int *delays; 924884Sjp151216 int delay_size; 934884Sjp151216 int total; 944884Sjp151216 int sec; 954884Sjp151216 }; 964884Sjp151216 974884Sjp151216 984884Sjp151216 typedef struct idmap_tsd { 994884Sjp151216 sqlite *db_db; 1004884Sjp151216 sqlite *cache_db; 1014884Sjp151216 struct idmap_busy cache_busy; 1024884Sjp151216 struct idmap_busy db_busy; 1034884Sjp151216 } idmap_tsd_t; 1044884Sjp151216 10510504SKeyur.Desai@Sun.COM /* 10610504SKeyur.Desai@Sun.COM * Flags to indicate how local the directory we're consulting is. 10710504SKeyur.Desai@Sun.COM * If neither is set, it means the directory belongs to a remote forest. 10810504SKeyur.Desai@Sun.COM */ 10910504SKeyur.Desai@Sun.COM #define DOMAIN_IS_LOCAL 0x01 11010504SKeyur.Desai@Sun.COM #define FOREST_IS_LOCAL 0x02 1114884Sjp151216 1124884Sjp151216 static const int cache_delay_table[] = 1134884Sjp151216 { 1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 1144884Sjp151216 50, 50, 60, 70, 80, 90, 100}; 1154884Sjp151216 1164884Sjp151216 static const int db_delay_table[] = 1174884Sjp151216 { 5, 10, 15, 20, 30, 40, 55, 70, 100}; 1184884Sjp151216 1194884Sjp151216 1204884Sjp151216 static pthread_key_t idmap_tsd_key; 1214884Sjp151216 1224884Sjp151216 void 1234884Sjp151216 idmap_tsd_destroy(void *key) 1244884Sjp151216 { 1254884Sjp151216 1264884Sjp151216 idmap_tsd_t *tsd = (idmap_tsd_t *)key; 1274884Sjp151216 if (tsd) { 1284884Sjp151216 if (tsd->db_db) 1294884Sjp151216 (void) sqlite_close(tsd->db_db); 1304884Sjp151216 if (tsd->cache_db) 1314884Sjp151216 (void) sqlite_close(tsd->cache_db); 1324884Sjp151216 free(tsd); 1334884Sjp151216 } 1344884Sjp151216 } 1354884Sjp151216 1364884Sjp151216 int 1375696Snw141292 idmap_init_tsd_key(void) 1385696Snw141292 { 1394884Sjp151216 return (pthread_key_create(&idmap_tsd_key, idmap_tsd_destroy)); 1404884Sjp151216 } 1414884Sjp151216 1424884Sjp151216 1434884Sjp151216 1444884Sjp151216 idmap_tsd_t * 1454884Sjp151216 idmap_get_tsd(void) 1464884Sjp151216 { 1474884Sjp151216 idmap_tsd_t *tsd; 1484884Sjp151216 1494884Sjp151216 if ((tsd = pthread_getspecific(idmap_tsd_key)) == NULL) { 1504884Sjp151216 /* No thread specific data so create it */ 1514884Sjp151216 if ((tsd = malloc(sizeof (*tsd))) != NULL) { 1524884Sjp151216 /* Initialize thread specific data */ 1534884Sjp151216 (void) memset(tsd, 0, sizeof (*tsd)); 1544884Sjp151216 /* save the trhread specific data */ 1554884Sjp151216 if (pthread_setspecific(idmap_tsd_key, tsd) != 0) { 1564884Sjp151216 /* Can't store key */ 1574884Sjp151216 free(tsd); 1584884Sjp151216 tsd = NULL; 1594884Sjp151216 } 1604884Sjp151216 } else { 1614884Sjp151216 tsd = NULL; 1624884Sjp151216 } 1634884Sjp151216 } 1644884Sjp151216 1654884Sjp151216 return (tsd); 1664884Sjp151216 } 1674884Sjp151216 1685696Snw141292 /* 1695696Snw141292 * A simple wrapper around u8_textprep_str() that returns the Unicode 1705696Snw141292 * lower-case version of some string. The result must be freed. 1715696Snw141292 */ 1725696Snw141292 char * 1735696Snw141292 tolower_u8(const char *s) 1745696Snw141292 { 1755696Snw141292 char *res = NULL; 1765696Snw141292 char *outs; 1775696Snw141292 size_t inlen, outlen, inbytesleft, outbytesleft; 1785696Snw141292 int rc, err; 1795696Snw141292 1805696Snw141292 /* 1815696Snw141292 * u8_textprep_str() does not allocate memory. The input and 1825696Snw141292 * output buffers may differ in size (though that would be more 1835696Snw141292 * likely when normalization is done). We have to loop over it... 1845696Snw141292 * 1855696Snw141292 * To improve the chances that we can avoid looping we add 10 1865696Snw141292 * bytes of output buffer room the first go around. 1875696Snw141292 */ 1885696Snw141292 inlen = inbytesleft = strlen(s); 1895696Snw141292 outlen = outbytesleft = inlen + 10; 1905696Snw141292 if ((res = malloc(outlen)) == NULL) 1915696Snw141292 return (NULL); 1925696Snw141292 outs = res; 1935696Snw141292 1945696Snw141292 while ((rc = u8_textprep_str((char *)s, &inbytesleft, outs, 1955696Snw141292 &outbytesleft, U8_TEXTPREP_TOLOWER, U8_UNICODE_LATEST, &err)) < 0 && 1965696Snw141292 err == E2BIG) { 1975696Snw141292 if ((res = realloc(res, outlen + inbytesleft)) == NULL) 1985696Snw141292 return (NULL); 1995696Snw141292 /* adjust input/output buffer pointers */ 2005696Snw141292 s += (inlen - inbytesleft); 2015696Snw141292 outs = res + outlen - outbytesleft; 2025696Snw141292 /* adjust outbytesleft and outlen */ 2035696Snw141292 outlen += inbytesleft; 2045696Snw141292 outbytesleft += inbytesleft; 2055696Snw141292 } 2065696Snw141292 2075696Snw141292 if (rc < 0) { 2085696Snw141292 free(res); 2095696Snw141292 res = NULL; 2105696Snw141292 return (NULL); 2115696Snw141292 } 2125696Snw141292 2135696Snw141292 res[outlen - outbytesleft] = '\0'; 2145696Snw141292 2155696Snw141292 return (res); 2165696Snw141292 } 2175696Snw141292 2185696Snw141292 static int sql_exec_tran_no_cb(sqlite *db, char *sql, const char *dbname, 2195696Snw141292 const char *while_doing); 2205696Snw141292 2214520Snw141292 2224520Snw141292 /* 2234520Snw141292 * Initialize 'dbname' using 'sql' 2244520Snw141292 */ 2255696Snw141292 static 2265696Snw141292 int 2275696Snw141292 init_db_instance(const char *dbname, int version, 2285696Snw141292 const char *detect_version_sql, char * const *sql, 2295696Snw141292 init_db_option_t opt, int *created, int *upgraded) 2304520Snw141292 { 2315696Snw141292 int rc, curr_version; 2325696Snw141292 int tries = 1; 2335696Snw141292 int prio = LOG_NOTICE; 2344520Snw141292 sqlite *db = NULL; 2355696Snw141292 char *errmsg = NULL; 2365696Snw141292 2375696Snw141292 *created = 0; 2385696Snw141292 *upgraded = 0; 2395696Snw141292 2405696Snw141292 if (opt == REMOVE_IF_CORRUPT) 2415696Snw141292 tries = 3; 2425696Snw141292 2435696Snw141292 rinse_repeat: 2445696Snw141292 if (tries == 0) { 2455696Snw141292 idmapdlog(LOG_ERR, "Failed to initialize db %s", dbname); 2465696Snw141292 return (-1); 2475696Snw141292 } 2485696Snw141292 if (tries-- == 1) 2495696Snw141292 /* Last try, log errors */ 2505696Snw141292 prio = LOG_ERR; 2515696Snw141292 2525696Snw141292 db = sqlite_open(dbname, 0600, &errmsg); 2535696Snw141292 if (db == NULL) { 2545696Snw141292 idmapdlog(prio, "Error creating database %s (%s)", 2555696Snw141292 dbname, CHECK_NULL(errmsg)); 2565696Snw141292 sqlite_freemem(errmsg); 2575696Snw141292 if (opt == REMOVE_IF_CORRUPT) 2585696Snw141292 (void) unlink(dbname); 2595696Snw141292 goto rinse_repeat; 2604520Snw141292 } 2614520Snw141292 2624520Snw141292 sqlite_busy_timeout(db, 3000); 2635696Snw141292 2645696Snw141292 /* Detect current version of schema in the db, if any */ 2655696Snw141292 curr_version = 0; 2665696Snw141292 if (detect_version_sql != NULL) { 2675696Snw141292 char *end, **results; 2685696Snw141292 int nrow; 2695696Snw141292 2705696Snw141292 #ifdef IDMAPD_DEBUG 2715696Snw141292 (void) fprintf(stderr, "Schema version detection SQL: %s\n", 2725696Snw141292 detect_version_sql); 2735696Snw141292 #endif /* IDMAPD_DEBUG */ 2745696Snw141292 rc = sqlite_get_table(db, detect_version_sql, &results, 2755696Snw141292 &nrow, NULL, &errmsg); 2765696Snw141292 if (rc != SQLITE_OK) { 2775696Snw141292 idmapdlog(prio, 2785696Snw141292 "Error detecting schema version of db %s (%s)", 2795696Snw141292 dbname, errmsg); 2805696Snw141292 sqlite_freemem(errmsg); 2815696Snw141292 sqlite_free_table(results); 2825696Snw141292 sqlite_close(db); 2835696Snw141292 return (-1); 2845696Snw141292 } 2855696Snw141292 if (nrow != 1) { 2865696Snw141292 idmapdlog(prio, 2875696Snw141292 "Error detecting schema version of db %s", dbname); 2885696Snw141292 sqlite_close(db); 2895696Snw141292 sqlite_free_table(results); 2905696Snw141292 return (-1); 2915696Snw141292 } 2925696Snw141292 curr_version = strtol(results[1], &end, 10); 2935696Snw141292 sqlite_free_table(results); 2944520Snw141292 } 2954520Snw141292 2965696Snw141292 if (curr_version < 0) { 2975696Snw141292 if (opt == REMOVE_IF_CORRUPT) 2985696Snw141292 (void) unlink(dbname); 2995696Snw141292 goto rinse_repeat; 3004520Snw141292 } 3014520Snw141292 3025696Snw141292 if (curr_version == version) 3035696Snw141292 goto done; 3045696Snw141292 3055696Snw141292 /* Install or upgrade schema */ 3065696Snw141292 #ifdef IDMAPD_DEBUG 3075696Snw141292 (void) fprintf(stderr, "Schema init/upgrade SQL: %s\n", 3085696Snw141292 sql[curr_version]); 3095696Snw141292 #endif /* IDMAPD_DEBUG */ 3105696Snw141292 rc = sql_exec_tran_no_cb(db, sql[curr_version], dbname, 3115696Snw141292 (curr_version == 0) ? "installing schema" : "upgrading schema"); 3125696Snw141292 if (rc != 0) { 3135696Snw141292 idmapdlog(prio, "Error %s schema for db %s", dbname, 3145696Snw141292 (curr_version == 0) ? "installing schema" : 3155696Snw141292 "upgrading schema"); 3165696Snw141292 if (opt == REMOVE_IF_CORRUPT) 3175696Snw141292 (void) unlink(dbname); 3185696Snw141292 goto rinse_repeat; 3194520Snw141292 } 3204520Snw141292 3215696Snw141292 *upgraded = (curr_version > 0); 3225696Snw141292 *created = (curr_version == 0); 3235696Snw141292 3245696Snw141292 done: 3254520Snw141292 (void) sqlite_close(db); 3265696Snw141292 return (0); 3274520Snw141292 } 3284520Snw141292 3294884Sjp151216 3304884Sjp151216 /* 3314884Sjp151216 * This is the SQLite database busy handler that retries the SQL 3324884Sjp151216 * operation until it is successful. 3334884Sjp151216 */ 3344884Sjp151216 int 3354884Sjp151216 /* LINTED E_FUNC_ARG_UNUSED */ 3364884Sjp151216 idmap_sqlite_busy_handler(void *arg, const char *table_name, int count) 3374884Sjp151216 { 3384884Sjp151216 struct idmap_busy *busy = arg; 3394884Sjp151216 int delay; 3404884Sjp151216 struct timespec rqtp; 3414884Sjp151216 3424884Sjp151216 if (count == 1) { 3434884Sjp151216 busy->total = 0; 3444884Sjp151216 busy->sec = 2; 3454884Sjp151216 } 3464884Sjp151216 if (busy->total > 1000 * busy->sec) { 3476414Sjp151216 idmapdlog(LOG_DEBUG, 3484884Sjp151216 "Thread %d waited %d sec for the %s database", 3494884Sjp151216 pthread_self(), busy->sec, busy->name); 3504884Sjp151216 busy->sec++; 3514884Sjp151216 } 3524884Sjp151216 3534884Sjp151216 if (count <= busy->delay_size) { 3544884Sjp151216 delay = busy->delays[count-1]; 3554884Sjp151216 } else { 3564884Sjp151216 delay = busy->delays[busy->delay_size - 1]; 3574884Sjp151216 } 3584884Sjp151216 busy->total += delay; 3594884Sjp151216 rqtp.tv_sec = 0; 3604884Sjp151216 rqtp.tv_nsec = delay * (NANOSEC / MILLISEC); 3614884Sjp151216 (void) nanosleep(&rqtp, NULL); 3624884Sjp151216 return (1); 3634884Sjp151216 } 3644884Sjp151216 3654884Sjp151216 3664520Snw141292 /* 3674520Snw141292 * Get the database handle 3684520Snw141292 */ 3694520Snw141292 idmap_retcode 3705696Snw141292 get_db_handle(sqlite **db) 3715696Snw141292 { 3725696Snw141292 char *errmsg; 3735696Snw141292 idmap_tsd_t *tsd; 3744520Snw141292 3754520Snw141292 /* 3764884Sjp151216 * Retrieve the db handle from thread-specific storage 3774520Snw141292 * If none exists, open and store in thread-specific storage. 3784520Snw141292 */ 3794884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 3804520Snw141292 idmapdlog(LOG_ERR, 3815696Snw141292 "Error getting thread specific data for %s", IDMAP_DBNAME); 3824884Sjp151216 return (IDMAP_ERR_MEMORY); 3834520Snw141292 } 3844884Sjp151216 3854884Sjp151216 if (tsd->db_db == NULL) { 3864884Sjp151216 tsd->db_db = sqlite_open(IDMAP_DBNAME, 0, &errmsg); 3874884Sjp151216 if (tsd->db_db == NULL) { 3885696Snw141292 idmapdlog(LOG_ERR, "Error opening database %s (%s)", 3895696Snw141292 IDMAP_DBNAME, CHECK_NULL(errmsg)); 3904884Sjp151216 sqlite_freemem(errmsg); 3915696Snw141292 return (IDMAP_ERR_DB); 3924884Sjp151216 } 3935696Snw141292 3944884Sjp151216 tsd->db_busy.name = IDMAP_DBNAME; 3954884Sjp151216 tsd->db_busy.delays = db_delay_table; 3964884Sjp151216 tsd->db_busy.delay_size = sizeof (db_delay_table) / 3974884Sjp151216 sizeof (int); 3984884Sjp151216 sqlite_busy_handler(tsd->db_db, idmap_sqlite_busy_handler, 3994884Sjp151216 &tsd->db_busy); 4004884Sjp151216 } 4014884Sjp151216 *db = tsd->db_db; 4024520Snw141292 return (IDMAP_SUCCESS); 4034520Snw141292 } 4044520Snw141292 4054520Snw141292 /* 4064520Snw141292 * Get the cache handle 4074520Snw141292 */ 4084520Snw141292 idmap_retcode 4095696Snw141292 get_cache_handle(sqlite **cache) 4105696Snw141292 { 4115696Snw141292 char *errmsg; 4125696Snw141292 idmap_tsd_t *tsd; 4134520Snw141292 4144520Snw141292 /* 4154884Sjp151216 * Retrieve the db handle from thread-specific storage 4164520Snw141292 * If none exists, open and store in thread-specific storage. 4174520Snw141292 */ 4184884Sjp151216 if ((tsd = idmap_get_tsd()) == NULL) { 4195696Snw141292 idmapdlog(LOG_ERR, "Error getting thread specific data for %s", 4205696Snw141292 IDMAP_DBNAME); 4214884Sjp151216 return (IDMAP_ERR_MEMORY); 4224520Snw141292 } 4234884Sjp151216 4244884Sjp151216 if (tsd->cache_db == NULL) { 4254884Sjp151216 tsd->cache_db = sqlite_open(IDMAP_CACHENAME, 0, &errmsg); 4264884Sjp151216 if (tsd->cache_db == NULL) { 4275696Snw141292 idmapdlog(LOG_ERR, "Error opening database %s (%s)", 4285696Snw141292 IDMAP_CACHENAME, CHECK_NULL(errmsg)); 4294884Sjp151216 sqlite_freemem(errmsg); 4305696Snw141292 return (IDMAP_ERR_DB); 4314884Sjp151216 } 4325696Snw141292 4334884Sjp151216 tsd->cache_busy.name = IDMAP_CACHENAME; 4344884Sjp151216 tsd->cache_busy.delays = cache_delay_table; 4354884Sjp151216 tsd->cache_busy.delay_size = sizeof (cache_delay_table) / 4364884Sjp151216 sizeof (int); 4374884Sjp151216 sqlite_busy_handler(tsd->cache_db, idmap_sqlite_busy_handler, 4384884Sjp151216 &tsd->cache_busy); 4394884Sjp151216 } 4404884Sjp151216 *cache = tsd->cache_db; 4414520Snw141292 return (IDMAP_SUCCESS); 4424520Snw141292 } 4434520Snw141292 4444520Snw141292 /* 4454520Snw141292 * Initialize cache and db 4464520Snw141292 */ 4474520Snw141292 int 4485696Snw141292 init_dbs() 4495696Snw141292 { 4506386Sjp151216 char *sql[4]; 4515696Snw141292 int created, upgraded; 4525696Snw141292 4534520Snw141292 /* name-based mappings; probably OK to blow away in a pinch(?) */ 4545696Snw141292 sql[0] = DB_INSTALL_SQL; 4555696Snw141292 sql[1] = DB_UPGRADE_FROM_v1_SQL; 4566386Sjp151216 sql[2] = NULL; 4575696Snw141292 4585696Snw141292 if (init_db_instance(IDMAP_DBNAME, DB_VERSION, DB_VERSION_SQL, sql, 4595696Snw141292 FAIL_IF_CORRUPT, &created, &upgraded) < 0) 4604520Snw141292 return (-1); 4614520Snw141292 4624520Snw141292 /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ 4635696Snw141292 sql[0] = CACHE_INSTALL_SQL; 4645696Snw141292 sql[1] = CACHE_UPGRADE_FROM_v1_SQL; 4656386Sjp151216 sql[2] = CACHE_UPGRADE_FROM_v2_SQL; 4666386Sjp151216 sql[3] = NULL; 4676386Sjp151216 4685696Snw141292 if (init_db_instance(IDMAP_CACHENAME, CACHE_VERSION, CACHE_VERSION_SQL, 4695696Snw141292 sql, REMOVE_IF_CORRUPT, &created, &upgraded) < 0) 4704520Snw141292 return (-1); 4714520Snw141292 4725696Snw141292 _idmapdstate.new_eph_db = (created || upgraded) ? 1 : 0; 4735696Snw141292 4744520Snw141292 return (0); 4754520Snw141292 } 4764520Snw141292 4774520Snw141292 /* 4784520Snw141292 * Finalize databases 4794520Snw141292 */ 4804520Snw141292 void 4815696Snw141292 fini_dbs() 4825696Snw141292 { 4834520Snw141292 } 4844520Snw141292 4854520Snw141292 /* 4865731Sbaban * This table is a listing of status codes that will be returned to the 4874520Snw141292 * client when a SQL command fails with the corresponding error message. 4884520Snw141292 */ 4894520Snw141292 static msg_table_t sqlmsgtable[] = { 4904864Sbaban {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 4914520Snw141292 "columns unixname, is_user, u2w_order are not unique"}, 4924864Sbaban {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 4935696Snw141292 "columns winname, windomain, is_user, is_wuser, w2u_order are not" 4945696Snw141292 " unique"}, 4955696Snw141292 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, "Conflicting w2u namerules"}, 4964520Snw141292 {-1, NULL} 4974520Snw141292 }; 4984520Snw141292 4994520Snw141292 /* 5004520Snw141292 * idmapd's version of string2stat to map SQLite messages to 5014520Snw141292 * status codes 5024520Snw141292 */ 5034520Snw141292 idmap_retcode 5045696Snw141292 idmapd_string2stat(const char *msg) 5055696Snw141292 { 5064520Snw141292 int i; 5074520Snw141292 for (i = 0; sqlmsgtable[i].msg; i++) { 5084520Snw141292 if (strcasecmp(sqlmsgtable[i].msg, msg) == 0) 5094520Snw141292 return (sqlmsgtable[i].retcode); 5104520Snw141292 } 5114520Snw141292 return (IDMAP_ERR_OTHER); 5124520Snw141292 } 5134520Snw141292 5144520Snw141292 /* 5155696Snw141292 * Executes some SQL in a transaction. 5165696Snw141292 * 5175696Snw141292 * Returns 0 on success, -1 if it failed but the rollback succeeded, -2 5185696Snw141292 * if the rollback failed. 5195696Snw141292 */ 5205696Snw141292 static 5215696Snw141292 int 5225696Snw141292 sql_exec_tran_no_cb(sqlite *db, char *sql, const char *dbname, 5235696Snw141292 const char *while_doing) 5245696Snw141292 { 5255696Snw141292 char *errmsg = NULL; 5265696Snw141292 int rc; 5275696Snw141292 5285696Snw141292 rc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg); 5295696Snw141292 if (rc != SQLITE_OK) { 5305696Snw141292 idmapdlog(LOG_ERR, "Begin transaction failed (%s) " 5315696Snw141292 "while %s (%s)", errmsg, while_doing, dbname); 5325696Snw141292 sqlite_freemem(errmsg); 5335696Snw141292 return (-1); 5345696Snw141292 } 5355696Snw141292 5365696Snw141292 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 5375696Snw141292 if (rc != SQLITE_OK) { 5385696Snw141292 idmapdlog(LOG_ERR, "Database error (%s) while %s (%s)", errmsg, 5395696Snw141292 while_doing, dbname); 5405696Snw141292 sqlite_freemem(errmsg); 5415696Snw141292 errmsg = NULL; 5425696Snw141292 goto rollback; 5435696Snw141292 } 5445696Snw141292 5455696Snw141292 rc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, &errmsg); 5465696Snw141292 if (rc == SQLITE_OK) { 5475696Snw141292 sqlite_freemem(errmsg); 5485696Snw141292 return (0); 5495696Snw141292 } 5505696Snw141292 5515696Snw141292 idmapdlog(LOG_ERR, "Database commit error (%s) while s (%s)", 5525696Snw141292 errmsg, while_doing, dbname); 5535696Snw141292 sqlite_freemem(errmsg); 5545696Snw141292 errmsg = NULL; 5555696Snw141292 5565696Snw141292 rollback: 5575696Snw141292 rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, &errmsg); 5585696Snw141292 if (rc != SQLITE_OK) { 5595696Snw141292 idmapdlog(LOG_ERR, "Rollback failed (%s) while %s (%s)", 5605696Snw141292 errmsg, while_doing, dbname); 5615696Snw141292 sqlite_freemem(errmsg); 5625696Snw141292 return (-2); 5635696Snw141292 } 5645696Snw141292 sqlite_freemem(errmsg); 5655696Snw141292 5665696Snw141292 return (-1); 5675696Snw141292 } 5685696Snw141292 5695696Snw141292 /* 5704520Snw141292 * Execute the given SQL statment without using any callbacks 5714520Snw141292 */ 5724520Snw141292 idmap_retcode 5736017Snw141292 sql_exec_no_cb(sqlite *db, const char *dbname, char *sql) 5745696Snw141292 { 5754520Snw141292 char *errmsg = NULL; 5764884Sjp151216 int r; 5774520Snw141292 idmap_retcode retcode; 5784520Snw141292 5794884Sjp151216 r = sqlite_exec(db, sql, NULL, NULL, &errmsg); 5804884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 5814520Snw141292 5824520Snw141292 if (r != SQLITE_OK) { 5836017Snw141292 idmapdlog(LOG_ERR, "Database error on %s while executing %s " 5846017Snw141292 "(%s)", dbname, sql, CHECK_NULL(errmsg)); 5854884Sjp151216 retcode = idmapd_string2stat(errmsg); 5864864Sbaban if (errmsg != NULL) 5874520Snw141292 sqlite_freemem(errmsg); 5884520Snw141292 return (retcode); 5894520Snw141292 } 5904520Snw141292 5914520Snw141292 return (IDMAP_SUCCESS); 5924520Snw141292 } 5934520Snw141292 5944520Snw141292 /* 5954520Snw141292 * Generate expression that can be used in WHERE statements. 5964520Snw141292 * Examples: 5974520Snw141292 * <prefix> <col> <op> <value> <suffix> 5984520Snw141292 * "" "unixuser" "=" "foo" "AND" 5994520Snw141292 */ 6004520Snw141292 idmap_retcode 6015696Snw141292 gen_sql_expr_from_rule(idmap_namerule *rule, char **out) 6025696Snw141292 { 6035696Snw141292 char *s_windomain = NULL, *s_winname = NULL; 6045696Snw141292 char *s_unixname = NULL; 605*10966SJordan.Brown@Sun.COM char *dir; 6065696Snw141292 char *lower_winname; 6075696Snw141292 int retcode = IDMAP_SUCCESS; 6085696Snw141292 6094520Snw141292 if (out == NULL) 6104520Snw141292 return (IDMAP_ERR_ARG); 6114520Snw141292 6125696Snw141292 6135696Snw141292 if (!EMPTY_STRING(rule->windomain)) { 6145696Snw141292 s_windomain = sqlite_mprintf("AND windomain = %Q ", 6155696Snw141292 rule->windomain); 6165696Snw141292 if (s_windomain == NULL) { 6175696Snw141292 retcode = IDMAP_ERR_MEMORY; 6185696Snw141292 goto out; 6195696Snw141292 } 6205696Snw141292 } 6215696Snw141292 6225696Snw141292 if (!EMPTY_STRING(rule->winname)) { 6235696Snw141292 if ((lower_winname = tolower_u8(rule->winname)) == NULL) 6245696Snw141292 lower_winname = rule->winname; 6255696Snw141292 s_winname = sqlite_mprintf( 6265696Snw141292 "AND winname = %Q AND is_wuser = %d ", 6275696Snw141292 lower_winname, rule->is_wuser ? 1 : 0); 6285696Snw141292 if (lower_winname != rule->winname) 6295696Snw141292 free(lower_winname); 6305696Snw141292 if (s_winname == NULL) { 6315696Snw141292 retcode = IDMAP_ERR_MEMORY; 6325696Snw141292 goto out; 6335696Snw141292 } 6345696Snw141292 } 6355696Snw141292 6365696Snw141292 if (!EMPTY_STRING(rule->unixname)) { 6375696Snw141292 s_unixname = sqlite_mprintf( 6385696Snw141292 "AND unixname = %Q AND is_user = %d ", 6395696Snw141292 rule->unixname, rule->is_user ? 1 : 0); 6405696Snw141292 if (s_unixname == NULL) { 6415696Snw141292 retcode = IDMAP_ERR_MEMORY; 6425696Snw141292 goto out; 6435696Snw141292 } 6445696Snw141292 } 6455696Snw141292 646*10966SJordan.Brown@Sun.COM switch (rule->direction) { 647*10966SJordan.Brown@Sun.COM case IDMAP_DIRECTION_BI: 648*10966SJordan.Brown@Sun.COM dir = "AND w2u_order > 0 AND u2w_order > 0"; 649*10966SJordan.Brown@Sun.COM break; 650*10966SJordan.Brown@Sun.COM case IDMAP_DIRECTION_W2U: 651*10966SJordan.Brown@Sun.COM dir = "AND w2u_order > 0" 652*10966SJordan.Brown@Sun.COM " AND (u2w_order = 0 OR u2w_order ISNULL)"; 653*10966SJordan.Brown@Sun.COM break; 654*10966SJordan.Brown@Sun.COM case IDMAP_DIRECTION_U2W: 655*10966SJordan.Brown@Sun.COM dir = "AND u2w_order > 0" 656*10966SJordan.Brown@Sun.COM " AND (w2u_order = 0 OR w2u_order ISNULL)"; 657*10966SJordan.Brown@Sun.COM break; 658*10966SJordan.Brown@Sun.COM default: 659*10966SJordan.Brown@Sun.COM dir = ""; 660*10966SJordan.Brown@Sun.COM break; 661*10966SJordan.Brown@Sun.COM } 662*10966SJordan.Brown@Sun.COM 663*10966SJordan.Brown@Sun.COM *out = sqlite_mprintf("%s %s %s %s", 6645696Snw141292 s_windomain ? s_windomain : "", 6655696Snw141292 s_winname ? s_winname : "", 666*10966SJordan.Brown@Sun.COM s_unixname ? s_unixname : "", 667*10966SJordan.Brown@Sun.COM dir); 6685696Snw141292 6695696Snw141292 if (*out == NULL) { 6705696Snw141292 retcode = IDMAP_ERR_MEMORY; 6715696Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 6725696Snw141292 goto out; 6735696Snw141292 } 6745696Snw141292 6755696Snw141292 out: 6765696Snw141292 if (s_windomain != NULL) 6775696Snw141292 sqlite_freemem(s_windomain); 6785696Snw141292 if (s_winname != NULL) 6795696Snw141292 sqlite_freemem(s_winname); 6805696Snw141292 if (s_unixname != NULL) 6815696Snw141292 sqlite_freemem(s_unixname); 6825696Snw141292 6835696Snw141292 return (retcode); 6844520Snw141292 } 6854520Snw141292 6865696Snw141292 6875696Snw141292 6884520Snw141292 /* 6894520Snw141292 * Generate and execute SQL statement for LIST RPC calls 6904520Snw141292 */ 6914520Snw141292 idmap_retcode 6926017Snw141292 process_list_svc_sql(sqlite *db, const char *dbname, char *sql, uint64_t limit, 6936386Sjp151216 int flag, list_svc_cb cb, void *result) 6945696Snw141292 { 6954520Snw141292 list_cb_data_t cb_data; 6964520Snw141292 char *errmsg = NULL; 6974884Sjp151216 int r; 6984520Snw141292 idmap_retcode retcode = IDMAP_ERR_INTERNAL; 6994520Snw141292 7004520Snw141292 (void) memset(&cb_data, 0, sizeof (cb_data)); 7014520Snw141292 cb_data.result = result; 7024520Snw141292 cb_data.limit = limit; 7036386Sjp151216 cb_data.flag = flag; 7044520Snw141292 7054884Sjp151216 7064884Sjp151216 r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); 7074884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 7084884Sjp151216 switch (r) { 7094884Sjp151216 case SQLITE_OK: 7104884Sjp151216 retcode = IDMAP_SUCCESS; 7114884Sjp151216 break; 7124884Sjp151216 7134884Sjp151216 default: 7144884Sjp151216 retcode = IDMAP_ERR_INTERNAL; 7156017Snw141292 idmapdlog(LOG_ERR, "Database error on %s while executing " 7166017Snw141292 "%s (%s)", dbname, sql, CHECK_NULL(errmsg)); 7174884Sjp151216 break; 7184520Snw141292 } 7194864Sbaban if (errmsg != NULL) 7204520Snw141292 sqlite_freemem(errmsg); 7214520Snw141292 return (retcode); 7224520Snw141292 } 7234520Snw141292 7244520Snw141292 /* 7254520Snw141292 * This routine is called by callbacks that process the results of 7264520Snw141292 * LIST RPC calls to validate data and to allocate memory for 7274520Snw141292 * the result array. 7284520Snw141292 */ 7294520Snw141292 idmap_retcode 7304520Snw141292 validate_list_cb_data(list_cb_data_t *cb_data, int argc, char **argv, 7315696Snw141292 int ncol, uchar_t **list, size_t valsize) 7325696Snw141292 { 7334520Snw141292 size_t nsize; 7344520Snw141292 void *tmplist; 7354520Snw141292 7364520Snw141292 if (cb_data->limit > 0 && cb_data->next == cb_data->limit) 7374520Snw141292 return (IDMAP_NEXT); 7384520Snw141292 7394520Snw141292 if (argc < ncol || argv == NULL) { 7404520Snw141292 idmapdlog(LOG_ERR, "Invalid data"); 7414520Snw141292 return (IDMAP_ERR_INTERNAL); 7424520Snw141292 } 7434520Snw141292 7444520Snw141292 /* alloc in bulk to reduce number of reallocs */ 7454520Snw141292 if (cb_data->next >= cb_data->len) { 7464520Snw141292 nsize = (cb_data->len + SIZE_INCR) * valsize; 7474520Snw141292 tmplist = realloc(*list, nsize); 7484520Snw141292 if (tmplist == NULL) { 7494520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7504520Snw141292 return (IDMAP_ERR_MEMORY); 7514520Snw141292 } 7524520Snw141292 *list = tmplist; 7534520Snw141292 (void) memset(*list + (cb_data->len * valsize), 0, 7545696Snw141292 SIZE_INCR * valsize); 7554520Snw141292 cb_data->len += SIZE_INCR; 7564520Snw141292 } 7574520Snw141292 return (IDMAP_SUCCESS); 7584520Snw141292 } 7594520Snw141292 7605696Snw141292 static 7615696Snw141292 idmap_retcode 7624520Snw141292 get_namerule_order(char *winname, char *windomain, char *unixname, 7635696Snw141292 int direction, int is_diagonal, int *w2u_order, int *u2w_order) 7645696Snw141292 { 7654520Snw141292 *w2u_order = 0; 7664520Snw141292 *u2w_order = 0; 7674520Snw141292 7684520Snw141292 /* 7694520Snw141292 * Windows to UNIX lookup order: 7704520Snw141292 * 1. winname@domain (or winname) to "" 7714520Snw141292 * 2. winname@domain (or winname) to unixname 7724520Snw141292 * 3. winname@* to "" 7734520Snw141292 * 4. winname@* to unixname 7744520Snw141292 * 5. *@domain (or *) to * 7754520Snw141292 * 6. *@domain (or *) to "" 7764520Snw141292 * 7. *@domain (or *) to unixname 7774520Snw141292 * 8. *@* to * 7784520Snw141292 * 9. *@* to "" 7794520Snw141292 * 10. *@* to unixname 7804520Snw141292 * 7814520Snw141292 * winname is a special case of winname@domain when domain is the 7824520Snw141292 * default domain. Similarly * is a special case of *@domain when 7834520Snw141292 * domain is the default domain. 7844520Snw141292 * 7854520Snw141292 * Note that "" has priority over specific names because "" inhibits 7864520Snw141292 * mappings and traditionally deny rules always had higher priority. 7874520Snw141292 */ 7884644Sbaban if (direction != IDMAP_DIRECTION_U2W) { 7894644Sbaban /* bi-directional or from windows to unix */ 7904520Snw141292 if (winname == NULL) 7914520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 7924520Snw141292 else if (unixname == NULL) 7934520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 7944520Snw141292 else if (EMPTY_NAME(winname)) 7954520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 7964520Snw141292 else if (*winname == '*' && windomain && *windomain == '*') { 7974520Snw141292 if (*unixname == '*') 7984520Snw141292 *w2u_order = 8; 7994520Snw141292 else if (EMPTY_NAME(unixname)) 8004520Snw141292 *w2u_order = 9; 8014520Snw141292 else /* unixname == name */ 8024520Snw141292 *w2u_order = 10; 8034520Snw141292 } else if (*winname == '*') { 8044520Snw141292 if (*unixname == '*') 8054520Snw141292 *w2u_order = 5; 8064520Snw141292 else if (EMPTY_NAME(unixname)) 8074520Snw141292 *w2u_order = 6; 8084520Snw141292 else /* name */ 8094520Snw141292 *w2u_order = 7; 8104864Sbaban } else if (windomain != NULL && *windomain == '*') { 8114520Snw141292 /* winname == name */ 8124520Snw141292 if (*unixname == '*') 8134520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 8144520Snw141292 else if (EMPTY_NAME(unixname)) 8154520Snw141292 *w2u_order = 3; 8164520Snw141292 else /* name */ 8174520Snw141292 *w2u_order = 4; 8184520Snw141292 } else { 8194520Snw141292 /* winname == name && windomain == null or name */ 8204520Snw141292 if (*unixname == '*') 8214520Snw141292 return (IDMAP_ERR_W2U_NAMERULE); 8224520Snw141292 else if (EMPTY_NAME(unixname)) 8234520Snw141292 *w2u_order = 1; 8244520Snw141292 else /* name */ 8254520Snw141292 *w2u_order = 2; 8264520Snw141292 } 8275696Snw141292 8284520Snw141292 } 8294520Snw141292 8304520Snw141292 /* 8315696Snw141292 * 1. unixname to "", non-diagonal 8325696Snw141292 * 2. unixname to winname@domain (or winname), non-diagonal 8335696Snw141292 * 3. unixname to "", diagonal 8345696Snw141292 * 4. unixname to winname@domain (or winname), diagonal 8355696Snw141292 * 5. * to *@domain (or *), non-diagonal 8365696Snw141292 * 5. * to *@domain (or *), diagonal 8375696Snw141292 * 7. * to "" 8385696Snw141292 * 8. * to winname@domain (or winname) 8395696Snw141292 * 9. * to "", non-diagonal 8405696Snw141292 * 10. * to winname@domain (or winname), diagonal 8414520Snw141292 */ 8424644Sbaban if (direction != IDMAP_DIRECTION_W2U) { 8435696Snw141292 int diagonal = is_diagonal ? 1 : 0; 8445696Snw141292 8454644Sbaban /* bi-directional or from unix to windows */ 8464520Snw141292 if (unixname == NULL || EMPTY_NAME(unixname)) 8474520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 8484520Snw141292 else if (winname == NULL) 8494520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 8504864Sbaban else if (windomain != NULL && *windomain == '*') 8514644Sbaban return (IDMAP_ERR_U2W_NAMERULE); 8524520Snw141292 else if (*unixname == '*') { 8534520Snw141292 if (*winname == '*') 8545696Snw141292 *u2w_order = 5 + diagonal; 8554520Snw141292 else if (EMPTY_NAME(winname)) 8565696Snw141292 *u2w_order = 7 + 2 * diagonal; 8574520Snw141292 else 8585696Snw141292 *u2w_order = 8 + 2 * diagonal; 8594520Snw141292 } else { 8604520Snw141292 if (*winname == '*') 8614520Snw141292 return (IDMAP_ERR_U2W_NAMERULE); 8624520Snw141292 else if (EMPTY_NAME(winname)) 8635696Snw141292 *u2w_order = 1 + 2 * diagonal; 8644520Snw141292 else 8655696Snw141292 *u2w_order = 2 + 2 * diagonal; 8664520Snw141292 } 8674520Snw141292 } 8684520Snw141292 return (IDMAP_SUCCESS); 8694520Snw141292 } 8704520Snw141292 8714520Snw141292 /* 8724520Snw141292 * Generate and execute SQL statement to add name-based mapping rule 8734520Snw141292 */ 8744520Snw141292 idmap_retcode 8755696Snw141292 add_namerule(sqlite *db, idmap_namerule *rule) 8765696Snw141292 { 8774520Snw141292 char *sql = NULL; 8784520Snw141292 idmap_stat retcode; 8795064Sdm199847 char *dom = NULL; 8809422SAfshin.Ardakani@Sun.COM char *name; 8814520Snw141292 int w2u_order, u2w_order; 8824520Snw141292 char w2ubuf[11], u2wbuf[11]; 8839422SAfshin.Ardakani@Sun.COM char *canonname = NULL; 8849422SAfshin.Ardakani@Sun.COM char *canondomain = NULL; 8854520Snw141292 8865064Sdm199847 retcode = get_namerule_order(rule->winname, rule->windomain, 8875696Snw141292 rule->unixname, rule->direction, 8885696Snw141292 rule->is_user == rule->is_wuser ? 0 : 1, &w2u_order, &u2w_order); 8894520Snw141292 if (retcode != IDMAP_SUCCESS) 8904520Snw141292 goto out; 8914520Snw141292 8924520Snw141292 if (w2u_order) 8934520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "%d", w2u_order); 8944520Snw141292 if (u2w_order) 8954520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "%d", u2w_order); 8964520Snw141292 8974864Sbaban /* 8984864Sbaban * For the triggers on namerules table to work correctly: 8994864Sbaban * 1) Use NULL instead of 0 for w2u_order and u2w_order 9004864Sbaban * 2) Use "" instead of NULL for "no domain" 9014864Sbaban */ 9024864Sbaban 9039422SAfshin.Ardakani@Sun.COM name = rule->winname; 9049422SAfshin.Ardakani@Sun.COM dom = rule->windomain; 9054520Snw141292 9064520Snw141292 RDLOCK_CONFIG(); 9079422SAfshin.Ardakani@Sun.COM if (lookup_wksids_name2sid(name, dom, 9089422SAfshin.Ardakani@Sun.COM &canonname, &canondomain, 9099422SAfshin.Ardakani@Sun.COM NULL, NULL, NULL) == IDMAP_SUCCESS) { 9109422SAfshin.Ardakani@Sun.COM name = canonname; 9119422SAfshin.Ardakani@Sun.COM dom = canondomain; 9129422SAfshin.Ardakani@Sun.COM } else if (EMPTY_STRING(dom)) { 9135317Sjp151216 if (_idmapdstate.cfg->pgcfg.default_domain) 9145317Sjp151216 dom = _idmapdstate.cfg->pgcfg.default_domain; 9154864Sbaban else 9164864Sbaban dom = ""; 9174864Sbaban } 9184884Sjp151216 sql = sqlite_mprintf("INSERT into namerules " 9195696Snw141292 "(is_user, is_wuser, windomain, winname_display, is_nt4, " 9205696Snw141292 "unixname, w2u_order, u2w_order) " 9215696Snw141292 "VALUES(%d, %d, %Q, %Q, %d, %Q, %q, %q);", 9225696Snw141292 rule->is_user ? 1 : 0, rule->is_wuser ? 1 : 0, dom, 9239422SAfshin.Ardakani@Sun.COM name, rule->is_nt4 ? 1 : 0, rule->unixname, 9245696Snw141292 w2u_order ? w2ubuf : NULL, u2w_order ? u2wbuf : NULL); 9254520Snw141292 UNLOCK_CONFIG(); 9264520Snw141292 9274520Snw141292 if (sql == NULL) { 9284520Snw141292 retcode = IDMAP_ERR_INTERNAL; 9294520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 9304520Snw141292 goto out; 9314520Snw141292 } 9324520Snw141292 9336017Snw141292 retcode = sql_exec_no_cb(db, IDMAP_DBNAME, sql); 9344520Snw141292 9354520Snw141292 if (retcode == IDMAP_ERR_OTHER) 9364520Snw141292 retcode = IDMAP_ERR_CFG; 9374520Snw141292 9384520Snw141292 out: 9399422SAfshin.Ardakani@Sun.COM free(canonname); 9409422SAfshin.Ardakani@Sun.COM free(canondomain); 9414864Sbaban if (sql != NULL) 9424520Snw141292 sqlite_freemem(sql); 9434520Snw141292 return (retcode); 9444520Snw141292 } 9454520Snw141292 9464520Snw141292 /* 9474520Snw141292 * Flush name-based mapping rules 9484520Snw141292 */ 9494520Snw141292 idmap_retcode 9505696Snw141292 flush_namerules(sqlite *db) 9515696Snw141292 { 9524520Snw141292 idmap_stat retcode; 9534520Snw141292 9546017Snw141292 retcode = sql_exec_no_cb(db, IDMAP_DBNAME, "DELETE FROM namerules;"); 9555696Snw141292 9564520Snw141292 return (retcode); 9574520Snw141292 } 9584520Snw141292 9594520Snw141292 /* 9604520Snw141292 * Generate and execute SQL statement to remove a name-based mapping rule 9614520Snw141292 */ 9624520Snw141292 idmap_retcode 9635696Snw141292 rm_namerule(sqlite *db, idmap_namerule *rule) 9645696Snw141292 { 9654520Snw141292 char *sql = NULL; 9664520Snw141292 idmap_stat retcode; 9675696Snw141292 char *expr = NULL; 9684520Snw141292 9695064Sdm199847 if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && 9705064Sdm199847 EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 9714520Snw141292 return (IDMAP_SUCCESS); 9724520Snw141292 9735696Snw141292 retcode = gen_sql_expr_from_rule(rule, &expr); 9745696Snw141292 if (retcode != IDMAP_SUCCESS) 9755696Snw141292 goto out; 9765696Snw141292 977*10966SJordan.Brown@Sun.COM sql = sqlite_mprintf("DELETE FROM namerules WHERE 1 %s;", expr); 9784520Snw141292 9794520Snw141292 if (sql == NULL) { 9804520Snw141292 retcode = IDMAP_ERR_INTERNAL; 9814520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 9824520Snw141292 goto out; 9834520Snw141292 } 9844520Snw141292 9855696Snw141292 9866017Snw141292 retcode = sql_exec_no_cb(db, IDMAP_DBNAME, sql); 9874520Snw141292 9884520Snw141292 out: 9895696Snw141292 if (expr != NULL) 9905696Snw141292 sqlite_freemem(expr); 9914864Sbaban if (sql != NULL) 9924520Snw141292 sqlite_freemem(sql); 9934520Snw141292 return (retcode); 9944520Snw141292 } 9954520Snw141292 9964520Snw141292 /* 9974520Snw141292 * Compile the given SQL query and step just once. 9984520Snw141292 * 9994520Snw141292 * Input: 10004520Snw141292 * db - db handle 10014520Snw141292 * sql - SQL statement 10024520Snw141292 * 10034520Snw141292 * Output: 10044520Snw141292 * vm - virtual SQL machine 10054520Snw141292 * ncol - number of columns in the result 10064520Snw141292 * values - column values 10074520Snw141292 * 10084520Snw141292 * Return values: 10094520Snw141292 * IDMAP_SUCCESS 10104520Snw141292 * IDMAP_ERR_NOTFOUND 10114520Snw141292 * IDMAP_ERR_INTERNAL 10124520Snw141292 */ 10134520Snw141292 10145696Snw141292 static 10155696Snw141292 idmap_retcode 10164520Snw141292 sql_compile_n_step_once(sqlite *db, char *sql, sqlite_vm **vm, int *ncol, 10175696Snw141292 int reqcol, const char ***values) 10185696Snw141292 { 10194520Snw141292 char *errmsg = NULL; 10204884Sjp151216 int r; 10214884Sjp151216 10224884Sjp151216 if ((r = sqlite_compile(db, sql, NULL, vm, &errmsg)) != SQLITE_OK) { 10235696Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 10245696Snw141292 CHECK_NULL(errmsg)); 10254520Snw141292 sqlite_freemem(errmsg); 10264520Snw141292 return (IDMAP_ERR_INTERNAL); 10274520Snw141292 } 10284520Snw141292 10294884Sjp151216 r = sqlite_step(*vm, ncol, values, NULL); 10304884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 10314884Sjp151216 10324884Sjp151216 if (r == SQLITE_ROW) { 10334864Sbaban if (ncol != NULL && *ncol < reqcol) { 10344520Snw141292 (void) sqlite_finalize(*vm, NULL); 10354520Snw141292 *vm = NULL; 10364520Snw141292 return (IDMAP_ERR_INTERNAL); 10374520Snw141292 } 10384520Snw141292 /* Caller will call finalize after using the results */ 10394520Snw141292 return (IDMAP_SUCCESS); 10404520Snw141292 } else if (r == SQLITE_DONE) { 10414520Snw141292 (void) sqlite_finalize(*vm, NULL); 10424520Snw141292 *vm = NULL; 10434520Snw141292 return (IDMAP_ERR_NOTFOUND); 10444520Snw141292 } 10454520Snw141292 10464520Snw141292 (void) sqlite_finalize(*vm, &errmsg); 10474520Snw141292 *vm = NULL; 10485696Snw141292 idmapdlog(LOG_ERR, "Database error during %s (%s)", sql, 10495696Snw141292 CHECK_NULL(errmsg)); 10504520Snw141292 sqlite_freemem(errmsg); 10514520Snw141292 return (IDMAP_ERR_INTERNAL); 10524520Snw141292 } 10534520Snw141292 10544864Sbaban /* 10556616Sdm199847 * Load config in the state. 10565731Sbaban * 10576616Sdm199847 * nm_siduid and nm_sidgid fields: 10585731Sbaban * state->nm_siduid represents mode used by sid2uid and uid2sid 10595731Sbaban * requests for directory-based name mappings. Similarly, 10605731Sbaban * state->nm_sidgid represents mode used by sid2gid and gid2sid 10615731Sbaban * requests. 10625731Sbaban * 10635731Sbaban * sid2uid/uid2sid: 106410504SKeyur.Desai@Sun.COM * none -> directory_based_mapping != DIRECTORY_MAPPING_NAME 10655731Sbaban * AD-mode -> !nldap_winname_attr && ad_unixuser_attr 10665731Sbaban * nldap-mode -> nldap_winname_attr && !ad_unixuser_attr 10675731Sbaban * mixed-mode -> nldap_winname_attr && ad_unixuser_attr 10685731Sbaban * 10695731Sbaban * sid2gid/gid2sid: 107010504SKeyur.Desai@Sun.COM * none -> directory_based_mapping != DIRECTORY_MAPPING_NAME 10715731Sbaban * AD-mode -> !nldap_winname_attr && ad_unixgroup_attr 10725731Sbaban * nldap-mode -> nldap_winname_attr && !ad_unixgroup_attr 10735731Sbaban * mixed-mode -> nldap_winname_attr && ad_unixgroup_attr 10745731Sbaban */ 10755731Sbaban idmap_retcode 10766616Sdm199847 load_cfg_in_state(lookup_state_t *state) 10775731Sbaban { 10785731Sbaban state->nm_siduid = IDMAP_NM_NONE; 10795731Sbaban state->nm_sidgid = IDMAP_NM_NONE; 10805731Sbaban RDLOCK_CONFIG(); 10816616Sdm199847 10827031Snw141292 state->eph_map_unres_sids = 0; 10837031Snw141292 if (_idmapdstate.cfg->pgcfg.eph_map_unres_sids) 10847031Snw141292 state->eph_map_unres_sids = 1; 10857031Snw141292 108610504SKeyur.Desai@Sun.COM state->directory_based_mapping = 108710504SKeyur.Desai@Sun.COM _idmapdstate.cfg->pgcfg.directory_based_mapping; 108810504SKeyur.Desai@Sun.COM 10896616Sdm199847 if (_idmapdstate.cfg->pgcfg.default_domain != NULL) { 10906616Sdm199847 state->defdom = 10916616Sdm199847 strdup(_idmapdstate.cfg->pgcfg.default_domain); 10926616Sdm199847 if (state->defdom == NULL) { 10936616Sdm199847 UNLOCK_CONFIG(); 10946616Sdm199847 return (IDMAP_ERR_MEMORY); 10956616Sdm199847 } 10966616Sdm199847 } else { 10976616Sdm199847 UNLOCK_CONFIG(); 10986813Sdm199847 return (IDMAP_SUCCESS); 10996616Sdm199847 } 110010504SKeyur.Desai@Sun.COM 110110504SKeyur.Desai@Sun.COM if (_idmapdstate.cfg->pgcfg.directory_based_mapping != 110210504SKeyur.Desai@Sun.COM DIRECTORY_MAPPING_NAME) { 11035731Sbaban UNLOCK_CONFIG(); 11045731Sbaban return (IDMAP_SUCCESS); 11055731Sbaban } 110610504SKeyur.Desai@Sun.COM 11075731Sbaban if (_idmapdstate.cfg->pgcfg.nldap_winname_attr != NULL) { 11085731Sbaban state->nm_siduid = 11095731Sbaban (_idmapdstate.cfg->pgcfg.ad_unixuser_attr != NULL) 11105731Sbaban ? IDMAP_NM_MIXED : IDMAP_NM_NLDAP; 11115731Sbaban state->nm_sidgid = 11125731Sbaban (_idmapdstate.cfg->pgcfg.ad_unixgroup_attr != NULL) 11135731Sbaban ? IDMAP_NM_MIXED : IDMAP_NM_NLDAP; 11145731Sbaban } else { 11155731Sbaban state->nm_siduid = 11165731Sbaban (_idmapdstate.cfg->pgcfg.ad_unixuser_attr != NULL) 11175731Sbaban ? IDMAP_NM_AD : IDMAP_NM_NONE; 11185731Sbaban state->nm_sidgid = 11195731Sbaban (_idmapdstate.cfg->pgcfg.ad_unixgroup_attr != NULL) 11205731Sbaban ? IDMAP_NM_AD : IDMAP_NM_NONE; 11215731Sbaban } 11225731Sbaban if (_idmapdstate.cfg->pgcfg.ad_unixuser_attr != NULL) { 11235731Sbaban state->ad_unixuser_attr = 11245731Sbaban strdup(_idmapdstate.cfg->pgcfg.ad_unixuser_attr); 11255731Sbaban if (state->ad_unixuser_attr == NULL) { 11265731Sbaban UNLOCK_CONFIG(); 11275731Sbaban return (IDMAP_ERR_MEMORY); 11285731Sbaban } 11295731Sbaban } 11305731Sbaban if (_idmapdstate.cfg->pgcfg.ad_unixgroup_attr != NULL) { 11315731Sbaban state->ad_unixgroup_attr = 11325731Sbaban strdup(_idmapdstate.cfg->pgcfg.ad_unixgroup_attr); 11335731Sbaban if (state->ad_unixgroup_attr == NULL) { 11345731Sbaban UNLOCK_CONFIG(); 11355731Sbaban return (IDMAP_ERR_MEMORY); 11365731Sbaban } 11375731Sbaban } 11386616Sdm199847 if (_idmapdstate.cfg->pgcfg.nldap_winname_attr != NULL) { 11396616Sdm199847 state->nldap_winname_attr = 11406616Sdm199847 strdup(_idmapdstate.cfg->pgcfg.nldap_winname_attr); 11416616Sdm199847 if (state->nldap_winname_attr == NULL) { 11426616Sdm199847 UNLOCK_CONFIG(); 11436616Sdm199847 return (IDMAP_ERR_MEMORY); 11446616Sdm199847 } 11456616Sdm199847 } 11465731Sbaban UNLOCK_CONFIG(); 11475731Sbaban return (IDMAP_SUCCESS); 11485731Sbaban } 11495731Sbaban 11505731Sbaban /* 11519422SAfshin.Ardakani@Sun.COM * Set the rule with specified values. 11526386Sjp151216 * All the strings are copied. 11536386Sjp151216 */ 11546386Sjp151216 static void 11556386Sjp151216 idmap_namerule_set(idmap_namerule *rule, const char *windomain, 11566386Sjp151216 const char *winname, const char *unixname, boolean_t is_user, 11576386Sjp151216 boolean_t is_wuser, boolean_t is_nt4, int direction) 11586386Sjp151216 { 11596386Sjp151216 /* 11606386Sjp151216 * Only update if they differ because we have to free 11616386Sjp151216 * and duplicate the strings 11626386Sjp151216 */ 11636386Sjp151216 if (rule->windomain == NULL || windomain == NULL || 11646386Sjp151216 strcmp(rule->windomain, windomain) != 0) { 11656386Sjp151216 if (rule->windomain != NULL) { 11666386Sjp151216 free(rule->windomain); 11676386Sjp151216 rule->windomain = NULL; 11686386Sjp151216 } 11696386Sjp151216 if (windomain != NULL) 11706386Sjp151216 rule->windomain = strdup(windomain); 11716386Sjp151216 } 11726386Sjp151216 11736386Sjp151216 if (rule->winname == NULL || winname == NULL || 11746386Sjp151216 strcmp(rule->winname, winname) != 0) { 11756386Sjp151216 if (rule->winname != NULL) { 11766386Sjp151216 free(rule->winname); 11776386Sjp151216 rule->winname = NULL; 11786386Sjp151216 } 11796386Sjp151216 if (winname != NULL) 11806386Sjp151216 rule->winname = strdup(winname); 11816386Sjp151216 } 11826386Sjp151216 11836386Sjp151216 if (rule->unixname == NULL || unixname == NULL || 11846386Sjp151216 strcmp(rule->unixname, unixname) != 0) { 11856386Sjp151216 if (rule->unixname != NULL) { 11866386Sjp151216 free(rule->unixname); 11876386Sjp151216 rule->unixname = NULL; 11886386Sjp151216 } 11896386Sjp151216 if (unixname != NULL) 11906386Sjp151216 rule->unixname = strdup(unixname); 11916386Sjp151216 } 11926386Sjp151216 11936386Sjp151216 rule->is_user = is_user; 11946386Sjp151216 rule->is_wuser = is_wuser; 11956386Sjp151216 rule->is_nt4 = is_nt4; 11966386Sjp151216 rule->direction = direction; 11976386Sjp151216 } 11986386Sjp151216 11995731Sbaban /* 12005731Sbaban * Lookup well-known SIDs table either by winname or by SID. 12019422SAfshin.Ardakani@Sun.COM * 12029422SAfshin.Ardakani@Sun.COM * If the given winname or SID is a well-known SID then we set is_wksid 12035731Sbaban * variable and then proceed to see if the SID has a hard mapping to 12045731Sbaban * a particular UID/GID (Ex: Creator Owner/Creator Group mapped to 12059422SAfshin.Ardakani@Sun.COM * fixed ephemeral ids). The direction flag indicates whether we have 12069422SAfshin.Ardakani@Sun.COM * a mapping; UNDEF indicates that we do not. 12079422SAfshin.Ardakani@Sun.COM * 12089422SAfshin.Ardakani@Sun.COM * If we find a mapping then we return success, except for the 12099422SAfshin.Ardakani@Sun.COM * special case of SENTINEL_PID which indicates an inhibited mapping. 12109422SAfshin.Ardakani@Sun.COM * 12119422SAfshin.Ardakani@Sun.COM * If we find a matching entry, but no mapping, we supply SID, name, and type 12129422SAfshin.Ardakani@Sun.COM * information and return "not found". Higher layers will probably 12139422SAfshin.Ardakani@Sun.COM * do ephemeral mapping. 12149422SAfshin.Ardakani@Sun.COM * 12159422SAfshin.Ardakani@Sun.COM * If we do not find a match, we return "not found" and leave the question 12169422SAfshin.Ardakani@Sun.COM * to higher layers. 12175731Sbaban */ 12185696Snw141292 static 12195696Snw141292 idmap_retcode 12209422SAfshin.Ardakani@Sun.COM lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res, int *is_wksid) 12215696Snw141292 { 12229422SAfshin.Ardakani@Sun.COM const wksids_table_t *wksid; 12239422SAfshin.Ardakani@Sun.COM 12249422SAfshin.Ardakani@Sun.COM *is_wksid = 0; 12259422SAfshin.Ardakani@Sun.COM 12269422SAfshin.Ardakani@Sun.COM assert(req->id1.idmap_id_u.sid.prefix != NULL || 12279422SAfshin.Ardakani@Sun.COM req->id1name != NULL); 12289422SAfshin.Ardakani@Sun.COM 12299422SAfshin.Ardakani@Sun.COM if (req->id1.idmap_id_u.sid.prefix != NULL) { 12309422SAfshin.Ardakani@Sun.COM wksid = find_wksid_by_sid(req->id1.idmap_id_u.sid.prefix, 12319422SAfshin.Ardakani@Sun.COM req->id1.idmap_id_u.sid.rid, res->id.idtype); 12329422SAfshin.Ardakani@Sun.COM } else { 12339422SAfshin.Ardakani@Sun.COM wksid = find_wksid_by_name(req->id1name, req->id1domain, 12349422SAfshin.Ardakani@Sun.COM res->id.idtype); 12359422SAfshin.Ardakani@Sun.COM } 12369422SAfshin.Ardakani@Sun.COM if (wksid == NULL) 12379422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOTFOUND); 12389422SAfshin.Ardakani@Sun.COM 12399422SAfshin.Ardakani@Sun.COM /* Found matching entry. */ 12409422SAfshin.Ardakani@Sun.COM 12419422SAfshin.Ardakani@Sun.COM /* Fill in name if it was not already there. */ 12429422SAfshin.Ardakani@Sun.COM if (req->id1name == NULL) { 12439422SAfshin.Ardakani@Sun.COM req->id1name = strdup(wksid->winname); 12449422SAfshin.Ardakani@Sun.COM if (req->id1name == NULL) 12459422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_MEMORY); 12469422SAfshin.Ardakani@Sun.COM } 12479422SAfshin.Ardakani@Sun.COM 12489422SAfshin.Ardakani@Sun.COM /* Fill in SID if it was not already there */ 12499422SAfshin.Ardakani@Sun.COM if (req->id1.idmap_id_u.sid.prefix == NULL) { 12509422SAfshin.Ardakani@Sun.COM if (wksid->sidprefix != NULL) { 12515731Sbaban req->id1.idmap_id_u.sid.prefix = 12529422SAfshin.Ardakani@Sun.COM strdup(wksid->sidprefix); 12539422SAfshin.Ardakani@Sun.COM } else { 12549422SAfshin.Ardakani@Sun.COM RDLOCK_CONFIG(); 12559422SAfshin.Ardakani@Sun.COM req->id1.idmap_id_u.sid.prefix = 12569422SAfshin.Ardakani@Sun.COM strdup(_idmapdstate.cfg->pgcfg.machine_sid); 12579422SAfshin.Ardakani@Sun.COM UNLOCK_CONFIG(); 12589422SAfshin.Ardakani@Sun.COM } 12599422SAfshin.Ardakani@Sun.COM if (req->id1.idmap_id_u.sid.prefix == NULL) 12609422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_MEMORY); 12619422SAfshin.Ardakani@Sun.COM req->id1.idmap_id_u.sid.rid = wksid->rid; 12629422SAfshin.Ardakani@Sun.COM } 12639422SAfshin.Ardakani@Sun.COM 12649422SAfshin.Ardakani@Sun.COM /* Fill in the canonical domain if not already there */ 12659422SAfshin.Ardakani@Sun.COM if (req->id1domain == NULL) { 12669422SAfshin.Ardakani@Sun.COM const char *dom; 12679422SAfshin.Ardakani@Sun.COM 12689422SAfshin.Ardakani@Sun.COM RDLOCK_CONFIG(); 12699422SAfshin.Ardakani@Sun.COM if (wksid->domain != NULL) { 12709422SAfshin.Ardakani@Sun.COM dom = wksid->domain; 12719422SAfshin.Ardakani@Sun.COM } else { 12729422SAfshin.Ardakani@Sun.COM dom = _idmapdstate.hostname; 12735731Sbaban } 12749422SAfshin.Ardakani@Sun.COM req->id1domain = strdup(dom); 12759422SAfshin.Ardakani@Sun.COM UNLOCK_CONFIG(); 12769422SAfshin.Ardakani@Sun.COM if (req->id1domain == NULL) 12779422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_MEMORY); 12789422SAfshin.Ardakani@Sun.COM } 12799422SAfshin.Ardakani@Sun.COM 12809422SAfshin.Ardakani@Sun.COM *is_wksid = 1; 12819422SAfshin.Ardakani@Sun.COM req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE; 12829422SAfshin.Ardakani@Sun.COM 12839422SAfshin.Ardakani@Sun.COM req->id1.idtype = wksid->is_wuser ? IDMAP_USID : IDMAP_GSID; 12849422SAfshin.Ardakani@Sun.COM 12859422SAfshin.Ardakani@Sun.COM if (res->id.idtype == IDMAP_POSIXID) { 12869422SAfshin.Ardakani@Sun.COM res->id.idtype = wksid->is_wuser ? IDMAP_UID : IDMAP_GID; 12879422SAfshin.Ardakani@Sun.COM } 12889422SAfshin.Ardakani@Sun.COM 12899422SAfshin.Ardakani@Sun.COM if (wksid->direction == IDMAP_DIRECTION_UNDEF) { 12909422SAfshin.Ardakani@Sun.COM /* 12919422SAfshin.Ardakani@Sun.COM * We don't have a mapping 12929422SAfshin.Ardakani@Sun.COM * (But note that we may have supplied SID, name, or type 12939422SAfshin.Ardakani@Sun.COM * information.) 12949422SAfshin.Ardakani@Sun.COM */ 12959422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOTFOUND); 12964520Snw141292 } 12979422SAfshin.Ardakani@Sun.COM 12989422SAfshin.Ardakani@Sun.COM /* 12999422SAfshin.Ardakani@Sun.COM * We have an explicit mapping. 13009422SAfshin.Ardakani@Sun.COM */ 13019422SAfshin.Ardakani@Sun.COM if (wksid->pid == SENTINEL_PID) { 13029422SAfshin.Ardakani@Sun.COM /* 13039422SAfshin.Ardakani@Sun.COM * ... which is that mapping is inhibited. 13049422SAfshin.Ardakani@Sun.COM */ 13059422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOMAPPING); 13069422SAfshin.Ardakani@Sun.COM } 13079422SAfshin.Ardakani@Sun.COM 13089422SAfshin.Ardakani@Sun.COM switch (res->id.idtype) { 13099422SAfshin.Ardakani@Sun.COM case IDMAP_UID: 13109422SAfshin.Ardakani@Sun.COM res->id.idmap_id_u.uid = wksid->pid; 13119422SAfshin.Ardakani@Sun.COM break; 13129422SAfshin.Ardakani@Sun.COM case IDMAP_GID: 13139422SAfshin.Ardakani@Sun.COM res->id.idmap_id_u.gid = wksid->pid; 13149422SAfshin.Ardakani@Sun.COM break; 13159422SAfshin.Ardakani@Sun.COM default: 13169422SAfshin.Ardakani@Sun.COM /* IDMAP_POSIXID is eliminated above */ 13179422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOTSUPPORTED); 13189422SAfshin.Ardakani@Sun.COM } 13199422SAfshin.Ardakani@Sun.COM 13209422SAfshin.Ardakani@Sun.COM res->direction = wksid->direction; 13219422SAfshin.Ardakani@Sun.COM res->info.how.map_type = IDMAP_MAP_TYPE_KNOWN_SID; 13229422SAfshin.Ardakani@Sun.COM res->info.src = IDMAP_MAP_SRC_HARD_CODED; 13239422SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS); 13244520Snw141292 } 13254520Snw141292 13265696Snw141292 13279422SAfshin.Ardakani@Sun.COM /* 13289422SAfshin.Ardakani@Sun.COM * Look for an entry mapping a PID to a SID. 13299422SAfshin.Ardakani@Sun.COM * 13309422SAfshin.Ardakani@Sun.COM * Note that direction=UNDEF entries do not specify a mapping, 13319422SAfshin.Ardakani@Sun.COM * and that SENTINEL_PID entries represent either an inhibited 13329422SAfshin.Ardakani@Sun.COM * mapping or an ephemeral mapping. We don't handle either here; 13339422SAfshin.Ardakani@Sun.COM * they are filtered out by find_wksid_by_pid. 13349422SAfshin.Ardakani@Sun.COM */ 13355696Snw141292 static 13365696Snw141292 idmap_retcode 13375696Snw141292 lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) 13385696Snw141292 { 13399422SAfshin.Ardakani@Sun.COM const wksids_table_t *wksid; 13409422SAfshin.Ardakani@Sun.COM 13419422SAfshin.Ardakani@Sun.COM wksid = find_wksid_by_pid(req->id1.idmap_id_u.uid, is_user); 13429422SAfshin.Ardakani@Sun.COM if (wksid == NULL) 13435731Sbaban return (IDMAP_ERR_NOTFOUND); 13449422SAfshin.Ardakani@Sun.COM 13459422SAfshin.Ardakani@Sun.COM if (res->id.idtype == IDMAP_SID) { 13469422SAfshin.Ardakani@Sun.COM res->id.idtype = wksid->is_wuser ? IDMAP_USID : IDMAP_GSID; 13479422SAfshin.Ardakani@Sun.COM } 13489422SAfshin.Ardakani@Sun.COM res->id.idmap_id_u.sid.rid = wksid->rid; 13499422SAfshin.Ardakani@Sun.COM 13509422SAfshin.Ardakani@Sun.COM if (wksid->sidprefix != NULL) { 13519422SAfshin.Ardakani@Sun.COM res->id.idmap_id_u.sid.prefix = 13529422SAfshin.Ardakani@Sun.COM strdup(wksid->sidprefix); 13539422SAfshin.Ardakani@Sun.COM } else { 13549422SAfshin.Ardakani@Sun.COM RDLOCK_CONFIG(); 13559422SAfshin.Ardakani@Sun.COM res->id.idmap_id_u.sid.prefix = 13569422SAfshin.Ardakani@Sun.COM strdup(_idmapdstate.cfg->pgcfg.machine_sid); 13579422SAfshin.Ardakani@Sun.COM UNLOCK_CONFIG(); 13589422SAfshin.Ardakani@Sun.COM } 13599422SAfshin.Ardakani@Sun.COM 13609422SAfshin.Ardakani@Sun.COM if (res->id.idmap_id_u.sid.prefix == NULL) { 13619422SAfshin.Ardakani@Sun.COM idmapdlog(LOG_ERR, "Out of memory"); 13629422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_MEMORY); 13634864Sbaban } 13649422SAfshin.Ardakani@Sun.COM 13659422SAfshin.Ardakani@Sun.COM res->direction = wksid->direction; 13669422SAfshin.Ardakani@Sun.COM res->info.how.map_type = IDMAP_MAP_TYPE_KNOWN_SID; 13679422SAfshin.Ardakani@Sun.COM res->info.src = IDMAP_MAP_SRC_HARD_CODED; 13689422SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS); 13694864Sbaban } 13704864Sbaban 13719422SAfshin.Ardakani@Sun.COM /* 13729422SAfshin.Ardakani@Sun.COM * Look up a name in the wksids list, matching name and, if supplied, domain, 13739422SAfshin.Ardakani@Sun.COM * and extract data. 13749422SAfshin.Ardakani@Sun.COM * 13759422SAfshin.Ardakani@Sun.COM * Given: 13769422SAfshin.Ardakani@Sun.COM * name Windows user name 13779422SAfshin.Ardakani@Sun.COM * domain Windows domain name (or NULL) 13789422SAfshin.Ardakani@Sun.COM * 13799422SAfshin.Ardakani@Sun.COM * Return: Error code 13809422SAfshin.Ardakani@Sun.COM * 13819422SAfshin.Ardakani@Sun.COM * *canonname canonical name (if canonname non-NULL) [1] 13829422SAfshin.Ardakani@Sun.COM * *canondomain canonical domain (if canondomain non-NULL) [1] 13839422SAfshin.Ardakani@Sun.COM * *sidprefix SID prefix (if sidprefix non-NULL) [1] 13849422SAfshin.Ardakani@Sun.COM * *rid RID (if rid non-NULL) [2] 13859422SAfshin.Ardakani@Sun.COM * *type Type (if type non-NULL) [2] 13869422SAfshin.Ardakani@Sun.COM * 13879422SAfshin.Ardakani@Sun.COM * [1] malloc'ed, NULL on error 13889422SAfshin.Ardakani@Sun.COM * [2] Undefined on error 13899422SAfshin.Ardakani@Sun.COM */ 13905696Snw141292 idmap_retcode 13919422SAfshin.Ardakani@Sun.COM lookup_wksids_name2sid( 13929422SAfshin.Ardakani@Sun.COM const char *name, 13939422SAfshin.Ardakani@Sun.COM const char *domain, 13949422SAfshin.Ardakani@Sun.COM char **canonname, 13959422SAfshin.Ardakani@Sun.COM char **canondomain, 13969422SAfshin.Ardakani@Sun.COM char **sidprefix, 13979422SAfshin.Ardakani@Sun.COM idmap_rid_t *rid, 13989422SAfshin.Ardakani@Sun.COM int *type) 13995696Snw141292 { 14009422SAfshin.Ardakani@Sun.COM const wksids_table_t *wksid; 14019422SAfshin.Ardakani@Sun.COM 14029422SAfshin.Ardakani@Sun.COM if (sidprefix != NULL) 14039422SAfshin.Ardakani@Sun.COM *sidprefix = NULL; 14049422SAfshin.Ardakani@Sun.COM if (canonname != NULL) 14059422SAfshin.Ardakani@Sun.COM *canonname = NULL; 14069422SAfshin.Ardakani@Sun.COM if (canondomain != NULL) 14079422SAfshin.Ardakani@Sun.COM *canondomain = NULL; 14089422SAfshin.Ardakani@Sun.COM 14099422SAfshin.Ardakani@Sun.COM wksid = find_wksid_by_name(name, domain, IDMAP_POSIXID); 14109422SAfshin.Ardakani@Sun.COM if (wksid == NULL) 14119422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOTFOUND); 14129422SAfshin.Ardakani@Sun.COM 14139422SAfshin.Ardakani@Sun.COM if (sidprefix != NULL) { 14149422SAfshin.Ardakani@Sun.COM if (wksid->sidprefix != NULL) { 14159422SAfshin.Ardakani@Sun.COM *sidprefix = strdup(wksid->sidprefix); 14169422SAfshin.Ardakani@Sun.COM } else { 14179422SAfshin.Ardakani@Sun.COM RDLOCK_CONFIG(); 14189422SAfshin.Ardakani@Sun.COM *sidprefix = strdup( 14199422SAfshin.Ardakani@Sun.COM _idmapdstate.cfg->pgcfg.machine_sid); 14209422SAfshin.Ardakani@Sun.COM UNLOCK_CONFIG(); 14215731Sbaban } 14229422SAfshin.Ardakani@Sun.COM if (*sidprefix == NULL) 14239422SAfshin.Ardakani@Sun.COM goto nomem; 14249422SAfshin.Ardakani@Sun.COM } 14259422SAfshin.Ardakani@Sun.COM 14269422SAfshin.Ardakani@Sun.COM if (rid != NULL) 14279422SAfshin.Ardakani@Sun.COM *rid = wksid->rid; 14289422SAfshin.Ardakani@Sun.COM 14299422SAfshin.Ardakani@Sun.COM if (canonname != NULL) { 14309422SAfshin.Ardakani@Sun.COM *canonname = strdup(wksid->winname); 14319422SAfshin.Ardakani@Sun.COM if (*canonname == NULL) 14329422SAfshin.Ardakani@Sun.COM goto nomem; 14339422SAfshin.Ardakani@Sun.COM } 14349422SAfshin.Ardakani@Sun.COM 14359422SAfshin.Ardakani@Sun.COM if (canondomain != NULL) { 14369422SAfshin.Ardakani@Sun.COM if (wksid->domain != NULL) { 14379422SAfshin.Ardakani@Sun.COM *canondomain = strdup(wksid->domain); 14389422SAfshin.Ardakani@Sun.COM } else { 14399422SAfshin.Ardakani@Sun.COM RDLOCK_CONFIG(); 14409422SAfshin.Ardakani@Sun.COM *canondomain = strdup(_idmapdstate.hostname); 14419422SAfshin.Ardakani@Sun.COM UNLOCK_CONFIG(); 14424520Snw141292 } 14439422SAfshin.Ardakani@Sun.COM if (*canondomain == NULL) 14449422SAfshin.Ardakani@Sun.COM goto nomem; 14454520Snw141292 } 14469422SAfshin.Ardakani@Sun.COM 14479422SAfshin.Ardakani@Sun.COM if (type != NULL) 14489422SAfshin.Ardakani@Sun.COM *type = (wksid->is_wuser) ? 14499422SAfshin.Ardakani@Sun.COM _IDMAP_T_USER : _IDMAP_T_GROUP; 14509422SAfshin.Ardakani@Sun.COM 14519422SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS); 14529422SAfshin.Ardakani@Sun.COM 14539422SAfshin.Ardakani@Sun.COM nomem: 14549422SAfshin.Ardakani@Sun.COM idmapdlog(LOG_ERR, "Out of memory"); 14559422SAfshin.Ardakani@Sun.COM 14569422SAfshin.Ardakani@Sun.COM if (sidprefix != NULL) { 14579422SAfshin.Ardakani@Sun.COM free(*sidprefix); 14589422SAfshin.Ardakani@Sun.COM *sidprefix = NULL; 14599422SAfshin.Ardakani@Sun.COM } 14609422SAfshin.Ardakani@Sun.COM 14619422SAfshin.Ardakani@Sun.COM if (canonname != NULL) { 14629422SAfshin.Ardakani@Sun.COM free(*canonname); 14639422SAfshin.Ardakani@Sun.COM *canonname = NULL; 14649422SAfshin.Ardakani@Sun.COM } 14659422SAfshin.Ardakani@Sun.COM 14669422SAfshin.Ardakani@Sun.COM if (canondomain != NULL) { 14679422SAfshin.Ardakani@Sun.COM free(*canondomain); 14689422SAfshin.Ardakani@Sun.COM *canondomain = NULL; 14699422SAfshin.Ardakani@Sun.COM } 14709422SAfshin.Ardakani@Sun.COM 14719422SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_MEMORY); 14724520Snw141292 } 14734520Snw141292 14745696Snw141292 static 14755696Snw141292 idmap_retcode 14765696Snw141292 lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) 14775696Snw141292 { 14784520Snw141292 char *end; 14794520Snw141292 char *sql = NULL; 14804520Snw141292 const char **values; 14814520Snw141292 sqlite_vm *vm = NULL; 14824520Snw141292 int ncol, is_user; 14834520Snw141292 uid_t pid; 14844520Snw141292 time_t curtime, exp; 14854520Snw141292 idmap_retcode retcode; 14865932Sbaban char *is_user_string, *lower_name; 14874520Snw141292 14884520Snw141292 /* Current time */ 14894520Snw141292 errno = 0; 14904520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 14915696Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 14925696Snw141292 strerror(errno)); 14934520Snw141292 retcode = IDMAP_ERR_INTERNAL; 14944520Snw141292 goto out; 14954520Snw141292 } 14964520Snw141292 14975731Sbaban switch (res->id.idtype) { 14985696Snw141292 case IDMAP_UID: 14995696Snw141292 is_user_string = "1"; 15005696Snw141292 break; 15015696Snw141292 case IDMAP_GID: 15025696Snw141292 is_user_string = "0"; 15035696Snw141292 break; 15045696Snw141292 case IDMAP_POSIXID: 15055696Snw141292 /* the non-diagonal mapping */ 15065696Snw141292 is_user_string = "is_wuser"; 15075696Snw141292 break; 15085696Snw141292 default: 15095696Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 15105696Snw141292 goto out; 15115696Snw141292 } 15125696Snw141292 15134520Snw141292 /* SQL to lookup the cache */ 15146386Sjp151216 15155731Sbaban if (req->id1.idmap_id_u.sid.prefix != NULL) { 15165731Sbaban sql = sqlite_mprintf("SELECT pid, is_user, expiration, " 15176386Sjp151216 "unixname, u2w, is_wuser, " 15186386Sjp151216 "map_type, map_dn, map_attr, map_value, " 15196386Sjp151216 "map_windomain, map_winname, map_unixname, map_is_nt4 " 15205731Sbaban "FROM idmap_cache WHERE is_user = %s AND " 15215731Sbaban "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 15225731Sbaban "(pid >= 2147483648 OR " 15235731Sbaban "(expiration = 0 OR expiration ISNULL OR " 15245731Sbaban "expiration > %d));", 15255731Sbaban is_user_string, req->id1.idmap_id_u.sid.prefix, 15265731Sbaban req->id1.idmap_id_u.sid.rid, curtime); 15275731Sbaban } else if (req->id1name != NULL) { 15285932Sbaban if ((lower_name = tolower_u8(req->id1name)) == NULL) 15295932Sbaban lower_name = req->id1name; 15305731Sbaban sql = sqlite_mprintf("SELECT pid, is_user, expiration, " 15316386Sjp151216 "unixname, u2w, is_wuser, " 15326386Sjp151216 "map_type, map_dn, map_attr, map_value, " 15336386Sjp151216 "map_windomain, map_winname, map_unixname, map_is_nt4 " 15345731Sbaban "FROM idmap_cache WHERE is_user = %s AND " 15355731Sbaban "winname = %Q AND windomain = %Q AND w2u = 1 AND " 15365731Sbaban "(pid >= 2147483648 OR " 15375731Sbaban "(expiration = 0 OR expiration ISNULL OR " 15385731Sbaban "expiration > %d));", 15396386Sjp151216 is_user_string, lower_name, req->id1domain, 15406386Sjp151216 curtime); 15415932Sbaban if (lower_name != req->id1name) 15425932Sbaban free(lower_name); 15435731Sbaban } else { 15445731Sbaban retcode = IDMAP_ERR_ARG; 15455731Sbaban goto out; 15465731Sbaban } 15474520Snw141292 if (sql == NULL) { 15484520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 15494520Snw141292 retcode = IDMAP_ERR_MEMORY; 15504520Snw141292 goto out; 15514520Snw141292 } 15526386Sjp151216 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 15536386Sjp151216 14, &values); 15544520Snw141292 sqlite_freemem(sql); 15554520Snw141292 15564520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 15574520Snw141292 goto out; 15584520Snw141292 } else if (retcode == IDMAP_SUCCESS) { 15594520Snw141292 /* sanity checks */ 15604520Snw141292 if (values[0] == NULL || values[1] == NULL) { 15614520Snw141292 retcode = IDMAP_ERR_CACHE; 15624520Snw141292 goto out; 15634520Snw141292 } 15644520Snw141292 15654520Snw141292 pid = strtoul(values[0], &end, 10); 15665731Sbaban is_user = strncmp(values[1], "0", 2) ? 1 : 0; 15674520Snw141292 15685696Snw141292 if (is_user) { 15695696Snw141292 res->id.idtype = IDMAP_UID; 15705696Snw141292 res->id.idmap_id_u.uid = pid; 15715696Snw141292 } else { 15725696Snw141292 res->id.idtype = IDMAP_GID; 15735696Snw141292 res->id.idmap_id_u.gid = pid; 15745696Snw141292 } 15755696Snw141292 15764520Snw141292 /* 15774520Snw141292 * We may have an expired ephemeral mapping. Consider 15784520Snw141292 * the expired entry as valid if we are not going to 15794520Snw141292 * perform name-based mapping. But do not renew the 15804520Snw141292 * expiration. 15814520Snw141292 * If we will be doing name-based mapping then store the 15824520Snw141292 * ephemeral pid in the result so that we can use it 15834520Snw141292 * if we end up doing dynamic mapping again. 15844520Snw141292 */ 15854520Snw141292 if (!DO_NOT_ALLOC_NEW_ID_MAPPING(req) && 15865696Snw141292 !AVOID_NAMESERVICE(req) && 15875696Snw141292 IS_EPHEMERAL(pid) && values[2] != NULL) { 15885696Snw141292 exp = strtoll(values[2], &end, 10); 15895696Snw141292 if (exp && exp <= curtime) { 15905696Snw141292 /* Store the ephemeral pid */ 15915696Snw141292 res->direction = IDMAP_DIRECTION_BI; 15925696Snw141292 req->direction |= is_user 15935696Snw141292 ? _IDMAP_F_EXP_EPH_UID 15945696Snw141292 : _IDMAP_F_EXP_EPH_GID; 15955696Snw141292 retcode = IDMAP_ERR_NOTFOUND; 15964520Snw141292 } 15974520Snw141292 } 15984520Snw141292 } 15994520Snw141292 16004520Snw141292 out: 16014520Snw141292 if (retcode == IDMAP_SUCCESS) { 16024864Sbaban if (values[4] != NULL) 16034520Snw141292 res->direction = 16044644Sbaban (strtol(values[4], &end, 10) == 0)? 16054644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 16064520Snw141292 else 16074644Sbaban res->direction = IDMAP_DIRECTION_W2U; 16084520Snw141292 16094864Sbaban if (values[3] != NULL) { 16105731Sbaban if (req->id2name != NULL) 16115731Sbaban free(req->id2name); 16125064Sdm199847 req->id2name = strdup(values[3]); 16135064Sdm199847 if (req->id2name == NULL) { 16144520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 16154520Snw141292 retcode = IDMAP_ERR_MEMORY; 16164520Snw141292 } 16174520Snw141292 } 16185731Sbaban 16195731Sbaban req->id1.idtype = strncmp(values[5], "0", 2) ? 16205731Sbaban IDMAP_USID : IDMAP_GSID; 16216386Sjp151216 16226386Sjp151216 if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { 16236386Sjp151216 res->info.src = IDMAP_MAP_SRC_CACHE; 16246386Sjp151216 res->info.how.map_type = strtoul(values[6], &end, 10); 16256386Sjp151216 switch (res->info.how.map_type) { 16266386Sjp151216 case IDMAP_MAP_TYPE_DS_AD: 16276386Sjp151216 res->info.how.idmap_how_u.ad.dn = 16286386Sjp151216 strdup(values[7]); 16296386Sjp151216 res->info.how.idmap_how_u.ad.attr = 16306386Sjp151216 strdup(values[8]); 16316386Sjp151216 res->info.how.idmap_how_u.ad.value = 16326386Sjp151216 strdup(values[9]); 16336386Sjp151216 break; 16346386Sjp151216 16356386Sjp151216 case IDMAP_MAP_TYPE_DS_NLDAP: 16366386Sjp151216 res->info.how.idmap_how_u.nldap.dn = 16376386Sjp151216 strdup(values[7]); 16386386Sjp151216 res->info.how.idmap_how_u.nldap.attr = 16396386Sjp151216 strdup(values[8]); 16406386Sjp151216 res->info.how.idmap_how_u.nldap.value = 16416386Sjp151216 strdup(values[9]); 16426386Sjp151216 break; 16436386Sjp151216 16446386Sjp151216 case IDMAP_MAP_TYPE_RULE_BASED: 16456386Sjp151216 res->info.how.idmap_how_u.rule.windomain = 16466386Sjp151216 strdup(values[10]); 16476386Sjp151216 res->info.how.idmap_how_u.rule.winname = 16486386Sjp151216 strdup(values[11]); 16496386Sjp151216 res->info.how.idmap_how_u.rule.unixname = 16506386Sjp151216 strdup(values[12]); 16516386Sjp151216 res->info.how.idmap_how_u.rule.is_nt4 = 16526386Sjp151216 strtoul(values[13], &end, 1); 16536386Sjp151216 res->info.how.idmap_how_u.rule.is_user = 16546386Sjp151216 is_user; 16556386Sjp151216 res->info.how.idmap_how_u.rule.is_wuser = 16566386Sjp151216 strtoul(values[5], &end, 1); 16576386Sjp151216 break; 16586386Sjp151216 16596386Sjp151216 case IDMAP_MAP_TYPE_EPHEMERAL: 16606386Sjp151216 break; 16616386Sjp151216 16626386Sjp151216 case IDMAP_MAP_TYPE_LOCAL_SID: 16636386Sjp151216 break; 16646386Sjp151216 16656386Sjp151216 case IDMAP_MAP_TYPE_KNOWN_SID: 16666386Sjp151216 break; 16676386Sjp151216 166810504SKeyur.Desai@Sun.COM case IDMAP_MAP_TYPE_IDMU: 166910504SKeyur.Desai@Sun.COM res->info.how.idmap_how_u.idmu.dn = 167010504SKeyur.Desai@Sun.COM strdup(values[7]); 167110504SKeyur.Desai@Sun.COM res->info.how.idmap_how_u.idmu.attr = 167210504SKeyur.Desai@Sun.COM strdup(values[8]); 167310504SKeyur.Desai@Sun.COM res->info.how.idmap_how_u.idmu.value = 167410504SKeyur.Desai@Sun.COM strdup(values[9]); 167510504SKeyur.Desai@Sun.COM break; 167610504SKeyur.Desai@Sun.COM 16776386Sjp151216 default: 167810504SKeyur.Desai@Sun.COM /* Unknown mapping type */ 16796386Sjp151216 assert(FALSE); 16806386Sjp151216 } 16816386Sjp151216 } 16824520Snw141292 } 16834864Sbaban if (vm != NULL) 16844520Snw141292 (void) sqlite_finalize(vm, NULL); 16854520Snw141292 return (retcode); 16864520Snw141292 } 16874520Snw141292 16885696Snw141292 static 16895696Snw141292 idmap_retcode 16904864Sbaban lookup_cache_sid2name(sqlite *cache, const char *sidprefix, idmap_rid_t rid, 16919422SAfshin.Ardakani@Sun.COM char **canonname, char **canondomain, int *type) 16925696Snw141292 { 16934520Snw141292 char *end; 16944520Snw141292 char *sql = NULL; 16954520Snw141292 const char **values; 16964520Snw141292 sqlite_vm *vm = NULL; 16974520Snw141292 int ncol; 16984520Snw141292 time_t curtime; 16994520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 17004520Snw141292 17014520Snw141292 /* Get current time */ 17024520Snw141292 errno = 0; 17034520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 17045696Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 17055696Snw141292 strerror(errno)); 17064520Snw141292 retcode = IDMAP_ERR_INTERNAL; 17074520Snw141292 goto out; 17084520Snw141292 } 17094520Snw141292 17104520Snw141292 /* SQL to lookup the cache */ 17115696Snw141292 sql = sqlite_mprintf("SELECT canon_name, domain, type " 17125696Snw141292 "FROM name_cache WHERE " 17135696Snw141292 "sidprefix = %Q AND rid = %u AND " 17145696Snw141292 "(expiration = 0 OR expiration ISNULL OR " 17155696Snw141292 "expiration > %d);", 17165696Snw141292 sidprefix, rid, curtime); 17174520Snw141292 if (sql == NULL) { 17184520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 17194520Snw141292 retcode = IDMAP_ERR_MEMORY; 17204520Snw141292 goto out; 17214520Snw141292 } 17224520Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 3, &values); 17234520Snw141292 sqlite_freemem(sql); 17244520Snw141292 17254520Snw141292 if (retcode == IDMAP_SUCCESS) { 17264864Sbaban if (type != NULL) { 17274520Snw141292 if (values[2] == NULL) { 17284520Snw141292 retcode = IDMAP_ERR_CACHE; 17294520Snw141292 goto out; 17304520Snw141292 } 17314520Snw141292 *type = strtol(values[2], &end, 10); 17324520Snw141292 } 17334520Snw141292 17349422SAfshin.Ardakani@Sun.COM if (canonname != NULL && values[0] != NULL) { 17359422SAfshin.Ardakani@Sun.COM if ((*canonname = strdup(values[0])) == NULL) { 17364520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 17374520Snw141292 retcode = IDMAP_ERR_MEMORY; 17384520Snw141292 goto out; 17394520Snw141292 } 17404520Snw141292 } 17414520Snw141292 17429422SAfshin.Ardakani@Sun.COM if (canondomain != NULL && values[1] != NULL) { 17439422SAfshin.Ardakani@Sun.COM if ((*canondomain = strdup(values[1])) == NULL) { 17449422SAfshin.Ardakani@Sun.COM if (canonname != NULL) { 17459422SAfshin.Ardakani@Sun.COM free(*canonname); 17469422SAfshin.Ardakani@Sun.COM *canonname = NULL; 17474520Snw141292 } 17484520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 17494520Snw141292 retcode = IDMAP_ERR_MEMORY; 17504520Snw141292 goto out; 17514520Snw141292 } 17524520Snw141292 } 17534520Snw141292 } 17544520Snw141292 17554520Snw141292 out: 17564864Sbaban if (vm != NULL) 17574520Snw141292 (void) sqlite_finalize(vm, NULL); 17584520Snw141292 return (retcode); 17594520Snw141292 } 17604520Snw141292 17614520Snw141292 /* 17625731Sbaban * Given SID, find winname using name_cache OR 17635731Sbaban * Given winname, find SID using name_cache. 17645731Sbaban * Used when mapping win to unix i.e. req->id1 is windows id and 17655731Sbaban * req->id2 is unix id 17664520Snw141292 */ 17675696Snw141292 static 17685696Snw141292 idmap_retcode 17695731Sbaban lookup_name_cache(sqlite *cache, idmap_mapping *req, idmap_id_res *res) 17705696Snw141292 { 17714520Snw141292 int type = -1; 17724520Snw141292 idmap_retcode retcode; 17735731Sbaban char *sidprefix = NULL; 17744520Snw141292 idmap_rid_t rid; 17754520Snw141292 char *name = NULL, *domain = NULL; 17764520Snw141292 17775731Sbaban /* Done if we've both sid and winname */ 17785731Sbaban if (req->id1.idmap_id_u.sid.prefix != NULL && req->id1name != NULL) 17795731Sbaban return (IDMAP_SUCCESS); 17805731Sbaban 17815731Sbaban if (req->id1.idmap_id_u.sid.prefix != NULL) { 17829422SAfshin.Ardakani@Sun.COM /* Lookup sid to winname */ 17835731Sbaban retcode = lookup_cache_sid2name(cache, 17845731Sbaban req->id1.idmap_id_u.sid.prefix, 17855731Sbaban req->id1.idmap_id_u.sid.rid, &name, &domain, &type); 17869422SAfshin.Ardakani@Sun.COM } else { 17879422SAfshin.Ardakani@Sun.COM /* Lookup winame to sid */ 17889422SAfshin.Ardakani@Sun.COM retcode = lookup_cache_name2sid(cache, req->id1name, 17899422SAfshin.Ardakani@Sun.COM req->id1domain, &name, &sidprefix, &rid, &type); 17905731Sbaban } 17915731Sbaban 17925731Sbaban if (retcode != IDMAP_SUCCESS) { 17935731Sbaban free(name); 17945731Sbaban free(domain); 17955731Sbaban free(sidprefix); 17965731Sbaban return (retcode); 17975731Sbaban } 17985731Sbaban 17995731Sbaban if (res->id.idtype == IDMAP_POSIXID) { 18005731Sbaban res->id.idtype = (type == _IDMAP_T_USER) ? 18015731Sbaban IDMAP_UID : IDMAP_GID; 18025731Sbaban } 18035731Sbaban req->id1.idtype = (type == _IDMAP_T_USER) ? 18045731Sbaban IDMAP_USID : IDMAP_GSID; 18055731Sbaban 18065731Sbaban req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE; 18079422SAfshin.Ardakani@Sun.COM 18089422SAfshin.Ardakani@Sun.COM /* 18099422SAfshin.Ardakani@Sun.COM * If we found canonical names or domain, use them instead of 18109422SAfshin.Ardakani@Sun.COM * the existing values. 18119422SAfshin.Ardakani@Sun.COM */ 18125731Sbaban if (name != NULL) { 18139422SAfshin.Ardakani@Sun.COM free(req->id1name); 18149422SAfshin.Ardakani@Sun.COM req->id1name = name; 18155731Sbaban } 18169422SAfshin.Ardakani@Sun.COM if (domain != NULL) { 18179422SAfshin.Ardakani@Sun.COM free(req->id1domain); 18185731Sbaban req->id1domain = domain; 18199422SAfshin.Ardakani@Sun.COM } 18209422SAfshin.Ardakani@Sun.COM 18215731Sbaban if (req->id1.idmap_id_u.sid.prefix == NULL) { 18225731Sbaban req->id1.idmap_id_u.sid.prefix = sidprefix; 18235731Sbaban req->id1.idmap_id_u.sid.rid = rid; 18244520Snw141292 } 18254520Snw141292 return (retcode); 18264520Snw141292 } 18274520Snw141292 18288361SJulian.Pullen@Sun.COM 18298361SJulian.Pullen@Sun.COM 18308361SJulian.Pullen@Sun.COM static int 18318361SJulian.Pullen@Sun.COM ad_lookup_batch_int(lookup_state_t *state, idmap_mapping_batch *batch, 183210504SKeyur.Desai@Sun.COM idmap_ids_res *result, adutils_ad_t *dir, int how_local, 183310504SKeyur.Desai@Sun.COM int *num_processed) 18345696Snw141292 { 18354520Snw141292 idmap_retcode retcode; 183610504SKeyur.Desai@Sun.COM int i, num_queued, is_wuser, is_user; 18378361SJulian.Pullen@Sun.COM int next_request; 18385731Sbaban int retries = 0, eunixtype; 18395731Sbaban char **unixname; 18404520Snw141292 idmap_mapping *req; 18414520Snw141292 idmap_id_res *res; 18425731Sbaban idmap_query_state_t *qs = NULL; 18436386Sjp151216 idmap_how *how; 18446616Sdm199847 char **dn, **attr, **value; 18455731Sbaban 18468361SJulian.Pullen@Sun.COM *num_processed = 0; 18478361SJulian.Pullen@Sun.COM 18485731Sbaban /* 18495731Sbaban * Since req->id2.idtype is unused, we will use it here 18505731Sbaban * to retrieve the value of sid_type. But it needs to be 18515731Sbaban * reset to IDMAP_NONE before we return to prevent xdr 18525731Sbaban * from mis-interpreting req->id2 when it tries to free 18535731Sbaban * the input argument. Other option is to allocate an 18545731Sbaban * array of integers and use it instead for the batched 18555731Sbaban * call. But why un-necessarily allocate memory. That may 18565731Sbaban * be an option if req->id2.idtype cannot be re-used in 18575731Sbaban * future. 185810504SKeyur.Desai@Sun.COM * 185910504SKeyur.Desai@Sun.COM * Similarly, we use req->id2.idmap_id_u.uid to return uidNumber 186010504SKeyur.Desai@Sun.COM * or gidNumber supplied by IDMU, and reset it back to SENTINEL_PID 186110504SKeyur.Desai@Sun.COM * when we're done. Note that the query always puts the result in 186210504SKeyur.Desai@Sun.COM * req->id2.idmap_id_u.uid, not .gid. 18635731Sbaban */ 18644520Snw141292 retry: 186510504SKeyur.Desai@Sun.COM retcode = idmap_lookup_batch_start(dir, state->ad_nqueries, 186610504SKeyur.Desai@Sun.COM state->directory_based_mapping, 186710504SKeyur.Desai@Sun.COM state->defdom, 186810504SKeyur.Desai@Sun.COM &qs); 18695731Sbaban if (retcode != IDMAP_SUCCESS) { 18708040SBaban.Kenkre@Sun.COM if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && 18718040SBaban.Kenkre@Sun.COM retries++ < ADUTILS_DEF_NUM_RETRIES) 18725968Snw141292 goto retry; 18736097Snw141292 degrade_svc(1, "failed to create batch for AD lookup"); 18748361SJulian.Pullen@Sun.COM goto out; 18754520Snw141292 } 18768361SJulian.Pullen@Sun.COM num_queued = 0; 18774520Snw141292 18785317Sjp151216 restore_svc(); 18795317Sjp151216 188010504SKeyur.Desai@Sun.COM if (how_local & FOREST_IS_LOCAL) { 18818361SJulian.Pullen@Sun.COM /* 18828361SJulian.Pullen@Sun.COM * Directory based name mapping is only performed within the 188310504SKeyur.Desai@Sun.COM * joined forest. We don't trust other "trusted" 18848361SJulian.Pullen@Sun.COM * forests to provide DS-based name mapping information because 18858361SJulian.Pullen@Sun.COM * AD's definition of "cross-forest trust" does not encompass 18868361SJulian.Pullen@Sun.COM * this sort of behavior. 18878361SJulian.Pullen@Sun.COM */ 18888361SJulian.Pullen@Sun.COM idmap_lookup_batch_set_unixattr(qs, 18898361SJulian.Pullen@Sun.COM state->ad_unixuser_attr, state->ad_unixgroup_attr); 18908361SJulian.Pullen@Sun.COM } 18918361SJulian.Pullen@Sun.COM 18928361SJulian.Pullen@Sun.COM for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 18934520Snw141292 req = &batch->idmap_mapping_batch_val[i]; 18944520Snw141292 res = &result->ids.ids_val[i]; 18956386Sjp151216 how = &res->info.how; 18966386Sjp151216 18975731Sbaban retcode = IDMAP_SUCCESS; 18985731Sbaban req->id2.idtype = IDMAP_NONE; 189910504SKeyur.Desai@Sun.COM req->id2.idmap_id_u.uid = SENTINEL_PID; 190010504SKeyur.Desai@Sun.COM 190110504SKeyur.Desai@Sun.COM /* Skip if no AD lookup required */ 190210504SKeyur.Desai@Sun.COM if (!(req->direction & _IDMAP_F_LOOKUP_AD)) 19035731Sbaban continue; 19045731Sbaban 190510504SKeyur.Desai@Sun.COM /* Skip if we've already tried and gotten a "not found" */ 190610504SKeyur.Desai@Sun.COM if (req->direction & _IDMAP_F_LOOKUP_OTHER_AD) 190710504SKeyur.Desai@Sun.COM continue; 190810504SKeyur.Desai@Sun.COM 190910504SKeyur.Desai@Sun.COM /* Skip if we've already either succeeded or failed */ 19106963Sbaban if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) 19115731Sbaban continue; 19125731Sbaban 19135731Sbaban if (IS_REQUEST_SID(*req, 1)) { 19146616Sdm199847 19156616Sdm199847 /* win2unix request: */ 19166616Sdm199847 191710504SKeyur.Desai@Sun.COM posix_id_t *pid = NULL; 19186616Sdm199847 unixname = dn = attr = value = NULL; 19195731Sbaban eunixtype = _IDMAP_T_UNDEF; 192010504SKeyur.Desai@Sun.COM if (state->directory_based_mapping == 192110504SKeyur.Desai@Sun.COM DIRECTORY_MAPPING_NAME && 192210504SKeyur.Desai@Sun.COM req->id2name == NULL) { 19235731Sbaban if (res->id.idtype == IDMAP_UID && 19245731Sbaban AD_OR_MIXED(state->nm_siduid)) { 19255731Sbaban eunixtype = _IDMAP_T_USER; 19265731Sbaban unixname = &req->id2name; 19275731Sbaban } else if (res->id.idtype == IDMAP_GID && 19285731Sbaban AD_OR_MIXED(state->nm_sidgid)) { 19295731Sbaban eunixtype = _IDMAP_T_GROUP; 19305731Sbaban unixname = &req->id2name; 19315731Sbaban } else if (AD_OR_MIXED(state->nm_siduid) || 19325731Sbaban AD_OR_MIXED(state->nm_sidgid)) { 19335731Sbaban unixname = &req->id2name; 19345731Sbaban } 193510504SKeyur.Desai@Sun.COM 193610504SKeyur.Desai@Sun.COM if (unixname != NULL) { 193710504SKeyur.Desai@Sun.COM /* 193810504SKeyur.Desai@Sun.COM * Get how info for DS-based name 193910504SKeyur.Desai@Sun.COM * mapping only if AD or MIXED 194010504SKeyur.Desai@Sun.COM * mode is enabled. 194110504SKeyur.Desai@Sun.COM */ 194210504SKeyur.Desai@Sun.COM idmap_info_free(&res->info); 194310504SKeyur.Desai@Sun.COM res->info.src = IDMAP_MAP_SRC_NEW; 194410504SKeyur.Desai@Sun.COM how->map_type = IDMAP_MAP_TYPE_DS_AD; 194510504SKeyur.Desai@Sun.COM dn = &how->idmap_how_u.ad.dn; 194610504SKeyur.Desai@Sun.COM attr = &how->idmap_how_u.ad.attr; 194710504SKeyur.Desai@Sun.COM value = &how->idmap_how_u.ad.value; 194810504SKeyur.Desai@Sun.COM } 194910504SKeyur.Desai@Sun.COM } else if (state->directory_based_mapping == 195010504SKeyur.Desai@Sun.COM DIRECTORY_MAPPING_IDMU && 195110504SKeyur.Desai@Sun.COM (how_local & DOMAIN_IS_LOCAL)) { 19526616Sdm199847 /* 195310504SKeyur.Desai@Sun.COM * Ensure that we only do IDMU processing 195410504SKeyur.Desai@Sun.COM * when querying the domain we've joined. 195510504SKeyur.Desai@Sun.COM */ 195610504SKeyur.Desai@Sun.COM pid = &req->id2.idmap_id_u.uid; 195710504SKeyur.Desai@Sun.COM /* 195810504SKeyur.Desai@Sun.COM * Get how info for IDMU based mapping. 19596616Sdm199847 */ 19606616Sdm199847 idmap_info_free(&res->info); 19616616Sdm199847 res->info.src = IDMAP_MAP_SRC_NEW; 196210504SKeyur.Desai@Sun.COM how->map_type = IDMAP_MAP_TYPE_IDMU; 196310504SKeyur.Desai@Sun.COM dn = &how->idmap_how_u.idmu.dn; 196410504SKeyur.Desai@Sun.COM attr = &how->idmap_how_u.idmu.attr; 196510504SKeyur.Desai@Sun.COM value = &how->idmap_how_u.idmu.value; 19666616Sdm199847 } 196710504SKeyur.Desai@Sun.COM 19686616Sdm199847 if (req->id1.idmap_id_u.sid.prefix != NULL) { 19696616Sdm199847 /* Lookup AD by SID */ 19706616Sdm199847 retcode = idmap_sid2name_batch_add1( 19716616Sdm199847 qs, req->id1.idmap_id_u.sid.prefix, 19726616Sdm199847 &req->id1.idmap_id_u.sid.rid, eunixtype, 19736616Sdm199847 dn, attr, value, 19746616Sdm199847 (req->id1name == NULL) ? 19756616Sdm199847 &req->id1name : NULL, 19766616Sdm199847 (req->id1domain == NULL) ? 19776616Sdm199847 &req->id1domain : NULL, 19786616Sdm199847 (int *)&req->id2.idtype, unixname, 197910504SKeyur.Desai@Sun.COM pid, 19806616Sdm199847 &res->retcode); 19818361SJulian.Pullen@Sun.COM if (retcode == IDMAP_SUCCESS) 19828361SJulian.Pullen@Sun.COM num_queued++; 19836616Sdm199847 } else { 19846616Sdm199847 /* Lookup AD by winname */ 19856616Sdm199847 assert(req->id1name != NULL); 19866616Sdm199847 retcode = idmap_name2sid_batch_add1( 19876616Sdm199847 qs, req->id1name, req->id1domain, 19886616Sdm199847 eunixtype, 19896616Sdm199847 dn, attr, value, 19906616Sdm199847 &req->id1name, 19916616Sdm199847 &req->id1.idmap_id_u.sid.prefix, 19926616Sdm199847 &req->id1.idmap_id_u.sid.rid, 19936616Sdm199847 (int *)&req->id2.idtype, unixname, 199410504SKeyur.Desai@Sun.COM pid, 19956616Sdm199847 &res->retcode); 19968361SJulian.Pullen@Sun.COM if (retcode == IDMAP_SUCCESS) 19978361SJulian.Pullen@Sun.COM num_queued++; 19986616Sdm199847 } 19995731Sbaban 20005731Sbaban } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) { 20016616Sdm199847 20026616Sdm199847 /* unix2win request: */ 20035731Sbaban 20045731Sbaban if (res->id.idmap_id_u.sid.prefix != NULL && 20055731Sbaban req->id2name != NULL) { 20068361SJulian.Pullen@Sun.COM /* Already have SID and winname. done */ 20075731Sbaban res->retcode = IDMAP_SUCCESS; 20085731Sbaban continue; 20095731Sbaban } 20105731Sbaban 20115731Sbaban if (res->id.idmap_id_u.sid.prefix != NULL) { 20125731Sbaban /* 20135731Sbaban * SID but no winname -- lookup AD by 20145731Sbaban * SID to get winname. 20156616Sdm199847 * how info is not needed here because 20166616Sdm199847 * we are not retrieving unixname from 20176616Sdm199847 * AD. 20185731Sbaban */ 20198361SJulian.Pullen@Sun.COM 20205731Sbaban retcode = idmap_sid2name_batch_add1( 20215731Sbaban qs, res->id.idmap_id_u.sid.prefix, 20225731Sbaban &res->id.idmap_id_u.sid.rid, 20236386Sjp151216 _IDMAP_T_UNDEF, 20246616Sdm199847 NULL, NULL, NULL, 20256386Sjp151216 &req->id2name, 20265731Sbaban &req->id2domain, (int *)&req->id2.idtype, 202710504SKeyur.Desai@Sun.COM NULL, NULL, &res->retcode); 20288361SJulian.Pullen@Sun.COM if (retcode == IDMAP_SUCCESS) 20298361SJulian.Pullen@Sun.COM num_queued++; 20305731Sbaban } else if (req->id2name != NULL) { 20315731Sbaban /* 20325731Sbaban * winname but no SID -- lookup AD by 20335731Sbaban * winname to get SID. 20346616Sdm199847 * how info is not needed here because 20356616Sdm199847 * we are not retrieving unixname from 20366616Sdm199847 * AD. 20375731Sbaban */ 20385731Sbaban retcode = idmap_name2sid_batch_add1( 20395731Sbaban qs, req->id2name, req->id2domain, 20406386Sjp151216 _IDMAP_T_UNDEF, 20416616Sdm199847 NULL, NULL, NULL, NULL, 20425731Sbaban &res->id.idmap_id_u.sid.prefix, 20435731Sbaban &res->id.idmap_id_u.sid.rid, 20445731Sbaban (int *)&req->id2.idtype, NULL, 204510504SKeyur.Desai@Sun.COM NULL, 20465731Sbaban &res->retcode); 20478361SJulian.Pullen@Sun.COM if (retcode == IDMAP_SUCCESS) 20488361SJulian.Pullen@Sun.COM num_queued++; 204910504SKeyur.Desai@Sun.COM } else if (state->directory_based_mapping == 205010504SKeyur.Desai@Sun.COM DIRECTORY_MAPPING_IDMU && 205110504SKeyur.Desai@Sun.COM (how_local & DOMAIN_IS_LOCAL)) { 205210504SKeyur.Desai@Sun.COM assert(req->id1.idmap_id_u.uid != SENTINEL_PID); 205310504SKeyur.Desai@Sun.COM is_user = IS_REQUEST_UID(*req); 205410504SKeyur.Desai@Sun.COM if (res->id.idtype == IDMAP_USID) 205510504SKeyur.Desai@Sun.COM is_wuser = 1; 205610504SKeyur.Desai@Sun.COM else if (res->id.idtype == IDMAP_GSID) 205710504SKeyur.Desai@Sun.COM is_wuser = 0; 205810504SKeyur.Desai@Sun.COM else 205910504SKeyur.Desai@Sun.COM is_wuser = is_user; 206010504SKeyur.Desai@Sun.COM 206110504SKeyur.Desai@Sun.COM /* IDMU can't do diagonal mappings */ 206210504SKeyur.Desai@Sun.COM if (is_user != is_wuser) 206310504SKeyur.Desai@Sun.COM continue; 206410504SKeyur.Desai@Sun.COM 206510504SKeyur.Desai@Sun.COM idmap_info_free(&res->info); 206610504SKeyur.Desai@Sun.COM res->info.src = IDMAP_MAP_SRC_NEW; 206710504SKeyur.Desai@Sun.COM how->map_type = IDMAP_MAP_TYPE_IDMU; 206810504SKeyur.Desai@Sun.COM retcode = idmap_pid2sid_batch_add1( 206910504SKeyur.Desai@Sun.COM qs, req->id1.idmap_id_u.uid, is_user, 207010504SKeyur.Desai@Sun.COM &how->idmap_how_u.ad.dn, 207110504SKeyur.Desai@Sun.COM &how->idmap_how_u.ad.attr, 207210504SKeyur.Desai@Sun.COM &how->idmap_how_u.ad.value, 207310504SKeyur.Desai@Sun.COM &res->id.idmap_id_u.sid.prefix, 207410504SKeyur.Desai@Sun.COM &res->id.idmap_id_u.sid.rid, 207510504SKeyur.Desai@Sun.COM &req->id2name, &req->id2domain, 207610504SKeyur.Desai@Sun.COM (int *)&req->id2.idtype, &res->retcode); 207710504SKeyur.Desai@Sun.COM if (retcode == IDMAP_SUCCESS) 207810504SKeyur.Desai@Sun.COM num_queued++; 20795731Sbaban } else if (req->id1name != NULL) { 20805731Sbaban /* 20818361SJulian.Pullen@Sun.COM * No SID and no winname but we've unixname. 20828361SJulian.Pullen@Sun.COM * Lookup AD by unixname to get SID. 20835731Sbaban */ 20845731Sbaban is_user = (IS_REQUEST_UID(*req)) ? 1 : 0; 20855731Sbaban if (res->id.idtype == IDMAP_USID) 20865731Sbaban is_wuser = 1; 20875731Sbaban else if (res->id.idtype == IDMAP_GSID) 20885731Sbaban is_wuser = 0; 20895731Sbaban else 20905731Sbaban is_wuser = is_user; 20918361SJulian.Pullen@Sun.COM 20926616Sdm199847 idmap_info_free(&res->info); 20936386Sjp151216 res->info.src = IDMAP_MAP_SRC_NEW; 20946386Sjp151216 how->map_type = IDMAP_MAP_TYPE_DS_AD; 20955731Sbaban retcode = idmap_unixname2sid_batch_add1( 20965731Sbaban qs, req->id1name, is_user, is_wuser, 20976386Sjp151216 &how->idmap_how_u.ad.dn, 20986386Sjp151216 &how->idmap_how_u.ad.attr, 20996386Sjp151216 &how->idmap_how_u.ad.value, 21005731Sbaban &res->id.idmap_id_u.sid.prefix, 21015731Sbaban &res->id.idmap_id_u.sid.rid, 21025731Sbaban &req->id2name, &req->id2domain, 21035731Sbaban (int *)&req->id2.idtype, &res->retcode); 21048361SJulian.Pullen@Sun.COM if (retcode == IDMAP_SUCCESS) 21058361SJulian.Pullen@Sun.COM num_queued++; 21065731Sbaban } 21075731Sbaban } 21088361SJulian.Pullen@Sun.COM 21098361SJulian.Pullen@Sun.COM if (retcode == IDMAP_ERR_DOMAIN_NOTFOUND) { 21108361SJulian.Pullen@Sun.COM req->direction |= _IDMAP_F_LOOKUP_OTHER_AD; 21118361SJulian.Pullen@Sun.COM retcode = IDMAP_SUCCESS; 21128361SJulian.Pullen@Sun.COM } else if (retcode != IDMAP_SUCCESS) { 21135731Sbaban break; 21144520Snw141292 } 21158361SJulian.Pullen@Sun.COM } /* End of for loop */ 21164520Snw141292 21176963Sbaban if (retcode == IDMAP_SUCCESS) { 21186963Sbaban /* add keeps track if we added an entry to the batch */ 21198361SJulian.Pullen@Sun.COM if (num_queued > 0) 21206963Sbaban retcode = idmap_lookup_batch_end(&qs); 21216963Sbaban else 21226963Sbaban idmap_lookup_release_batch(&qs); 212310504SKeyur.Desai@Sun.COM } else { 212410504SKeyur.Desai@Sun.COM idmap_lookup_release_batch(&qs); 212510504SKeyur.Desai@Sun.COM num_queued = 0; 212610504SKeyur.Desai@Sun.COM next_request = i + 1; 21276963Sbaban } 21285696Snw141292 21298040SBaban.Kenkre@Sun.COM if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && 21308040SBaban.Kenkre@Sun.COM retries++ < ADUTILS_DEF_NUM_RETRIES) 21314520Snw141292 goto retry; 21325317Sjp151216 else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 21336097Snw141292 degrade_svc(1, "some AD lookups timed out repeatedly"); 21344520Snw141292 21358361SJulian.Pullen@Sun.COM if (retcode != IDMAP_SUCCESS) { 21368361SJulian.Pullen@Sun.COM /* Mark any unproccessed requests for an other AD */ 21378361SJulian.Pullen@Sun.COM for (i = next_request; i < batch->idmap_mapping_batch_len; 21388361SJulian.Pullen@Sun.COM i++) { 21398361SJulian.Pullen@Sun.COM req = &batch->idmap_mapping_batch_val[i]; 21408361SJulian.Pullen@Sun.COM req->direction |= _IDMAP_F_LOOKUP_OTHER_AD; 21418361SJulian.Pullen@Sun.COM 21428361SJulian.Pullen@Sun.COM } 21438361SJulian.Pullen@Sun.COM } 21448361SJulian.Pullen@Sun.COM 21455731Sbaban if (retcode != IDMAP_SUCCESS) 21465731Sbaban idmapdlog(LOG_NOTICE, "Failed to batch AD lookup requests"); 21474520Snw141292 21484520Snw141292 out: 21495731Sbaban /* 21505731Sbaban * This loop does the following: 21516616Sdm199847 * 1. Reset _IDMAP_F_LOOKUP_AD flag from the request. 21526616Sdm199847 * 2. Reset req->id2.idtype to IDMAP_NONE 21536616Sdm199847 * 3. If batch_start or batch_add failed then set the status 21546616Sdm199847 * of each request marked for AD lookup to that error. 21558361SJulian.Pullen@Sun.COM * 4. Evaluate the type of the AD object (i.e. user or group) 21568361SJulian.Pullen@Sun.COM * and update the idtype in request. 21575731Sbaban */ 21585731Sbaban for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 215910504SKeyur.Desai@Sun.COM int type; 216010504SKeyur.Desai@Sun.COM uid_t posix_id; 216110504SKeyur.Desai@Sun.COM 21625731Sbaban req = &batch->idmap_mapping_batch_val[i]; 21635731Sbaban type = req->id2.idtype; 21645731Sbaban req->id2.idtype = IDMAP_NONE; 216510504SKeyur.Desai@Sun.COM posix_id = req->id2.idmap_id_u.uid; 216610504SKeyur.Desai@Sun.COM req->id2.idmap_id_u.uid = SENTINEL_PID; 21675746Sbaban res = &result->ids.ids_val[i]; 216810504SKeyur.Desai@Sun.COM 216910504SKeyur.Desai@Sun.COM /* 217010504SKeyur.Desai@Sun.COM * If it didn't need AD lookup, ignore it. 217110504SKeyur.Desai@Sun.COM */ 217210504SKeyur.Desai@Sun.COM if (!(req->direction & _IDMAP_F_LOOKUP_AD)) 21735731Sbaban continue; 21745731Sbaban 217510504SKeyur.Desai@Sun.COM /* 217610504SKeyur.Desai@Sun.COM * If we deferred it this time, reset for the next 217710504SKeyur.Desai@Sun.COM * AD server. 217810504SKeyur.Desai@Sun.COM */ 217910504SKeyur.Desai@Sun.COM if (req->direction & _IDMAP_F_LOOKUP_OTHER_AD) { 218010504SKeyur.Desai@Sun.COM req->direction &= ~_IDMAP_F_LOOKUP_OTHER_AD; 218110504SKeyur.Desai@Sun.COM continue; 218210504SKeyur.Desai@Sun.COM } 218310504SKeyur.Desai@Sun.COM 21848361SJulian.Pullen@Sun.COM /* Count number processed */ 21858361SJulian.Pullen@Sun.COM (*num_processed)++; 21868361SJulian.Pullen@Sun.COM 21876616Sdm199847 /* Reset AD lookup flag */ 21886616Sdm199847 req->direction &= ~(_IDMAP_F_LOOKUP_AD); 21896616Sdm199847 21906616Sdm199847 /* 21918361SJulian.Pullen@Sun.COM * If batch_start or batch_add failed then set the 21928361SJulian.Pullen@Sun.COM * status of each request marked for AD lookup to 21938361SJulian.Pullen@Sun.COM * that error. 21946616Sdm199847 */ 21955731Sbaban if (retcode != IDMAP_SUCCESS) { 21965731Sbaban res->retcode = retcode; 21975731Sbaban continue; 21985731Sbaban } 21995731Sbaban 22006386Sjp151216 if (res->retcode == IDMAP_ERR_NOTFOUND) { 22016386Sjp151216 /* Nothing found - remove the preset info */ 22026616Sdm199847 idmap_info_free(&res->info); 22036386Sjp151216 } 22046386Sjp151216 22055731Sbaban if (IS_REQUEST_SID(*req, 1)) { 22065731Sbaban if (res->retcode != IDMAP_SUCCESS) 22075731Sbaban continue; 22086616Sdm199847 /* Evaluate result type */ 22095731Sbaban switch (type) { 22105731Sbaban case _IDMAP_T_USER: 22115731Sbaban if (res->id.idtype == IDMAP_POSIXID) 22125731Sbaban res->id.idtype = IDMAP_UID; 221310504SKeyur.Desai@Sun.COM /* 221410504SKeyur.Desai@Sun.COM * We found a user. If we got information 221510504SKeyur.Desai@Sun.COM * from IDMU and we were expecting a user, 221610504SKeyur.Desai@Sun.COM * copy the id. 221710504SKeyur.Desai@Sun.COM */ 221810504SKeyur.Desai@Sun.COM if (posix_id != SENTINEL_PID && 221910504SKeyur.Desai@Sun.COM res->id.idtype == IDMAP_UID) { 222010504SKeyur.Desai@Sun.COM res->id.idmap_id_u.uid = posix_id; 222110504SKeyur.Desai@Sun.COM res->direction = IDMAP_DIRECTION_BI; 222210504SKeyur.Desai@Sun.COM res->info.how.map_type = 222310504SKeyur.Desai@Sun.COM IDMAP_MAP_TYPE_IDMU; 222410504SKeyur.Desai@Sun.COM res->info.src = IDMAP_MAP_SRC_NEW; 222510504SKeyur.Desai@Sun.COM } 22265731Sbaban req->id1.idtype = IDMAP_USID; 22275731Sbaban break; 22288361SJulian.Pullen@Sun.COM 22295731Sbaban case _IDMAP_T_GROUP: 22305731Sbaban if (res->id.idtype == IDMAP_POSIXID) 22315731Sbaban res->id.idtype = IDMAP_GID; 223210504SKeyur.Desai@Sun.COM /* 223310504SKeyur.Desai@Sun.COM * We found a group. If we got information 223410504SKeyur.Desai@Sun.COM * from IDMU and we were expecting a group, 223510504SKeyur.Desai@Sun.COM * copy the id. 223610504SKeyur.Desai@Sun.COM */ 223710504SKeyur.Desai@Sun.COM if (posix_id != SENTINEL_PID && 223810504SKeyur.Desai@Sun.COM res->id.idtype == IDMAP_GID) { 223910504SKeyur.Desai@Sun.COM res->id.idmap_id_u.gid = posix_id; 224010504SKeyur.Desai@Sun.COM res->direction = IDMAP_DIRECTION_BI; 224110504SKeyur.Desai@Sun.COM res->info.how.map_type = 224210504SKeyur.Desai@Sun.COM IDMAP_MAP_TYPE_IDMU; 224310504SKeyur.Desai@Sun.COM res->info.src = IDMAP_MAP_SRC_NEW; 224410504SKeyur.Desai@Sun.COM } 22455731Sbaban req->id1.idtype = IDMAP_GSID; 22465731Sbaban break; 22478361SJulian.Pullen@Sun.COM 22485731Sbaban default: 22495731Sbaban res->retcode = IDMAP_ERR_SID; 22505731Sbaban break; 22515731Sbaban } 22526616Sdm199847 if (res->retcode == IDMAP_SUCCESS && 22536616Sdm199847 req->id1name != NULL && 22546616Sdm199847 (req->id2name == NULL || 22556616Sdm199847 res->id.idmap_id_u.uid == SENTINEL_PID) && 22566616Sdm199847 NLDAP_MODE(res->id.idtype, state)) { 22576616Sdm199847 req->direction |= _IDMAP_F_LOOKUP_NLDAP; 22586616Sdm199847 state->nldap_nqueries++; 22596616Sdm199847 } 22605731Sbaban } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) { 22615731Sbaban if (res->retcode != IDMAP_SUCCESS) { 22625731Sbaban if ((!(IDMAP_FATAL_ERROR(res->retcode))) && 22635731Sbaban res->id.idmap_id_u.sid.prefix == NULL && 226410504SKeyur.Desai@Sun.COM req->id2name == NULL) /* no winname */ 22655731Sbaban /* 226610504SKeyur.Desai@Sun.COM * If AD lookup by unixname or pid 22678361SJulian.Pullen@Sun.COM * failed with non fatal error 22688361SJulian.Pullen@Sun.COM * then clear the error (ie set 22698361SJulian.Pullen@Sun.COM * res->retcode to success). 22708361SJulian.Pullen@Sun.COM * This allows the next pass to 22718361SJulian.Pullen@Sun.COM * process other mapping 22726616Sdm199847 * mechanisms for this request. 22735731Sbaban */ 22745731Sbaban res->retcode = IDMAP_SUCCESS; 22755731Sbaban continue; 22765731Sbaban } 22776616Sdm199847 /* Evaluate result type */ 22785731Sbaban switch (type) { 22795731Sbaban case _IDMAP_T_USER: 22805731Sbaban if (res->id.idtype == IDMAP_SID) 22815731Sbaban res->id.idtype = IDMAP_USID; 22825731Sbaban break; 22838361SJulian.Pullen@Sun.COM 22845731Sbaban case _IDMAP_T_GROUP: 22855731Sbaban if (res->id.idtype == IDMAP_SID) 22865731Sbaban res->id.idtype = IDMAP_GSID; 22875731Sbaban break; 22888361SJulian.Pullen@Sun.COM 22895731Sbaban default: 22905731Sbaban res->retcode = IDMAP_ERR_SID; 22915731Sbaban break; 22925731Sbaban } 22935731Sbaban } 22945731Sbaban } 22955731Sbaban 22968361SJulian.Pullen@Sun.COM return (retcode); 22978361SJulian.Pullen@Sun.COM } 22988361SJulian.Pullen@Sun.COM 22998361SJulian.Pullen@Sun.COM 23008361SJulian.Pullen@Sun.COM 23018361SJulian.Pullen@Sun.COM /* 23028361SJulian.Pullen@Sun.COM * Batch AD lookups 23038361SJulian.Pullen@Sun.COM */ 23048361SJulian.Pullen@Sun.COM idmap_retcode 23058361SJulian.Pullen@Sun.COM ad_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch, 23068361SJulian.Pullen@Sun.COM idmap_ids_res *result) 23078361SJulian.Pullen@Sun.COM { 23088361SJulian.Pullen@Sun.COM idmap_retcode retcode; 23098361SJulian.Pullen@Sun.COM int i, j; 23108361SJulian.Pullen@Sun.COM idmap_mapping *req; 23118361SJulian.Pullen@Sun.COM idmap_id_res *res; 23128361SJulian.Pullen@Sun.COM int num_queries; 23138361SJulian.Pullen@Sun.COM int num_processed; 23148361SJulian.Pullen@Sun.COM 23158361SJulian.Pullen@Sun.COM if (state->ad_nqueries == 0) 23168361SJulian.Pullen@Sun.COM return (IDMAP_SUCCESS); 23178361SJulian.Pullen@Sun.COM 23188361SJulian.Pullen@Sun.COM for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 23198361SJulian.Pullen@Sun.COM req = &batch->idmap_mapping_batch_val[i]; 23208361SJulian.Pullen@Sun.COM res = &result->ids.ids_val[i]; 23218361SJulian.Pullen@Sun.COM 23228361SJulian.Pullen@Sun.COM /* Skip if not marked for AD lookup or already in error. */ 23238361SJulian.Pullen@Sun.COM if (!(req->direction & _IDMAP_F_LOOKUP_AD) || 23248361SJulian.Pullen@Sun.COM res->retcode != IDMAP_SUCCESS) 23258361SJulian.Pullen@Sun.COM continue; 23268361SJulian.Pullen@Sun.COM 23278361SJulian.Pullen@Sun.COM /* Init status */ 23288361SJulian.Pullen@Sun.COM res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; 23298361SJulian.Pullen@Sun.COM } 23308361SJulian.Pullen@Sun.COM 23318361SJulian.Pullen@Sun.COM RDLOCK_CONFIG(); 23328361SJulian.Pullen@Sun.COM num_queries = state->ad_nqueries; 233310504SKeyur.Desai@Sun.COM 233410504SKeyur.Desai@Sun.COM if (_idmapdstate.num_gcs == 0 && _idmapdstate.num_dcs == 0) { 23358361SJulian.Pullen@Sun.COM /* Case of no ADs */ 23368361SJulian.Pullen@Sun.COM retcode = IDMAP_ERR_NO_ACTIVEDIRECTORY; 23378361SJulian.Pullen@Sun.COM for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 23388361SJulian.Pullen@Sun.COM req = &batch->idmap_mapping_batch_val[i]; 23398361SJulian.Pullen@Sun.COM res = &result->ids.ids_val[i]; 23408361SJulian.Pullen@Sun.COM if (!(req->direction & _IDMAP_F_LOOKUP_AD)) 23418361SJulian.Pullen@Sun.COM continue; 23428361SJulian.Pullen@Sun.COM req->direction &= ~(_IDMAP_F_LOOKUP_AD); 23438361SJulian.Pullen@Sun.COM res->retcode = IDMAP_ERR_NO_ACTIVEDIRECTORY; 23448361SJulian.Pullen@Sun.COM } 234510504SKeyur.Desai@Sun.COM goto out; 23468361SJulian.Pullen@Sun.COM } 234710504SKeyur.Desai@Sun.COM 234810504SKeyur.Desai@Sun.COM if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU) { 234910504SKeyur.Desai@Sun.COM for (i = 0; i < _idmapdstate.num_dcs && num_queries > 0; i++) { 235010504SKeyur.Desai@Sun.COM 235110504SKeyur.Desai@Sun.COM retcode = ad_lookup_batch_int(state, batch, 235210504SKeyur.Desai@Sun.COM result, _idmapdstate.dcs[i], 235310504SKeyur.Desai@Sun.COM i == 0 ? DOMAIN_IS_LOCAL|FOREST_IS_LOCAL : 0, 235410504SKeyur.Desai@Sun.COM &num_processed); 235510504SKeyur.Desai@Sun.COM num_queries -= num_processed; 235610504SKeyur.Desai@Sun.COM 235710504SKeyur.Desai@Sun.COM } 235810504SKeyur.Desai@Sun.COM } 235910504SKeyur.Desai@Sun.COM 236010504SKeyur.Desai@Sun.COM for (i = 0; i < _idmapdstate.num_gcs && num_queries > 0; i++) { 236110504SKeyur.Desai@Sun.COM 236210504SKeyur.Desai@Sun.COM retcode = ad_lookup_batch_int(state, batch, result, 236310504SKeyur.Desai@Sun.COM _idmapdstate.gcs[i], 236410504SKeyur.Desai@Sun.COM i == 0 ? FOREST_IS_LOCAL : 0, 236510504SKeyur.Desai@Sun.COM &num_processed); 236610504SKeyur.Desai@Sun.COM num_queries -= num_processed; 236710504SKeyur.Desai@Sun.COM 236810504SKeyur.Desai@Sun.COM } 236910504SKeyur.Desai@Sun.COM 237010504SKeyur.Desai@Sun.COM /* 237110504SKeyur.Desai@Sun.COM * There are no more ADs to try. Return errors for any 237210504SKeyur.Desai@Sun.COM * remaining requests. 237310504SKeyur.Desai@Sun.COM */ 237410504SKeyur.Desai@Sun.COM if (num_queries > 0) { 237510504SKeyur.Desai@Sun.COM for (j = 0; j < batch->idmap_mapping_batch_len; j++) { 237610504SKeyur.Desai@Sun.COM req = &batch->idmap_mapping_batch_val[j]; 237710504SKeyur.Desai@Sun.COM res = &result->ids.ids_val[j]; 237810504SKeyur.Desai@Sun.COM if (!(req->direction & _IDMAP_F_LOOKUP_AD)) 237910504SKeyur.Desai@Sun.COM continue; 238010504SKeyur.Desai@Sun.COM req->direction &= ~(_IDMAP_F_LOOKUP_AD); 238110504SKeyur.Desai@Sun.COM res->retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 238210504SKeyur.Desai@Sun.COM } 238310504SKeyur.Desai@Sun.COM } 238410504SKeyur.Desai@Sun.COM 238510504SKeyur.Desai@Sun.COM out: 23868361SJulian.Pullen@Sun.COM UNLOCK_CONFIG(); 23878361SJulian.Pullen@Sun.COM 23885731Sbaban /* AD lookups done. Reset state->ad_nqueries and return */ 23895731Sbaban state->ad_nqueries = 0; 23904520Snw141292 return (retcode); 23914520Snw141292 } 23924520Snw141292 23935696Snw141292 /* 23945696Snw141292 * Convention when processing win2unix requests: 23955696Snw141292 * 23965696Snw141292 * Windows identity: 23975696Snw141292 * req->id1name = 23985696Snw141292 * winname if given otherwise winname found will be placed 23995696Snw141292 * here. 24005696Snw141292 * req->id1domain = 24015696Snw141292 * windomain if given otherwise windomain found will be 24025696Snw141292 * placed here. 24035696Snw141292 * req->id1.idtype = 24045696Snw141292 * Either IDMAP_SID/USID/GSID. If this is IDMAP_SID then it'll 24055696Snw141292 * be set to IDMAP_USID/GSID depending upon whether the 24065696Snw141292 * given SID is user or group respectively. The user/group-ness 24075696Snw141292 * is determined either when looking up well-known SIDs table OR 24086616Sdm199847 * if the SID is found in namecache OR by ad_lookup_one() OR by 24095696Snw141292 * ad_lookup_batch(). 24105696Snw141292 * req->id1..sid.[prefix, rid] = 24115696Snw141292 * SID if given otherwise SID found will be placed here. 24125696Snw141292 * 24135696Snw141292 * Unix identity: 24145696Snw141292 * req->id2name = 24155696Snw141292 * unixname found will be placed here. 24165696Snw141292 * req->id2domain = 24175696Snw141292 * NOT USED 24185696Snw141292 * res->id.idtype = 24195696Snw141292 * Target type initialized from req->id2.idtype. If 24205696Snw141292 * it is IDMAP_POSIXID then actual type (IDMAP_UID/GID) found 24215696Snw141292 * will be placed here. 24225696Snw141292 * res->id..[uid or gid] = 24235696Snw141292 * UID/GID found will be placed here. 24245696Snw141292 * 24255696Snw141292 * Others: 24265696Snw141292 * res->retcode = 24275696Snw141292 * Return status for this request will be placed here. 24285696Snw141292 * res->direction = 24295696Snw141292 * Direction found will be placed here. Direction 24305696Snw141292 * meaning whether the resultant mapping is valid 24315696Snw141292 * only from win2unix or bi-directional. 24325696Snw141292 * req->direction = 24335696Snw141292 * INTERNAL USE. Used by idmapd to set various 24345696Snw141292 * flags (_IDMAP_F_xxxx) to aid in processing 24355696Snw141292 * of the request. 24365696Snw141292 * req->id2.idtype = 24375696Snw141292 * INTERNAL USE. Initially this is the requested target 24385696Snw141292 * type and is used to initialize res->id.idtype. 24395696Snw141292 * ad_lookup_batch() uses this field temporarily to store 24405696Snw141292 * sid_type obtained by the batched AD lookups and after 24415696Snw141292 * use resets it to IDMAP_NONE to prevent xdr from 24425696Snw141292 * mis-interpreting the contents of req->id2. 244310504SKeyur.Desai@Sun.COM * req->id2.idmap_id_u.uid = 244410504SKeyur.Desai@Sun.COM * INTERNAL USE. If the AD lookup finds IDMU data 244510504SKeyur.Desai@Sun.COM * (uidNumber or gidNumber, depending on the type of 244610504SKeyur.Desai@Sun.COM * the entry), it's left here. 24475696Snw141292 */ 24485696Snw141292 24495696Snw141292 /* 24505696Snw141292 * This function does the following: 24515696Snw141292 * 1. Lookup well-known SIDs table. 24525696Snw141292 * 2. Check if the given SID is a local-SID and if so extract UID/GID from it. 24535696Snw141292 * 3. Lookup cache. 24545696Snw141292 * 4. Check if the client does not want new mapping to be allocated 24555696Snw141292 * in which case this pass is the final pass. 24565696Snw141292 * 5. Set AD lookup flag if it determines that the next stage needs 24575696Snw141292 * to do AD lookup. 24585696Snw141292 */ 24594520Snw141292 idmap_retcode 24606616Sdm199847 sid2pid_first_pass(lookup_state_t *state, idmap_mapping *req, 24615696Snw141292 idmap_id_res *res) 24625696Snw141292 { 24634520Snw141292 idmap_retcode retcode; 24645731Sbaban int wksid; 24655731Sbaban 24665731Sbaban /* Initialize result */ 24675731Sbaban res->id.idtype = req->id2.idtype; 24685731Sbaban res->id.idmap_id_u.uid = SENTINEL_PID; 24695731Sbaban res->direction = IDMAP_DIRECTION_UNDEF; 24705731Sbaban wksid = 0; 24714520Snw141292 24725127Sdm199847 if (EMPTY_STRING(req->id1.idmap_id_u.sid.prefix)) { 24735731Sbaban if (req->id1name == NULL) { 24745731Sbaban retcode = IDMAP_ERR_ARG; 24755731Sbaban goto out; 24765731Sbaban } 24775731Sbaban /* sanitize sidprefix */ 24785731Sbaban free(req->id1.idmap_id_u.sid.prefix); 24795731Sbaban req->id1.idmap_id_u.sid.prefix = NULL; 24804520Snw141292 } 24815731Sbaban 24825731Sbaban /* Lookup well-known SIDs table */ 24835731Sbaban retcode = lookup_wksids_sid2pid(req, res, &wksid); 24844520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 24854520Snw141292 goto out; 24864520Snw141292 24875731Sbaban if (!wksid) { 24888040SBaban.Kenkre@Sun.COM /* Check if this is a localsid */ 24895731Sbaban retcode = lookup_localsid2pid(req, res); 24905731Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 24915731Sbaban goto out; 24928040SBaban.Kenkre@Sun.COM 24938040SBaban.Kenkre@Sun.COM if (ALLOW_WK_OR_LOCAL_SIDS_ONLY(req)) { 24948361SJulian.Pullen@Sun.COM retcode = IDMAP_ERR_NONE_GENERATED; 24958040SBaban.Kenkre@Sun.COM goto out; 24968040SBaban.Kenkre@Sun.COM } 24975731Sbaban } 24985731Sbaban 24995731Sbaban /* Lookup cache */ 25006616Sdm199847 retcode = lookup_cache_sid2pid(state->cache, req, res); 25014520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 25024520Snw141292 goto out; 25034520Snw141292 25044520Snw141292 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { 25058361SJulian.Pullen@Sun.COM retcode = IDMAP_ERR_NONE_GENERATED; 25064520Snw141292 goto out; 25074520Snw141292 } 25084520Snw141292 25094520Snw141292 /* 25105731Sbaban * Failed to find non-expired entry in cache. Next step is 25115731Sbaban * to determine if this request needs to be batched for AD lookup. 25125731Sbaban * 25135731Sbaban * At this point we have either sid or winname or both. If we don't 25145731Sbaban * have both then lookup name_cache for the sid or winname 25155731Sbaban * whichever is missing. If not found then this request will be 25165731Sbaban * batched for AD lookup. 25174520Snw141292 */ 25186616Sdm199847 retcode = lookup_name_cache(state->cache, req, res); 25195731Sbaban if (retcode != IDMAP_SUCCESS && retcode != IDMAP_ERR_NOTFOUND) 25205731Sbaban goto out; 25214520Snw141292 25224520Snw141292 /* 25235731Sbaban * Set the flag to indicate that we are not done yet so that 25245731Sbaban * subsequent passes considers this request for name-based 25255731Sbaban * mapping and ephemeral mapping. 25264520Snw141292 */ 25275731Sbaban state->sid2pid_done = FALSE; 25285731Sbaban req->direction |= _IDMAP_F_NOTDONE; 25295731Sbaban 25305731Sbaban /* 25315731Sbaban * Even if we have both sid and winname, we still may need to batch 25325731Sbaban * this request for AD lookup if we don't have unixname and 25335731Sbaban * directory-based name mapping (AD or mixed) is enabled. 25345731Sbaban * We avoid AD lookup for well-known SIDs because they don't have 25355731Sbaban * regular AD objects. 25365731Sbaban */ 25375731Sbaban if (retcode != IDMAP_SUCCESS || 25385731Sbaban (!wksid && req->id2name == NULL && 253910504SKeyur.Desai@Sun.COM AD_OR_MIXED_MODE(res->id.idtype, state)) || 254010504SKeyur.Desai@Sun.COM (!wksid && res->id.idmap_id_u.uid == SENTINEL_PID && 254110504SKeyur.Desai@Sun.COM state->directory_based_mapping == DIRECTORY_MAPPING_IDMU)) { 25424520Snw141292 retcode = IDMAP_SUCCESS; 25435731Sbaban req->direction |= _IDMAP_F_LOOKUP_AD; 25444520Snw141292 state->ad_nqueries++; 25456616Sdm199847 } else if (NLDAP_MODE(res->id.idtype, state)) { 25466616Sdm199847 req->direction |= _IDMAP_F_LOOKUP_NLDAP; 25476616Sdm199847 state->nldap_nqueries++; 25484520Snw141292 } 25494520Snw141292 25504520Snw141292 25514520Snw141292 out: 25524520Snw141292 res->retcode = idmap_stat4prot(retcode); 25535731Sbaban /* 25545731Sbaban * If we are done and there was an error then set fallback pid 25555731Sbaban * in the result. 25565731Sbaban */ 25575731Sbaban if (ARE_WE_DONE(req->direction) && res->retcode != IDMAP_SUCCESS) 25585731Sbaban res->id.idmap_id_u.uid = UID_NOBODY; 25594520Snw141292 return (retcode); 25604520Snw141292 } 25614520Snw141292 25624520Snw141292 /* 25634520Snw141292 * Generate SID using the following convention 25644520Snw141292 * <machine-sid-prefix>-<1000 + uid> 25654520Snw141292 * <machine-sid-prefix>-<2^31 + gid> 25664520Snw141292 */ 25675696Snw141292 static 25685696Snw141292 idmap_retcode 25696386Sjp151216 generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user, 25706386Sjp151216 int fallback) 25715696Snw141292 { 25725731Sbaban free(res->id.idmap_id_u.sid.prefix); 25735731Sbaban res->id.idmap_id_u.sid.prefix = NULL; 25745731Sbaban 25755731Sbaban /* 25765731Sbaban * Diagonal mapping for localSIDs not supported because of the 25775731Sbaban * way we generate localSIDs. 25785731Sbaban */ 25795731Sbaban if (is_user && res->id.idtype == IDMAP_GSID) 258010717Samw@Sun.COM return (IDMAP_ERR_NOTGROUP); 25815731Sbaban if (!is_user && res->id.idtype == IDMAP_USID) 258210717Samw@Sun.COM return (IDMAP_ERR_NOTUSER); 25835731Sbaban 25845731Sbaban /* Skip 1000 UIDs */ 258510122SJordan.Brown@Sun.COM if (is_user && 258610122SJordan.Brown@Sun.COM req->id1.idmap_id_u.uid + LOCALRID_UID_MIN > LOCALRID_UID_MAX) 25875731Sbaban return (IDMAP_ERR_NOMAPPING); 25885731Sbaban 25895731Sbaban RDLOCK_CONFIG(); 25905731Sbaban /* 25915731Sbaban * machine_sid is never NULL because if it is we won't be here. 25925731Sbaban * No need to assert because stdrup(NULL) will core anyways. 25935731Sbaban */ 25945731Sbaban res->id.idmap_id_u.sid.prefix = 25955731Sbaban strdup(_idmapdstate.cfg->pgcfg.machine_sid); 25965731Sbaban if (res->id.idmap_id_u.sid.prefix == NULL) { 25974520Snw141292 UNLOCK_CONFIG(); 25985731Sbaban idmapdlog(LOG_ERR, "Out of memory"); 25995731Sbaban return (IDMAP_ERR_MEMORY); 26004520Snw141292 } 26015731Sbaban UNLOCK_CONFIG(); 26025731Sbaban res->id.idmap_id_u.sid.rid = 260310122SJordan.Brown@Sun.COM (is_user) ? req->id1.idmap_id_u.uid + LOCALRID_UID_MIN : 260410122SJordan.Brown@Sun.COM req->id1.idmap_id_u.gid + LOCALRID_GID_MIN; 26055731Sbaban res->direction = IDMAP_DIRECTION_BI; 26065731Sbaban if (res->id.idtype == IDMAP_SID) 26075731Sbaban res->id.idtype = is_user ? IDMAP_USID : IDMAP_GSID; 26085731Sbaban 26099021Samw@Sun.COM if (!fallback) { 26106386Sjp151216 res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID; 26116386Sjp151216 res->info.src = IDMAP_MAP_SRC_ALGORITHMIC; 26126386Sjp151216 } 26136386Sjp151216 26145731Sbaban /* 26155731Sbaban * Don't update name_cache because local sids don't have 26165731Sbaban * valid windows names. 26175731Sbaban */ 26185731Sbaban req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE; 26195731Sbaban return (IDMAP_SUCCESS); 26204520Snw141292 } 26214520Snw141292 26225696Snw141292 static 26235696Snw141292 idmap_retcode 26245696Snw141292 lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) 26255696Snw141292 { 26264520Snw141292 char *sidprefix; 26274520Snw141292 uint32_t rid; 26284520Snw141292 int s; 26294520Snw141292 26304520Snw141292 /* 26314520Snw141292 * If the sidprefix == localsid then UID = last RID - 1000 or 26324520Snw141292 * GID = last RID - 2^31. 26334520Snw141292 */ 26345731Sbaban if ((sidprefix = req->id1.idmap_id_u.sid.prefix) == NULL) 26355731Sbaban /* This means we are looking up by winname */ 26365731Sbaban return (IDMAP_ERR_NOTFOUND); 26374520Snw141292 rid = req->id1.idmap_id_u.sid.rid; 26384520Snw141292 26394520Snw141292 RDLOCK_CONFIG(); 26405696Snw141292 s = (_idmapdstate.cfg->pgcfg.machine_sid) ? 26415696Snw141292 strcasecmp(sidprefix, _idmapdstate.cfg->pgcfg.machine_sid) : 1; 26424520Snw141292 UNLOCK_CONFIG(); 26434520Snw141292 26445731Sbaban /* 26455731Sbaban * If the given sidprefix does not match machine_sid then this is 26465731Sbaban * not a local SID. 26475731Sbaban */ 26485731Sbaban if (s != 0) 26495731Sbaban return (IDMAP_ERR_NOTFOUND); 26505731Sbaban 26515731Sbaban switch (res->id.idtype) { 26525731Sbaban case IDMAP_UID: 265310122SJordan.Brown@Sun.COM if (rid < LOCALRID_UID_MIN || rid > LOCALRID_UID_MAX) 26545731Sbaban return (IDMAP_ERR_ARG); 265510122SJordan.Brown@Sun.COM res->id.idmap_id_u.uid = rid - LOCALRID_UID_MIN; 26565731Sbaban break; 26575731Sbaban case IDMAP_GID: 265810122SJordan.Brown@Sun.COM if (rid < LOCALRID_GID_MIN) 26595731Sbaban return (IDMAP_ERR_ARG); 266010122SJordan.Brown@Sun.COM res->id.idmap_id_u.gid = rid - LOCALRID_GID_MIN; 26615731Sbaban break; 26625731Sbaban case IDMAP_POSIXID: 266310122SJordan.Brown@Sun.COM if (rid >= LOCALRID_GID_MIN) { 266410122SJordan.Brown@Sun.COM res->id.idmap_id_u.gid = rid - LOCALRID_GID_MIN; 26654520Snw141292 res->id.idtype = IDMAP_GID; 266610122SJordan.Brown@Sun.COM } else if (rid >= LOCALRID_UID_MIN) { 266710122SJordan.Brown@Sun.COM res->id.idmap_id_u.uid = rid - LOCALRID_UID_MIN; 266810122SJordan.Brown@Sun.COM res->id.idtype = IDMAP_UID; 26695731Sbaban } else { 267010122SJordan.Brown@Sun.COM return (IDMAP_ERR_ARG); 26714520Snw141292 } 26725731Sbaban break; 26735731Sbaban default: 26745731Sbaban return (IDMAP_ERR_NOTSUPPORTED); 26754520Snw141292 } 26769021Samw@Sun.COM res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID; 26779021Samw@Sun.COM res->info.src = IDMAP_MAP_SRC_ALGORITHMIC; 26785731Sbaban return (IDMAP_SUCCESS); 26794520Snw141292 } 26804520Snw141292 26815731Sbaban /* 26825731Sbaban * Name service lookup by unixname to get pid 26835731Sbaban */ 26845696Snw141292 static 26855696Snw141292 idmap_retcode 26865731Sbaban ns_lookup_byname(const char *name, const char *lower_name, idmap_id *id) 26875696Snw141292 { 26885696Snw141292 struct passwd pwd, *pwdp; 26895696Snw141292 struct group grp, *grpp; 26909132SJordan.Brown@Sun.COM char *buf; 26919132SJordan.Brown@Sun.COM static size_t pwdbufsiz = 0; 26929132SJordan.Brown@Sun.COM static size_t grpbufsiz = 0; 26934520Snw141292 26945731Sbaban switch (id->idtype) { 26955731Sbaban case IDMAP_UID: 26969132SJordan.Brown@Sun.COM if (pwdbufsiz == 0) 26979132SJordan.Brown@Sun.COM pwdbufsiz = sysconf(_SC_GETPW_R_SIZE_MAX); 26989132SJordan.Brown@Sun.COM buf = alloca(pwdbufsiz); 26999132SJordan.Brown@Sun.COM pwdp = getpwnam_r(name, &pwd, buf, pwdbufsiz); 27005731Sbaban if (pwdp == NULL && errno == 0 && lower_name != NULL && 27015696Snw141292 name != lower_name && strcmp(name, lower_name) != 0) 27029132SJordan.Brown@Sun.COM pwdp = getpwnam_r(lower_name, &pwd, buf, pwdbufsiz); 27035696Snw141292 if (pwdp == NULL) { 2704*10966SJordan.Brown@Sun.COM if (errno == 0) 27054520Snw141292 return (IDMAP_ERR_NOTFOUND); 27064520Snw141292 else 27074520Snw141292 return (IDMAP_ERR_INTERNAL); 27084520Snw141292 } 27095731Sbaban id->idmap_id_u.uid = pwd.pw_uid; 27105731Sbaban break; 27115731Sbaban case IDMAP_GID: 27129132SJordan.Brown@Sun.COM if (grpbufsiz == 0) 27139132SJordan.Brown@Sun.COM grpbufsiz = sysconf(_SC_GETGR_R_SIZE_MAX); 27149132SJordan.Brown@Sun.COM buf = alloca(grpbufsiz); 27159132SJordan.Brown@Sun.COM grpp = getgrnam_r(name, &grp, buf, grpbufsiz); 27165731Sbaban if (grpp == NULL && errno == 0 && lower_name != NULL && 27175696Snw141292 name != lower_name && strcmp(name, lower_name) != 0) 27189132SJordan.Brown@Sun.COM grpp = getgrnam_r(lower_name, &grp, buf, grpbufsiz); 27195696Snw141292 if (grpp == NULL) { 2720*10966SJordan.Brown@Sun.COM if (errno == 0) 27214520Snw141292 return (IDMAP_ERR_NOTFOUND); 27224520Snw141292 else 27234520Snw141292 return (IDMAP_ERR_INTERNAL); 27244520Snw141292 } 27255731Sbaban id->idmap_id_u.gid = grp.gr_gid; 27265731Sbaban break; 27275731Sbaban default: 27285731Sbaban return (IDMAP_ERR_ARG); 27294520Snw141292 } 27304520Snw141292 return (IDMAP_SUCCESS); 27314520Snw141292 } 27324520Snw141292 27335731Sbaban 27345731Sbaban /* 27355731Sbaban * Name service lookup by pid to get unixname 27365731Sbaban */ 27375731Sbaban static 27385731Sbaban idmap_retcode 27395731Sbaban ns_lookup_bypid(uid_t pid, int is_user, char **unixname) 27405731Sbaban { 27415731Sbaban struct passwd pwd; 27425731Sbaban struct group grp; 27439132SJordan.Brown@Sun.COM char *buf; 27449132SJordan.Brown@Sun.COM static size_t pwdbufsiz = 0; 27459132SJordan.Brown@Sun.COM static size_t grpbufsiz = 0; 27465731Sbaban 27475731Sbaban if (is_user) { 27489132SJordan.Brown@Sun.COM if (pwdbufsiz == 0) 27499132SJordan.Brown@Sun.COM pwdbufsiz = sysconf(_SC_GETPW_R_SIZE_MAX); 27509132SJordan.Brown@Sun.COM buf = alloca(pwdbufsiz); 27515731Sbaban errno = 0; 27529132SJordan.Brown@Sun.COM if (getpwuid_r(pid, &pwd, buf, pwdbufsiz) == NULL) { 2753*10966SJordan.Brown@Sun.COM if (errno == 0) 27545731Sbaban return (IDMAP_ERR_NOTFOUND); 27555731Sbaban else 27565731Sbaban return (IDMAP_ERR_INTERNAL); 27575731Sbaban } 27585731Sbaban *unixname = strdup(pwd.pw_name); 27595731Sbaban } else { 27609132SJordan.Brown@Sun.COM if (grpbufsiz == 0) 27619132SJordan.Brown@Sun.COM grpbufsiz = sysconf(_SC_GETGR_R_SIZE_MAX); 27629132SJordan.Brown@Sun.COM buf = alloca(grpbufsiz); 27635731Sbaban errno = 0; 27649132SJordan.Brown@Sun.COM if (getgrgid_r(pid, &grp, buf, grpbufsiz) == NULL) { 2765*10966SJordan.Brown@Sun.COM if (errno == 0) 27665731Sbaban return (IDMAP_ERR_NOTFOUND); 27675731Sbaban else 27685731Sbaban return (IDMAP_ERR_INTERNAL); 27695731Sbaban } 27705731Sbaban *unixname = strdup(grp.gr_name); 27715731Sbaban } 27725731Sbaban if (*unixname == NULL) 27735731Sbaban return (IDMAP_ERR_MEMORY); 27745731Sbaban return (IDMAP_SUCCESS); 27755731Sbaban } 27765731Sbaban 27774520Snw141292 /* 27784520Snw141292 * Name-based mapping 27794520Snw141292 * 27804520Snw141292 * Case 1: If no rule matches do ephemeral 27814520Snw141292 * 27824520Snw141292 * Case 2: If rule matches and unixname is "" then return no mapping. 27834520Snw141292 * 27844520Snw141292 * Case 3: If rule matches and unixname is specified then lookup name 27854520Snw141292 * service using the unixname. If unixname not found then return no mapping. 27864520Snw141292 * 27874520Snw141292 * Case 4: If rule matches and unixname is * then lookup name service 27884520Snw141292 * using winname as the unixname. If unixname not found then process 27894520Snw141292 * other rules using the lookup order. If no other rule matches then do 27904520Snw141292 * ephemeral. Otherwise, based on the matched rule do Case 2 or 3 or 4. 27914520Snw141292 * This allows us to specify a fallback unixname per _domain_ or no mapping 27924520Snw141292 * instead of the default behaviour of doing ephemeral mapping. 27934520Snw141292 * 27944520Snw141292 * Example 1: 27954520Snw141292 * *@sfbay == * 27964520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 27974520Snw141292 * the name service then foo@sfbay will be mapped to an ephemeral id. 27984520Snw141292 * 27994520Snw141292 * Example 2: 28004520Snw141292 * *@sfbay == * 28014520Snw141292 * *@sfbay => guest 28024520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 28034520Snw141292 * the name service then foo@sfbay will be mapped to guest. 28044520Snw141292 * 28054520Snw141292 * Example 3: 28064520Snw141292 * *@sfbay == * 28074520Snw141292 * *@sfbay => "" 28084520Snw141292 * If looking up windows users foo@sfbay and foo does not exists in 28094520Snw141292 * the name service then we will return no mapping for foo@sfbay. 28104520Snw141292 * 28114520Snw141292 */ 28125696Snw141292 static 28135696Snw141292 idmap_retcode 28146616Sdm199847 name_based_mapping_sid2pid(lookup_state_t *state, 28156616Sdm199847 idmap_mapping *req, idmap_id_res *res) 28165696Snw141292 { 28175696Snw141292 const char *unixname, *windomain; 28185696Snw141292 char *sql = NULL, *errmsg = NULL, *lower_winname = NULL; 28194520Snw141292 idmap_retcode retcode; 28205696Snw141292 char *end, *lower_unixname, *winname; 28214520Snw141292 const char **values; 28224520Snw141292 sqlite_vm *vm = NULL; 28239422SAfshin.Ardakani@Sun.COM int ncol, r, is_user, is_wuser; 28246386Sjp151216 idmap_namerule *rule = &res->info.how.idmap_how_u.rule; 28256386Sjp151216 int direction; 28264520Snw141292 const char *me = "name_based_mapping_sid2pid"; 28274520Snw141292 28285731Sbaban assert(req->id1name != NULL); /* We have winname */ 28295731Sbaban assert(req->id2name == NULL); /* We don't have unixname */ 28305731Sbaban 28315064Sdm199847 winname = req->id1name; 28325064Sdm199847 windomain = req->id1domain; 28335696Snw141292 28345696Snw141292 switch (req->id1.idtype) { 28355696Snw141292 case IDMAP_USID: 28365696Snw141292 is_wuser = 1; 28375696Snw141292 break; 28385696Snw141292 case IDMAP_GSID: 28395696Snw141292 is_wuser = 0; 28405696Snw141292 break; 28415696Snw141292 default: 28425731Sbaban idmapdlog(LOG_ERR, "%s: Unable to determine if the " 28435731Sbaban "given Windows id is user or group.", me); 28445696Snw141292 return (IDMAP_ERR_INTERNAL); 28455696Snw141292 } 28465696Snw141292 28475731Sbaban switch (res->id.idtype) { 28485696Snw141292 case IDMAP_UID: 28495696Snw141292 is_user = 1; 28505696Snw141292 break; 28515696Snw141292 case IDMAP_GID: 28525696Snw141292 is_user = 0; 28535696Snw141292 break; 28545696Snw141292 case IDMAP_POSIXID: 28555696Snw141292 is_user = is_wuser; 28565696Snw141292 res->id.idtype = is_user ? IDMAP_UID : IDMAP_GID; 28575696Snw141292 break; 28585696Snw141292 } 28594520Snw141292 28606616Sdm199847 if (windomain == NULL) 28614864Sbaban windomain = ""; 28624520Snw141292 28635696Snw141292 if ((lower_winname = tolower_u8(winname)) == NULL) 28645696Snw141292 lower_winname = winname; /* hope for the best */ 28654520Snw141292 sql = sqlite_mprintf( 28666386Sjp151216 "SELECT unixname, u2w_order, winname_display, windomain, is_nt4 " 28676386Sjp151216 "FROM namerules WHERE " 28685696Snw141292 "w2u_order > 0 AND is_user = %d AND is_wuser = %d AND " 28695696Snw141292 "(winname = %Q OR winname = '*') AND " 28709422SAfshin.Ardakani@Sun.COM "(windomain = %Q OR windomain = '*') " 28715696Snw141292 "ORDER BY w2u_order ASC;", 28729422SAfshin.Ardakani@Sun.COM is_user, is_wuser, lower_winname, windomain); 28734520Snw141292 if (sql == NULL) { 28744520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 28754520Snw141292 retcode = IDMAP_ERR_MEMORY; 28764520Snw141292 goto out; 28774520Snw141292 } 28784520Snw141292 28796616Sdm199847 if (sqlite_compile(state->db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 28804520Snw141292 retcode = IDMAP_ERR_INTERNAL; 28815696Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 28825696Snw141292 CHECK_NULL(errmsg)); 28834520Snw141292 sqlite_freemem(errmsg); 28844520Snw141292 goto out; 28854520Snw141292 } 28864520Snw141292 28876386Sjp151216 for (;;) { 28884520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 28894884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 28904884Sjp151216 28914884Sjp151216 if (r == SQLITE_ROW) { 28926386Sjp151216 if (ncol < 5) { 28934520Snw141292 retcode = IDMAP_ERR_INTERNAL; 28944520Snw141292 goto out; 28954520Snw141292 } 28964520Snw141292 if (values[0] == NULL) { 28974520Snw141292 retcode = IDMAP_ERR_INTERNAL; 28984520Snw141292 goto out; 28994520Snw141292 } 29004520Snw141292 29016386Sjp151216 if (values[1] != NULL) 29026386Sjp151216 direction = 29036386Sjp151216 (strtol(values[1], &end, 10) == 0)? 29046386Sjp151216 IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 29056386Sjp151216 else 29066386Sjp151216 direction = IDMAP_DIRECTION_W2U; 29076386Sjp151216 29084520Snw141292 if (EMPTY_NAME(values[0])) { 29096386Sjp151216 idmap_namerule_set(rule, values[3], values[2], 29106386Sjp151216 values[0], is_wuser, is_user, 29116386Sjp151216 strtol(values[4], &end, 10), 29126386Sjp151216 direction); 29134520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 29144520Snw141292 goto out; 29154520Snw141292 } 29166386Sjp151216 29176386Sjp151216 if (values[0][0] == '*') { 29186386Sjp151216 unixname = winname; 29196386Sjp151216 lower_unixname = lower_winname; 29206386Sjp151216 } else { 29216386Sjp151216 unixname = values[0]; 29226386Sjp151216 lower_unixname = NULL; 29236386Sjp151216 } 29246386Sjp151216 29255731Sbaban retcode = ns_lookup_byname(unixname, lower_unixname, 29265731Sbaban &res->id); 29274520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 29286386Sjp151216 if (values[0][0] == '*') 29294520Snw141292 /* Case 4 */ 29304520Snw141292 continue; 29316386Sjp151216 else { 29324520Snw141292 /* Case 3 */ 29336386Sjp151216 idmap_namerule_set(rule, values[3], 29346386Sjp151216 values[2], values[0], is_wuser, 29356386Sjp151216 is_user, 29366386Sjp151216 strtol(values[4], &end, 10), 29376386Sjp151216 direction); 29384520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 29396386Sjp151216 } 29404520Snw141292 } 29414520Snw141292 goto out; 29424520Snw141292 } else if (r == SQLITE_DONE) { 29434520Snw141292 retcode = IDMAP_ERR_NOTFOUND; 29444520Snw141292 goto out; 29454520Snw141292 } else { 29464520Snw141292 (void) sqlite_finalize(vm, &errmsg); 29474520Snw141292 vm = NULL; 29485696Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 29495696Snw141292 CHECK_NULL(errmsg)); 29504520Snw141292 sqlite_freemem(errmsg); 29514520Snw141292 retcode = IDMAP_ERR_INTERNAL; 29524520Snw141292 goto out; 29534520Snw141292 } 29544520Snw141292 } 29554520Snw141292 29564520Snw141292 out: 29576386Sjp151216 if (sql != NULL) 29586386Sjp151216 sqlite_freemem(sql); 29594520Snw141292 if (retcode == IDMAP_SUCCESS) { 29604864Sbaban if (values[1] != NULL) 29614520Snw141292 res->direction = 29624644Sbaban (strtol(values[1], &end, 10) == 0)? 29634644Sbaban IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; 29644520Snw141292 else 29654644Sbaban res->direction = IDMAP_DIRECTION_W2U; 29666386Sjp151216 29675064Sdm199847 req->id2name = strdup(unixname); 29686616Sdm199847 if (req->id2name == NULL) { 29696616Sdm199847 retcode = IDMAP_ERR_MEMORY; 29706616Sdm199847 } 29716616Sdm199847 } 29726616Sdm199847 29736616Sdm199847 if (retcode == IDMAP_SUCCESS) { 29746386Sjp151216 idmap_namerule_set(rule, values[3], values[2], 29756386Sjp151216 values[0], is_wuser, is_user, strtol(values[4], &end, 10), 29766386Sjp151216 res->direction); 29779021Samw@Sun.COM } 29789021Samw@Sun.COM 29799021Samw@Sun.COM if (retcode != IDMAP_ERR_NOTFOUND) { 29809021Samw@Sun.COM res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED; 29816386Sjp151216 res->info.src = IDMAP_MAP_SRC_NEW; 29824520Snw141292 } 29836616Sdm199847 29845696Snw141292 if (lower_winname != NULL && lower_winname != winname) 29855696Snw141292 free(lower_winname); 29864864Sbaban if (vm != NULL) 29874520Snw141292 (void) sqlite_finalize(vm, NULL); 29884520Snw141292 return (retcode); 29894520Snw141292 } 29904520Snw141292 29914520Snw141292 static 29924520Snw141292 int 29934520Snw141292 get_next_eph_uid(uid_t *next_uid) 29944520Snw141292 { 29954520Snw141292 uid_t uid; 29964520Snw141292 gid_t gid; 29974520Snw141292 int err; 29984520Snw141292 29994520Snw141292 *next_uid = (uid_t)-1; 30004520Snw141292 uid = _idmapdstate.next_uid++; 30014520Snw141292 if (uid >= _idmapdstate.limit_uid) { 30024520Snw141292 if ((err = allocids(0, 8192, &uid, 0, &gid)) != 0) 30034520Snw141292 return (err); 30044520Snw141292 30054520Snw141292 _idmapdstate.limit_uid = uid + 8192; 30064520Snw141292 _idmapdstate.next_uid = uid; 30074520Snw141292 } 30084520Snw141292 *next_uid = uid; 30094520Snw141292 30104520Snw141292 return (0); 30114520Snw141292 } 30124520Snw141292 30134520Snw141292 static 30144520Snw141292 int 30154520Snw141292 get_next_eph_gid(gid_t *next_gid) 30164520Snw141292 { 30174520Snw141292 uid_t uid; 30184520Snw141292 gid_t gid; 30194520Snw141292 int err; 30204520Snw141292 30214520Snw141292 *next_gid = (uid_t)-1; 30224520Snw141292 gid = _idmapdstate.next_gid++; 30234520Snw141292 if (gid >= _idmapdstate.limit_gid) { 30244520Snw141292 if ((err = allocids(0, 0, &uid, 8192, &gid)) != 0) 30254520Snw141292 return (err); 30264520Snw141292 30274520Snw141292 _idmapdstate.limit_gid = gid + 8192; 30284520Snw141292 _idmapdstate.next_gid = gid; 30294520Snw141292 } 30304520Snw141292 *next_gid = gid; 30314520Snw141292 30324520Snw141292 return (0); 30334520Snw141292 } 30344520Snw141292 30354864Sbaban static 30364864Sbaban int 30375696Snw141292 gethash(const char *str, uint32_t num, uint_t htsize) 30385696Snw141292 { 30394864Sbaban uint_t hval, i, len; 30404864Sbaban 30414864Sbaban if (str == NULL) 30424864Sbaban return (0); 30434864Sbaban for (len = strlen(str), hval = 0, i = 0; i < len; i++) { 30444864Sbaban hval += str[i]; 30454864Sbaban hval += (hval << 10); 30464864Sbaban hval ^= (hval >> 6); 30474864Sbaban } 30484864Sbaban for (str = (const char *)&num, i = 0; i < sizeof (num); i++) { 30494864Sbaban hval += str[i]; 30504864Sbaban hval += (hval << 10); 30514864Sbaban hval ^= (hval >> 6); 30524864Sbaban } 30534864Sbaban hval += (hval << 3); 30544864Sbaban hval ^= (hval >> 11); 30554864Sbaban hval += (hval << 15); 30564864Sbaban return (hval % htsize); 30574864Sbaban } 30584864Sbaban 30594864Sbaban static 30604864Sbaban int 30614864Sbaban get_from_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid, 30625696Snw141292 uid_t *pid) 30635696Snw141292 { 30644864Sbaban uint_t next, key; 30654864Sbaban uint_t htsize = state->sid_history_size; 30664864Sbaban idmap_sid *sid; 30674864Sbaban 30684864Sbaban next = gethash(prefix, rid, htsize); 30694864Sbaban while (next != htsize) { 30704864Sbaban key = state->sid_history[next].key; 30714864Sbaban if (key == htsize) 30724864Sbaban return (0); 30734864Sbaban sid = &state->batch->idmap_mapping_batch_val[key].id1. 30744864Sbaban idmap_id_u.sid; 30754864Sbaban if (sid->rid == rid && strcmp(sid->prefix, prefix) == 0) { 30764864Sbaban *pid = state->result->ids.ids_val[key].id. 30774864Sbaban idmap_id_u.uid; 30784864Sbaban return (1); 30794864Sbaban } 30804864Sbaban next = state->sid_history[next].next; 30814864Sbaban } 30824864Sbaban return (0); 30834864Sbaban } 30844864Sbaban 30854864Sbaban static 30864864Sbaban void 30875696Snw141292 add_to_sid_history(lookup_state_t *state, const char *prefix, uint32_t rid) 30885696Snw141292 { 30894864Sbaban uint_t hash, next; 30904864Sbaban uint_t htsize = state->sid_history_size; 30914864Sbaban 30924864Sbaban hash = next = gethash(prefix, rid, htsize); 30934864Sbaban while (state->sid_history[next].key != htsize) { 30944864Sbaban next++; 30954864Sbaban next %= htsize; 30964864Sbaban } 30974864Sbaban state->sid_history[next].key = state->curpos; 30984864Sbaban if (hash == next) 30994864Sbaban return; 31004864Sbaban state->sid_history[next].next = state->sid_history[hash].next; 31014864Sbaban state->sid_history[hash].next = next; 31024864Sbaban } 31034520Snw141292 31045731Sbaban void 31055731Sbaban cleanup_lookup_state(lookup_state_t *state) 31065731Sbaban { 31075731Sbaban free(state->sid_history); 31085731Sbaban free(state->ad_unixuser_attr); 31095731Sbaban free(state->ad_unixgroup_attr); 31106616Sdm199847 free(state->nldap_winname_attr); 31116616Sdm199847 free(state->defdom); 31125731Sbaban } 31135731Sbaban 31144520Snw141292 /* ARGSUSED */ 31154520Snw141292 static 31164520Snw141292 idmap_retcode 31176616Sdm199847 dynamic_ephemeral_mapping(lookup_state_t *state, 31185696Snw141292 idmap_mapping *req, idmap_id_res *res) 31195696Snw141292 { 31204520Snw141292 31214520Snw141292 uid_t next_pid; 31224520Snw141292 31234864Sbaban res->direction = IDMAP_DIRECTION_BI; 31244864Sbaban 31256386Sjp151216 if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 31266386Sjp151216 res->info.how.map_type = IDMAP_MAP_TYPE_EPHEMERAL; 31276386Sjp151216 res->info.src = IDMAP_MAP_SRC_CACHE; 31284864Sbaban return (IDMAP_SUCCESS); 31296386Sjp151216 } 31304864Sbaban 31314864Sbaban if (state->sid_history != NULL && 31324864Sbaban get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, 31334864Sbaban req->id1.idmap_id_u.sid.rid, &next_pid)) { 31344864Sbaban res->id.idmap_id_u.uid = next_pid; 31356386Sjp151216 res->info.how.map_type = IDMAP_MAP_TYPE_EPHEMERAL; 31366386Sjp151216 res->info.src = IDMAP_MAP_SRC_NEW; 31374864Sbaban return (IDMAP_SUCCESS); 31384864Sbaban } 31394864Sbaban 31404864Sbaban if (res->id.idtype == IDMAP_UID) { 31414520Snw141292 if (get_next_eph_uid(&next_pid) != 0) 31424520Snw141292 return (IDMAP_ERR_INTERNAL); 31434520Snw141292 res->id.idmap_id_u.uid = next_pid; 31444520Snw141292 } else { 31454520Snw141292 if (get_next_eph_gid(&next_pid) != 0) 31464520Snw141292 return (IDMAP_ERR_INTERNAL); 31474520Snw141292 res->id.idmap_id_u.gid = next_pid; 31484520Snw141292 } 31494520Snw141292 31506386Sjp151216 res->info.how.map_type = IDMAP_MAP_TYPE_EPHEMERAL; 31516386Sjp151216 res->info.src = IDMAP_MAP_SRC_NEW; 31524864Sbaban if (state->sid_history != NULL) 31534864Sbaban add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, 31544864Sbaban req->id1.idmap_id_u.sid.rid); 31554864Sbaban 31564520Snw141292 return (IDMAP_SUCCESS); 31574520Snw141292 } 31584520Snw141292 31594520Snw141292 idmap_retcode 31606616Sdm199847 sid2pid_second_pass(lookup_state_t *state, 31615696Snw141292 idmap_mapping *req, idmap_id_res *res) 31625696Snw141292 { 31634520Snw141292 idmap_retcode retcode; 31644520Snw141292 31654520Snw141292 /* Check if second pass is needed */ 31665731Sbaban if (ARE_WE_DONE(req->direction)) 31674520Snw141292 return (res->retcode); 31684520Snw141292 31694520Snw141292 /* Get status from previous pass */ 31705731Sbaban retcode = res->retcode; 31717031Snw141292 if (retcode != IDMAP_SUCCESS && state->eph_map_unres_sids && 31727031Snw141292 !EMPTY_STRING(req->id1.idmap_id_u.sid.prefix) && 31737031Snw141292 EMPTY_STRING(req->id1name)) { 31747031Snw141292 /* 31757031Snw141292 * We are asked to map an unresolvable SID to a UID or 31767031Snw141292 * GID, but, which? We'll treat all unresolvable SIDs 31777031Snw141292 * as users unless the caller specified which of a UID 31787031Snw141292 * or GID they want. 31797031Snw141292 */ 31807818SNicolas.Williams@Sun.COM if (req->id1.idtype == IDMAP_SID) 31817818SNicolas.Williams@Sun.COM req->id1.idtype = IDMAP_USID; 31827031Snw141292 if (res->id.idtype == IDMAP_POSIXID) 31837031Snw141292 res->id.idtype = IDMAP_UID; 31847031Snw141292 goto do_eph; 31857031Snw141292 } 31865731Sbaban if (retcode != IDMAP_SUCCESS) 31875731Sbaban goto out; 31885731Sbaban 31895731Sbaban /* 319010504SKeyur.Desai@Sun.COM * There are two ways we might get here with a Posix ID: 319110504SKeyur.Desai@Sun.COM * - It could be from an expired ephemeral cache entry. 319210504SKeyur.Desai@Sun.COM * - It could be from IDMU. 319310504SKeyur.Desai@Sun.COM * If it's from IDMU, we need to look up the name, for name-based 319410504SKeyur.Desai@Sun.COM * requests and the cache. 319510504SKeyur.Desai@Sun.COM */ 319610504SKeyur.Desai@Sun.COM if (!IS_EPHEMERAL(res->id.idmap_id_u.uid) && 319710504SKeyur.Desai@Sun.COM res->id.idmap_id_u.uid != SENTINEL_PID) { 319810504SKeyur.Desai@Sun.COM if (req->id2name == NULL) { 319910504SKeyur.Desai@Sun.COM /* 320010504SKeyur.Desai@Sun.COM * If the lookup fails, go ahead anyway. 320110504SKeyur.Desai@Sun.COM * The general UNIX rule is that it's OK to 320210504SKeyur.Desai@Sun.COM * have a UID or GID that isn't in the 320310504SKeyur.Desai@Sun.COM * name service. 320410504SKeyur.Desai@Sun.COM */ 320510504SKeyur.Desai@Sun.COM (void) ns_lookup_bypid(res->id.idmap_id_u.uid, 320610504SKeyur.Desai@Sun.COM res->id.idtype == IDMAP_UID, &req->id2name); 320710504SKeyur.Desai@Sun.COM } 320810504SKeyur.Desai@Sun.COM goto out; 320910504SKeyur.Desai@Sun.COM } 321010504SKeyur.Desai@Sun.COM 321110504SKeyur.Desai@Sun.COM /* 32125731Sbaban * If directory-based name mapping is enabled then the unixname 32135731Sbaban * may already have been retrieved from the AD object (AD-mode or 32145731Sbaban * mixed-mode) or from native LDAP object (nldap-mode) -- done. 32155731Sbaban */ 32165731Sbaban if (req->id2name != NULL) { 32175731Sbaban assert(res->id.idtype != IDMAP_POSIXID); 32185731Sbaban if (AD_MODE(res->id.idtype, state)) 32195731Sbaban res->direction = IDMAP_DIRECTION_BI; 32205731Sbaban else if (NLDAP_MODE(res->id.idtype, state)) 32215731Sbaban res->direction = IDMAP_DIRECTION_BI; 32225731Sbaban else if (MIXED_MODE(res->id.idtype, state)) 32235731Sbaban res->direction = IDMAP_DIRECTION_W2U; 32245731Sbaban 32255731Sbaban /* 32265731Sbaban * Special case: (1) If the ad_unixuser_attr and 32275731Sbaban * ad_unixgroup_attr uses the same attribute 32285731Sbaban * name and (2) if this is a diagonal mapping 32295731Sbaban * request and (3) the unixname has been retrieved 32305731Sbaban * from the AD object -- then we ignore it and fallback 32315731Sbaban * to name-based mapping rules and ephemeral mapping 32325731Sbaban * 32335731Sbaban * Example: 32345731Sbaban * Properties: 32355731Sbaban * config/ad_unixuser_attr = "unixname" 32365731Sbaban * config/ad_unixgroup_attr = "unixname" 32375731Sbaban * AD user object: 32385731Sbaban * dn: cn=bob ... 32395731Sbaban * objectclass: user 32405731Sbaban * sam: bob 32415731Sbaban * unixname: bob1234 32425731Sbaban * AD group object: 32435731Sbaban * dn: cn=winadmins ... 32445731Sbaban * objectclass: group 32455731Sbaban * sam: winadmins 32465731Sbaban * unixname: unixadmins 32475731Sbaban * 32485731Sbaban * In this example whether "unixname" refers to a unixuser 32495731Sbaban * or unixgroup depends upon the AD object. 32505731Sbaban * 32515731Sbaban * $idmap show -c winname:bob gid 32525731Sbaban * AD lookup by "samAccountName=bob" for 32535731Sbaban * "ad_unixgroup_attr (i.e unixname)" for directory-based 32545731Sbaban * mapping would get "bob1234" which is not what we want. 32555731Sbaban * Now why not getgrnam_r("bob1234") and use it if it 32565731Sbaban * is indeed a unixgroup? That's because Unix can have 32575731Sbaban * users and groups with the same name and we clearly 32585731Sbaban * don't know the intention of the admin here. 32595731Sbaban * Therefore we ignore this and fallback to name-based 32605731Sbaban * mapping rules or ephemeral mapping. 32615731Sbaban */ 32625731Sbaban if ((AD_MODE(res->id.idtype, state) || 32635731Sbaban MIXED_MODE(res->id.idtype, state)) && 32645731Sbaban state->ad_unixuser_attr != NULL && 32655731Sbaban state->ad_unixgroup_attr != NULL && 32665731Sbaban strcasecmp(state->ad_unixuser_attr, 32675731Sbaban state->ad_unixgroup_attr) == 0 && 32685731Sbaban ((req->id1.idtype == IDMAP_USID && 32695731Sbaban res->id.idtype == IDMAP_GID) || 32705731Sbaban (req->id1.idtype == IDMAP_GSID && 32715731Sbaban res->id.idtype == IDMAP_UID))) { 32725731Sbaban free(req->id2name); 32735731Sbaban req->id2name = NULL; 32745731Sbaban res->id.idmap_id_u.uid = SENTINEL_PID; 32755731Sbaban /* fallback */ 32765731Sbaban } else { 32775731Sbaban if (res->id.idmap_id_u.uid == SENTINEL_PID) 32785731Sbaban retcode = ns_lookup_byname(req->id2name, 32795731Sbaban NULL, &res->id); 32805731Sbaban /* 32816616Sdm199847 * If ns_lookup_byname() fails that means the 32826616Sdm199847 * unixname (req->id2name), which was obtained 32836616Sdm199847 * from the AD object by directory-based mapping, 32846616Sdm199847 * is not a valid Unix user/group and therefore 32856616Sdm199847 * we return the error to the client instead of 32866616Sdm199847 * doing rule-based mapping or ephemeral mapping. 32876616Sdm199847 * This way the client can detect the issue. 32885731Sbaban */ 32895731Sbaban goto out; 32904520Snw141292 } 32914520Snw141292 } 32924520Snw141292 32936386Sjp151216 /* Free any mapping info from Directory based mapping */ 32946386Sjp151216 if (res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN) 32956386Sjp151216 idmap_info_free(&res->info); 32966386Sjp151216 32975731Sbaban /* 32985731Sbaban * If we don't have unixname then evaluate local name-based 32995731Sbaban * mapping rules. 33005731Sbaban */ 33016616Sdm199847 retcode = name_based_mapping_sid2pid(state, req, res); 33025731Sbaban if (retcode != IDMAP_ERR_NOTFOUND) 33034520Snw141292 goto out; 33044520Snw141292 33057031Snw141292 do_eph: 33065731Sbaban /* If not found, do ephemeral mapping */ 33076616Sdm199847 retcode = dynamic_ephemeral_mapping(state, req, res); 33084520Snw141292 33094520Snw141292 out: 33104520Snw141292 res->retcode = idmap_stat4prot(retcode); 33115731Sbaban if (res->retcode != IDMAP_SUCCESS) { 33125731Sbaban req->direction = _IDMAP_F_DONE; 33135731Sbaban res->id.idmap_id_u.uid = UID_NOBODY; 33145731Sbaban } 33155731Sbaban if (!ARE_WE_DONE(req->direction)) 33165731Sbaban state->sid2pid_done = FALSE; 33174520Snw141292 return (retcode); 33184520Snw141292 } 33194520Snw141292 33204520Snw141292 idmap_retcode 33216616Sdm199847 update_cache_pid2sid(lookup_state_t *state, 33225696Snw141292 idmap_mapping *req, idmap_id_res *res) 33235696Snw141292 { 33244520Snw141292 char *sql = NULL; 33254520Snw141292 idmap_retcode retcode; 33266386Sjp151216 char *map_dn = NULL; 33276386Sjp151216 char *map_attr = NULL; 33286386Sjp151216 char *map_value = NULL; 33296386Sjp151216 char *map_windomain = NULL; 33306386Sjp151216 char *map_winname = NULL; 33316386Sjp151216 char *map_unixname = NULL; 33326386Sjp151216 int map_is_nt4 = FALSE; 33334520Snw141292 33344520Snw141292 /* Check if we need to cache anything */ 33355731Sbaban if (ARE_WE_DONE(req->direction)) 33364520Snw141292 return (IDMAP_SUCCESS); 33374520Snw141292 33384520Snw141292 /* We don't cache negative entries */ 33394520Snw141292 if (res->retcode != IDMAP_SUCCESS) 33404520Snw141292 return (IDMAP_SUCCESS); 33414520Snw141292 33425731Sbaban assert(res->direction != IDMAP_DIRECTION_UNDEF); 33436386Sjp151216 assert(req->id1.idmap_id_u.uid != SENTINEL_PID); 33446386Sjp151216 assert(res->id.idtype != IDMAP_SID); 33456386Sjp151216 334610504SKeyur.Desai@Sun.COM /* 334710504SKeyur.Desai@Sun.COM * If we've gotten to this point and we *still* don't know the 334810504SKeyur.Desai@Sun.COM * unixname, well, we'd like to have it now for the cache. 334910504SKeyur.Desai@Sun.COM * 335010504SKeyur.Desai@Sun.COM * If we truly always need it for the cache, we should probably 335110504SKeyur.Desai@Sun.COM * look it up once at the beginning, rather than "at need" in 335210504SKeyur.Desai@Sun.COM * several places as is now done. However, it's not really clear 335310504SKeyur.Desai@Sun.COM * that we *do* need it in the cache; there's a decent argument 335410504SKeyur.Desai@Sun.COM * that the cache should contain only SIDs and PIDs, so we'll 335510504SKeyur.Desai@Sun.COM * leave our options open by doing it "at need" here too. 335610504SKeyur.Desai@Sun.COM * 335710504SKeyur.Desai@Sun.COM * If we can't find it... c'est la vie. 335810504SKeyur.Desai@Sun.COM */ 335910504SKeyur.Desai@Sun.COM if (req->id1name == NULL) { 336010504SKeyur.Desai@Sun.COM (void) ns_lookup_bypid(req->id1.idmap_id_u.uid, 336110504SKeyur.Desai@Sun.COM req->id1.idtype == IDMAP_UID, &req->id1name); 336210504SKeyur.Desai@Sun.COM } 336310504SKeyur.Desai@Sun.COM 33646386Sjp151216 assert(res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN); 33656386Sjp151216 switch (res->info.how.map_type) { 33666386Sjp151216 case IDMAP_MAP_TYPE_DS_AD: 33676386Sjp151216 map_dn = res->info.how.idmap_how_u.ad.dn; 33686386Sjp151216 map_attr = res->info.how.idmap_how_u.ad.attr; 33696386Sjp151216 map_value = res->info.how.idmap_how_u.ad.value; 33706386Sjp151216 break; 33716386Sjp151216 33726386Sjp151216 case IDMAP_MAP_TYPE_DS_NLDAP: 33736386Sjp151216 map_dn = res->info.how.idmap_how_u.nldap.dn; 33746386Sjp151216 map_attr = res->info.how.idmap_how_u.nldap.attr; 33756386Sjp151216 map_value = res->info.how.idmap_how_u.nldap.value; 33766386Sjp151216 break; 33776386Sjp151216 33786386Sjp151216 case IDMAP_MAP_TYPE_RULE_BASED: 33796386Sjp151216 map_windomain = res->info.how.idmap_how_u.rule.windomain; 33806386Sjp151216 map_winname = res->info.how.idmap_how_u.rule.winname; 33816386Sjp151216 map_unixname = res->info.how.idmap_how_u.rule.unixname; 33826386Sjp151216 map_is_nt4 = res->info.how.idmap_how_u.rule.is_nt4; 33836386Sjp151216 break; 33846386Sjp151216 33856386Sjp151216 case IDMAP_MAP_TYPE_EPHEMERAL: 33866386Sjp151216 break; 33876386Sjp151216 33886386Sjp151216 case IDMAP_MAP_TYPE_LOCAL_SID: 33896386Sjp151216 break; 33906386Sjp151216 339110504SKeyur.Desai@Sun.COM case IDMAP_MAP_TYPE_IDMU: 339210504SKeyur.Desai@Sun.COM map_dn = res->info.how.idmap_how_u.idmu.dn; 339310504SKeyur.Desai@Sun.COM map_attr = res->info.how.idmap_how_u.idmu.attr; 339410504SKeyur.Desai@Sun.COM map_value = res->info.how.idmap_how_u.idmu.value; 339510504SKeyur.Desai@Sun.COM break; 339610504SKeyur.Desai@Sun.COM 33976386Sjp151216 default: 33986386Sjp151216 /* Dont cache other mapping types */ 33996386Sjp151216 assert(FALSE); 34006386Sjp151216 } 34015731Sbaban 34024520Snw141292 /* 34034520Snw141292 * Using NULL for u2w instead of 0 so that our trigger allows 34044520Snw141292 * the same pid to be the destination in multiple entries 34054520Snw141292 */ 34064520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 34075696Snw141292 "(sidprefix, rid, windomain, canon_winname, pid, unixname, " 34086386Sjp151216 "is_user, is_wuser, expiration, w2u, u2w, " 34096386Sjp151216 "map_type, map_dn, map_attr, map_value, map_windomain, " 34106386Sjp151216 "map_winname, map_unixname, map_is_nt4) " 34115696Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " 34126386Sjp151216 "strftime('%%s','now') + 600, %q, 1, " 34136386Sjp151216 "%d, %Q, %Q, %Q, %Q, %Q, %Q, %d); ", 34145696Snw141292 res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, 34155696Snw141292 req->id2domain, req->id2name, req->id1.idmap_id_u.uid, 34165696Snw141292 req->id1name, (req->id1.idtype == IDMAP_UID) ? 1 : 0, 34175731Sbaban (res->id.idtype == IDMAP_USID) ? 1 : 0, 34186386Sjp151216 (res->direction == 0) ? "1" : NULL, 34196386Sjp151216 res->info.how.map_type, map_dn, map_attr, map_value, 34206386Sjp151216 map_windomain, map_winname, map_unixname, map_is_nt4); 34214520Snw141292 34224520Snw141292 if (sql == NULL) { 34234520Snw141292 retcode = IDMAP_ERR_INTERNAL; 34244520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 34254520Snw141292 goto out; 34264520Snw141292 } 34274520Snw141292 34286616Sdm199847 retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql); 34294520Snw141292 if (retcode != IDMAP_SUCCESS) 34304520Snw141292 goto out; 34314520Snw141292 34324520Snw141292 state->pid2sid_done = FALSE; 34334520Snw141292 sqlite_freemem(sql); 34344520Snw141292 sql = NULL; 34354520Snw141292 34365731Sbaban /* Check if we need to update namecache */ 34375731Sbaban if (req->direction & _IDMAP_F_DONT_UPDATE_NAMECACHE) 34384520Snw141292 goto out; 34394520Snw141292 34405064Sdm199847 if (req->id2name == NULL) 34414520Snw141292 goto out; 34424520Snw141292 34434520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 34445696Snw141292 "(sidprefix, rid, canon_name, domain, type, expiration) " 34455696Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 34465696Snw141292 res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, 34475696Snw141292 req->id2name, req->id2domain, 34485731Sbaban (res->id.idtype == IDMAP_USID) ? _IDMAP_T_USER : _IDMAP_T_GROUP); 34494520Snw141292 34504520Snw141292 if (sql == NULL) { 34514520Snw141292 retcode = IDMAP_ERR_INTERNAL; 34524520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 34534520Snw141292 goto out; 34544520Snw141292 } 34554520Snw141292 34566616Sdm199847 retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql); 34574520Snw141292 34584520Snw141292 out: 34596386Sjp151216 if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO)) 34606386Sjp151216 idmap_info_free(&res->info); 34614864Sbaban if (sql != NULL) 34624520Snw141292 sqlite_freemem(sql); 34634520Snw141292 return (retcode); 34644520Snw141292 } 34654520Snw141292 34664520Snw141292 idmap_retcode 34676616Sdm199847 update_cache_sid2pid(lookup_state_t *state, 34685696Snw141292 idmap_mapping *req, idmap_id_res *res) 34695696Snw141292 { 34704520Snw141292 char *sql = NULL; 34714520Snw141292 idmap_retcode retcode; 34724520Snw141292 int is_eph_user; 34736386Sjp151216 char *map_dn = NULL; 34746386Sjp151216 char *map_attr = NULL; 34756386Sjp151216 char *map_value = NULL; 34766386Sjp151216 char *map_windomain = NULL; 34776386Sjp151216 char *map_winname = NULL; 34786386Sjp151216 char *map_unixname = NULL; 34796386Sjp151216 int map_is_nt4 = FALSE; 34804520Snw141292 34814520Snw141292 /* Check if we need to cache anything */ 34825731Sbaban if (ARE_WE_DONE(req->direction)) 34834520Snw141292 return (IDMAP_SUCCESS); 34844520Snw141292 34854520Snw141292 /* We don't cache negative entries */ 34864520Snw141292 if (res->retcode != IDMAP_SUCCESS) 34874520Snw141292 return (IDMAP_SUCCESS); 34884520Snw141292 34894520Snw141292 if (req->direction & _IDMAP_F_EXP_EPH_UID) 34904520Snw141292 is_eph_user = 1; 34914520Snw141292 else if (req->direction & _IDMAP_F_EXP_EPH_GID) 34924520Snw141292 is_eph_user = 0; 34934520Snw141292 else 34944520Snw141292 is_eph_user = -1; 34954520Snw141292 34964520Snw141292 if (is_eph_user >= 0 && !IS_EPHEMERAL(res->id.idmap_id_u.uid)) { 34974520Snw141292 sql = sqlite_mprintf("UPDATE idmap_cache " 34985696Snw141292 "SET w2u = 0 WHERE " 34995696Snw141292 "sidprefix = %Q AND rid = %u AND w2u = 1 AND " 35005696Snw141292 "pid >= 2147483648 AND is_user = %d;", 35015696Snw141292 req->id1.idmap_id_u.sid.prefix, 35025696Snw141292 req->id1.idmap_id_u.sid.rid, 35035696Snw141292 is_eph_user); 35044520Snw141292 if (sql == NULL) { 35054520Snw141292 retcode = IDMAP_ERR_INTERNAL; 35064520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 35074520Snw141292 goto out; 35084520Snw141292 } 35094520Snw141292 35106616Sdm199847 retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql); 35114520Snw141292 if (retcode != IDMAP_SUCCESS) 35124520Snw141292 goto out; 35134520Snw141292 35144520Snw141292 sqlite_freemem(sql); 35154520Snw141292 sql = NULL; 35164520Snw141292 } 35174520Snw141292 35185731Sbaban assert(res->direction != IDMAP_DIRECTION_UNDEF); 35196386Sjp151216 assert(res->id.idmap_id_u.uid != SENTINEL_PID); 35206386Sjp151216 35216386Sjp151216 switch (res->info.how.map_type) { 35226386Sjp151216 case IDMAP_MAP_TYPE_DS_AD: 35236386Sjp151216 map_dn = res->info.how.idmap_how_u.ad.dn; 35246386Sjp151216 map_attr = res->info.how.idmap_how_u.ad.attr; 35256386Sjp151216 map_value = res->info.how.idmap_how_u.ad.value; 35266386Sjp151216 break; 35276386Sjp151216 35286386Sjp151216 case IDMAP_MAP_TYPE_DS_NLDAP: 35296386Sjp151216 map_dn = res->info.how.idmap_how_u.nldap.dn; 35306386Sjp151216 map_attr = res->info.how.idmap_how_u.ad.attr; 35316386Sjp151216 map_value = res->info.how.idmap_how_u.nldap.value; 35326386Sjp151216 break; 35336386Sjp151216 35346386Sjp151216 case IDMAP_MAP_TYPE_RULE_BASED: 35356386Sjp151216 map_windomain = res->info.how.idmap_how_u.rule.windomain; 35366386Sjp151216 map_winname = res->info.how.idmap_how_u.rule.winname; 35376386Sjp151216 map_unixname = res->info.how.idmap_how_u.rule.unixname; 35386386Sjp151216 map_is_nt4 = res->info.how.idmap_how_u.rule.is_nt4; 35396386Sjp151216 break; 35406386Sjp151216 35416386Sjp151216 case IDMAP_MAP_TYPE_EPHEMERAL: 35426386Sjp151216 break; 35436386Sjp151216 354410504SKeyur.Desai@Sun.COM case IDMAP_MAP_TYPE_IDMU: 354510504SKeyur.Desai@Sun.COM map_dn = res->info.how.idmap_how_u.idmu.dn; 354610504SKeyur.Desai@Sun.COM map_attr = res->info.how.idmap_how_u.idmu.attr; 354710504SKeyur.Desai@Sun.COM map_value = res->info.how.idmap_how_u.idmu.value; 354810504SKeyur.Desai@Sun.COM break; 354910504SKeyur.Desai@Sun.COM 35506386Sjp151216 default: 35516386Sjp151216 /* Dont cache other mapping types */ 35526386Sjp151216 assert(FALSE); 35536386Sjp151216 } 35545696Snw141292 35554520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " 35565696Snw141292 "(sidprefix, rid, windomain, canon_winname, pid, unixname, " 35576386Sjp151216 "is_user, is_wuser, expiration, w2u, u2w, " 35586386Sjp151216 "map_type, map_dn, map_attr, map_value, map_windomain, " 35596386Sjp151216 "map_winname, map_unixname, map_is_nt4) " 35605696Snw141292 "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " 35616386Sjp151216 "strftime('%%s','now') + 600, 1, %q, " 35626386Sjp151216 "%d, %Q, %Q, %Q, %Q, %Q, %Q, %d);", 35635696Snw141292 req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, 35645731Sbaban (req->id1domain != NULL) ? req->id1domain : "", req->id1name, 35655731Sbaban res->id.idmap_id_u.uid, req->id2name, 35665731Sbaban (res->id.idtype == IDMAP_UID) ? 1 : 0, 35675696Snw141292 (req->id1.idtype == IDMAP_USID) ? 1 : 0, 35686386Sjp151216 (res->direction == 0) ? "1" : NULL, 35696386Sjp151216 res->info.how.map_type, map_dn, map_attr, map_value, 35706386Sjp151216 map_windomain, map_winname, map_unixname, map_is_nt4); 35714520Snw141292 35724520Snw141292 if (sql == NULL) { 35734520Snw141292 retcode = IDMAP_ERR_INTERNAL; 35744520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 35754520Snw141292 goto out; 35764520Snw141292 } 35774520Snw141292 35786616Sdm199847 retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql); 35794520Snw141292 if (retcode != IDMAP_SUCCESS) 35804520Snw141292 goto out; 35814520Snw141292 35824520Snw141292 state->sid2pid_done = FALSE; 35834520Snw141292 sqlite_freemem(sql); 35844520Snw141292 sql = NULL; 35854520Snw141292 35865731Sbaban /* Check if we need to update namecache */ 35875731Sbaban if (req->direction & _IDMAP_F_DONT_UPDATE_NAMECACHE) 35884520Snw141292 goto out; 35894520Snw141292 35905127Sdm199847 if (EMPTY_STRING(req->id1name)) 35914520Snw141292 goto out; 35924520Snw141292 35934520Snw141292 sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " 35945696Snw141292 "(sidprefix, rid, canon_name, domain, type, expiration) " 35955696Snw141292 "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", 35965696Snw141292 req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, 35975696Snw141292 req->id1name, req->id1domain, 35985696Snw141292 (req->id1.idtype == IDMAP_USID) ? _IDMAP_T_USER : _IDMAP_T_GROUP); 35994520Snw141292 36004520Snw141292 if (sql == NULL) { 36014520Snw141292 retcode = IDMAP_ERR_INTERNAL; 36024520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 36034520Snw141292 goto out; 36044520Snw141292 } 36054520Snw141292 36066616Sdm199847 retcode = sql_exec_no_cb(state->cache, IDMAP_CACHENAME, sql); 36074520Snw141292 36084520Snw141292 out: 36096386Sjp151216 if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO)) 36106386Sjp151216 idmap_info_free(&res->info); 36116386Sjp151216 36124864Sbaban if (sql != NULL) 36134520Snw141292 sqlite_freemem(sql); 36144520Snw141292 return (retcode); 36154520Snw141292 } 36164520Snw141292 36175696Snw141292 static 36185696Snw141292 idmap_retcode 36194520Snw141292 lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, 36205696Snw141292 int is_user, int getname) 36215696Snw141292 { 36224520Snw141292 char *end; 36234520Snw141292 char *sql = NULL; 36244520Snw141292 const char **values; 36254520Snw141292 sqlite_vm *vm = NULL; 36264520Snw141292 int ncol; 36274520Snw141292 idmap_retcode retcode = IDMAP_SUCCESS; 36284520Snw141292 time_t curtime; 36295731Sbaban idmap_id_type idtype; 36304520Snw141292 36314520Snw141292 /* Current time */ 36324520Snw141292 errno = 0; 36334520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 36345696Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 36355696Snw141292 strerror(errno)); 36364520Snw141292 retcode = IDMAP_ERR_INTERNAL; 36374520Snw141292 goto out; 36384520Snw141292 } 36394520Snw141292 36405731Sbaban /* SQL to lookup the cache by pid or by unixname */ 36415731Sbaban if (req->id1.idmap_id_u.uid != SENTINEL_PID) { 36426386Sjp151216 sql = sqlite_mprintf("SELECT sidprefix, rid, " 36436386Sjp151216 "canon_winname, windomain, w2u, is_wuser, " 36446386Sjp151216 "map_type, map_dn, map_attr, map_value, map_windomain, " 36456386Sjp151216 "map_winname, map_unixname, map_is_nt4 " 36465731Sbaban "FROM idmap_cache WHERE " 36475731Sbaban "pid = %u AND u2w = 1 AND is_user = %d AND " 36485731Sbaban "(pid >= 2147483648 OR " 36495731Sbaban "(expiration = 0 OR expiration ISNULL OR " 36505731Sbaban "expiration > %d));", 36515731Sbaban req->id1.idmap_id_u.uid, is_user, curtime); 36525731Sbaban } else if (req->id1name != NULL) { 36536386Sjp151216 sql = sqlite_mprintf("SELECT sidprefix, rid, " 36546386Sjp151216 "canon_winname, windomain, w2u, is_wuser, " 36556386Sjp151216 "map_type, map_dn, map_attr, map_value, map_windomain, " 36566386Sjp151216 "map_winname, map_unixname, map_is_nt4 " 36575731Sbaban "FROM idmap_cache WHERE " 36585731Sbaban "unixname = %Q AND u2w = 1 AND is_user = %d AND " 36595731Sbaban "(pid >= 2147483648 OR " 36605731Sbaban "(expiration = 0 OR expiration ISNULL OR " 36615731Sbaban "expiration > %d));", 36625731Sbaban req->id1name, is_user, curtime); 36636386Sjp151216 } else { 36646386Sjp151216 retcode = IDMAP_ERR_ARG; 36656386Sjp151216 goto out; 36665731Sbaban } 36675731Sbaban 36684520Snw141292 if (sql == NULL) { 36694520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 36704520Snw141292 retcode = IDMAP_ERR_MEMORY; 36714520Snw141292 goto out; 36724520Snw141292 } 36736386Sjp151216 retcode = sql_compile_n_step_once( 36746386Sjp151216 cache, sql, &vm, &ncol, 14, &values); 36754520Snw141292 sqlite_freemem(sql); 36764520Snw141292 36774520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) 36784520Snw141292 goto out; 36794520Snw141292 else if (retcode == IDMAP_SUCCESS) { 36804520Snw141292 /* sanity checks */ 36814520Snw141292 if (values[0] == NULL || values[1] == NULL) { 36824520Snw141292 retcode = IDMAP_ERR_CACHE; 36834520Snw141292 goto out; 36844520Snw141292 } 36854520Snw141292 36865731Sbaban switch (res->id.idtype) { 36874520Snw141292 case IDMAP_SID: 36885696Snw141292 case IDMAP_USID: 36895696Snw141292 case IDMAP_GSID: 36905731Sbaban idtype = strtol(values[5], &end, 10) == 1 36915696Snw141292 ? IDMAP_USID : IDMAP_GSID; 36925696Snw141292 36935731Sbaban if (res->id.idtype == IDMAP_USID && 36945731Sbaban idtype != IDMAP_USID) { 36955696Snw141292 retcode = IDMAP_ERR_NOTUSER; 36965696Snw141292 goto out; 36975731Sbaban } else if (res->id.idtype == IDMAP_GSID && 36985731Sbaban idtype != IDMAP_GSID) { 36995696Snw141292 retcode = IDMAP_ERR_NOTGROUP; 37005696Snw141292 goto out; 37015696Snw141292 } 37025731Sbaban res->id.idtype = idtype; 37035696Snw141292 37044520Snw141292 res->id.idmap_id_u.sid.rid = 37055696Snw141292 strtoul(values[1], &end, 10); 37064520Snw141292 res->id.idmap_id_u.sid.prefix = strdup(values[0]); 37074520Snw141292 if (res->id.idmap_id_u.sid.prefix == NULL) { 37084520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 37094520Snw141292 retcode = IDMAP_ERR_MEMORY; 37104520Snw141292 goto out; 37114520Snw141292 } 37124520Snw141292 37134864Sbaban if (values[4] != NULL) 37144520Snw141292 res->direction = 37154644Sbaban (strtol(values[4], &end, 10) == 0)? 37164644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 37174520Snw141292 else 37184644Sbaban res->direction = IDMAP_DIRECTION_U2W; 37194520Snw141292 37204520Snw141292 if (getname == 0 || values[2] == NULL) 37214520Snw141292 break; 37225064Sdm199847 req->id2name = strdup(values[2]); 37235064Sdm199847 if (req->id2name == NULL) { 37244520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 37254520Snw141292 retcode = IDMAP_ERR_MEMORY; 37264520Snw141292 goto out; 37274520Snw141292 } 37284520Snw141292 37294520Snw141292 if (values[3] == NULL) 37304520Snw141292 break; 37315064Sdm199847 req->id2domain = strdup(values[3]); 37325064Sdm199847 if (req->id2domain == NULL) { 37334520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 37344520Snw141292 retcode = IDMAP_ERR_MEMORY; 37354520Snw141292 goto out; 37364520Snw141292 } 37375696Snw141292 37384520Snw141292 break; 37394520Snw141292 default: 37404520Snw141292 retcode = IDMAP_ERR_NOTSUPPORTED; 37414520Snw141292 break; 37424520Snw141292 } 37436386Sjp151216 if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { 37446386Sjp151216 res->info.src = IDMAP_MAP_SRC_CACHE; 37456386Sjp151216 res->info.how.map_type = strtoul(values[6], &end, 10); 37466386Sjp151216 switch (res->info.how.map_type) { 37476386Sjp151216 case IDMAP_MAP_TYPE_DS_AD: 37486386Sjp151216 res->info.how.idmap_how_u.ad.dn = 37496386Sjp151216 strdup(values[7]); 37506386Sjp151216 res->info.how.idmap_how_u.ad.attr = 37516386Sjp151216 strdup(values[8]); 37526386Sjp151216 res->info.how.idmap_how_u.ad.value = 37536386Sjp151216 strdup(values[9]); 37546386Sjp151216 break; 37556386Sjp151216 37566386Sjp151216 case IDMAP_MAP_TYPE_DS_NLDAP: 37576386Sjp151216 res->info.how.idmap_how_u.nldap.dn = 37586386Sjp151216 strdup(values[7]); 37596386Sjp151216 res->info.how.idmap_how_u.nldap.attr = 37606386Sjp151216 strdup(values[8]); 37616386Sjp151216 res->info.how.idmap_how_u.nldap.value = 37626386Sjp151216 strdup(values[9]); 37636386Sjp151216 break; 37646386Sjp151216 37656386Sjp151216 case IDMAP_MAP_TYPE_RULE_BASED: 37666386Sjp151216 res->info.how.idmap_how_u.rule.windomain = 37676386Sjp151216 strdup(values[10]); 37686386Sjp151216 res->info.how.idmap_how_u.rule.winname = 37696386Sjp151216 strdup(values[11]); 37706386Sjp151216 res->info.how.idmap_how_u.rule.unixname = 37716386Sjp151216 strdup(values[12]); 37726386Sjp151216 res->info.how.idmap_how_u.rule.is_nt4 = 37736386Sjp151216 strtoul(values[13], &end, 10); 37746386Sjp151216 res->info.how.idmap_how_u.rule.is_user = 37756386Sjp151216 is_user; 37766386Sjp151216 res->info.how.idmap_how_u.rule.is_wuser = 37776386Sjp151216 strtol(values[5], &end, 10); 37786386Sjp151216 break; 37796386Sjp151216 37806386Sjp151216 case IDMAP_MAP_TYPE_EPHEMERAL: 37816386Sjp151216 break; 37826386Sjp151216 37836386Sjp151216 case IDMAP_MAP_TYPE_LOCAL_SID: 37846386Sjp151216 break; 37856386Sjp151216 37866386Sjp151216 case IDMAP_MAP_TYPE_KNOWN_SID: 37876386Sjp151216 break; 37886386Sjp151216 378910504SKeyur.Desai@Sun.COM case IDMAP_MAP_TYPE_IDMU: 379010504SKeyur.Desai@Sun.COM res->info.how.idmap_how_u.idmu.dn = 379110504SKeyur.Desai@Sun.COM strdup(values[7]); 379210504SKeyur.Desai@Sun.COM res->info.how.idmap_how_u.idmu.attr = 379310504SKeyur.Desai@Sun.COM strdup(values[8]); 379410504SKeyur.Desai@Sun.COM res->info.how.idmap_how_u.idmu.value = 379510504SKeyur.Desai@Sun.COM strdup(values[9]); 379610504SKeyur.Desai@Sun.COM break; 379710504SKeyur.Desai@Sun.COM 37986386Sjp151216 default: 379910504SKeyur.Desai@Sun.COM /* Unknown mapping type */ 38006386Sjp151216 assert(FALSE); 38016386Sjp151216 } 38026386Sjp151216 } 38034520Snw141292 } 38044520Snw141292 38054520Snw141292 out: 38064864Sbaban if (vm != NULL) 38074520Snw141292 (void) sqlite_finalize(vm, NULL); 38084520Snw141292 return (retcode); 38094520Snw141292 } 38104520Snw141292 38119422SAfshin.Ardakani@Sun.COM /* 38129422SAfshin.Ardakani@Sun.COM * Given: 38139422SAfshin.Ardakani@Sun.COM * cache sqlite handle 38149422SAfshin.Ardakani@Sun.COM * name Windows user name 38159422SAfshin.Ardakani@Sun.COM * domain Windows domain name 38169422SAfshin.Ardakani@Sun.COM * 38179422SAfshin.Ardakani@Sun.COM * Return: Error code 38189422SAfshin.Ardakani@Sun.COM * 38199422SAfshin.Ardakani@Sun.COM * *canonname Canonical name (if canonname is non-NULL) [1] 38209422SAfshin.Ardakani@Sun.COM * *sidprefix SID prefix [1] 38219422SAfshin.Ardakani@Sun.COM * *rid RID 38229422SAfshin.Ardakani@Sun.COM * *type Type of name 38239422SAfshin.Ardakani@Sun.COM * 38249422SAfshin.Ardakani@Sun.COM * [1] malloc'ed, NULL on error 38259422SAfshin.Ardakani@Sun.COM */ 38265696Snw141292 static 38275696Snw141292 idmap_retcode 38284520Snw141292 lookup_cache_name2sid(sqlite *cache, const char *name, const char *domain, 38295696Snw141292 char **canonname, char **sidprefix, idmap_rid_t *rid, int *type) 38305696Snw141292 { 38315696Snw141292 char *end, *lower_name; 38329422SAfshin.Ardakani@Sun.COM char *sql; 38334520Snw141292 const char **values; 38344520Snw141292 sqlite_vm *vm = NULL; 38354520Snw141292 int ncol; 38364520Snw141292 time_t curtime; 38379422SAfshin.Ardakani@Sun.COM idmap_retcode retcode; 38389422SAfshin.Ardakani@Sun.COM 38399422SAfshin.Ardakani@Sun.COM *sidprefix = NULL; 38409422SAfshin.Ardakani@Sun.COM if (canonname != NULL) 38419422SAfshin.Ardakani@Sun.COM *canonname = NULL; 38424520Snw141292 38434520Snw141292 /* Get current time */ 38444520Snw141292 errno = 0; 38454520Snw141292 if ((curtime = time(NULL)) == (time_t)-1) { 38465696Snw141292 idmapdlog(LOG_ERR, "Failed to get current time (%s)", 38475696Snw141292 strerror(errno)); 38484520Snw141292 retcode = IDMAP_ERR_INTERNAL; 38494520Snw141292 goto out; 38504520Snw141292 } 38514520Snw141292 38524520Snw141292 /* SQL to lookup the cache */ 38535696Snw141292 if ((lower_name = tolower_u8(name)) == NULL) 38545696Snw141292 lower_name = (char *)name; 38555696Snw141292 sql = sqlite_mprintf("SELECT sidprefix, rid, type, canon_name " 38565696Snw141292 "FROM name_cache WHERE name = %Q AND domain = %Q AND " 38575696Snw141292 "(expiration = 0 OR expiration ISNULL OR " 38585696Snw141292 "expiration > %d);", lower_name, domain, curtime); 38595696Snw141292 if (lower_name != name) 38605696Snw141292 free(lower_name); 38614520Snw141292 if (sql == NULL) { 38624520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 38634520Snw141292 retcode = IDMAP_ERR_MEMORY; 38644520Snw141292 goto out; 38654520Snw141292 } 38665696Snw141292 retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 4, &values); 38679422SAfshin.Ardakani@Sun.COM 38684520Snw141292 sqlite_freemem(sql); 38694520Snw141292 38709422SAfshin.Ardakani@Sun.COM if (retcode != IDMAP_SUCCESS) 38719422SAfshin.Ardakani@Sun.COM goto out; 38729422SAfshin.Ardakani@Sun.COM 38739422SAfshin.Ardakani@Sun.COM if (type != NULL) { 38749422SAfshin.Ardakani@Sun.COM if (values[2] == NULL) { 38755731Sbaban retcode = IDMAP_ERR_CACHE; 38765731Sbaban goto out; 38775731Sbaban } 38789422SAfshin.Ardakani@Sun.COM *type = strtol(values[2], &end, 10); 38799422SAfshin.Ardakani@Sun.COM } 38809422SAfshin.Ardakani@Sun.COM 38819422SAfshin.Ardakani@Sun.COM if (values[0] == NULL || values[1] == NULL) { 38829422SAfshin.Ardakani@Sun.COM retcode = IDMAP_ERR_CACHE; 38839422SAfshin.Ardakani@Sun.COM goto out; 38849422SAfshin.Ardakani@Sun.COM } 38859422SAfshin.Ardakani@Sun.COM 38869422SAfshin.Ardakani@Sun.COM if (canonname != NULL) { 38879422SAfshin.Ardakani@Sun.COM assert(values[3] != NULL); 38889422SAfshin.Ardakani@Sun.COM *canonname = strdup(values[3]); 38899422SAfshin.Ardakani@Sun.COM if (*canonname == NULL) { 38904520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 38914520Snw141292 retcode = IDMAP_ERR_MEMORY; 38924520Snw141292 goto out; 38934520Snw141292 } 38944520Snw141292 } 38954520Snw141292 38969422SAfshin.Ardakani@Sun.COM *sidprefix = strdup(values[0]); 38979422SAfshin.Ardakani@Sun.COM if (*sidprefix == NULL) { 38989422SAfshin.Ardakani@Sun.COM idmapdlog(LOG_ERR, "Out of memory"); 38999422SAfshin.Ardakani@Sun.COM retcode = IDMAP_ERR_MEMORY; 39009422SAfshin.Ardakani@Sun.COM goto out; 39019422SAfshin.Ardakani@Sun.COM } 39029422SAfshin.Ardakani@Sun.COM *rid = strtoul(values[1], &end, 10); 39039422SAfshin.Ardakani@Sun.COM 39049422SAfshin.Ardakani@Sun.COM retcode = IDMAP_SUCCESS; 39059422SAfshin.Ardakani@Sun.COM 39064520Snw141292 out: 39074864Sbaban if (vm != NULL) 39084520Snw141292 (void) sqlite_finalize(vm, NULL); 39099422SAfshin.Ardakani@Sun.COM 39109422SAfshin.Ardakani@Sun.COM if (retcode != IDMAP_SUCCESS) { 39119422SAfshin.Ardakani@Sun.COM free(*sidprefix); 39129422SAfshin.Ardakani@Sun.COM *sidprefix = NULL; 39139422SAfshin.Ardakani@Sun.COM if (canonname != NULL) { 39149422SAfshin.Ardakani@Sun.COM free(*canonname); 39159422SAfshin.Ardakani@Sun.COM *canonname = NULL; 39169422SAfshin.Ardakani@Sun.COM } 39179422SAfshin.Ardakani@Sun.COM } 39184520Snw141292 return (retcode); 39194520Snw141292 } 39204520Snw141292 39215696Snw141292 static 39225696Snw141292 idmap_retcode 39235731Sbaban ad_lookup_by_winname(lookup_state_t *state, 39245731Sbaban const char *name, const char *domain, int eunixtype, 39256386Sjp151216 char **dn, char **attr, char **value, char **canonname, 39266386Sjp151216 char **sidprefix, idmap_rid_t *rid, int *wintype, 39276386Sjp151216 char **unixname) 39285696Snw141292 { 39298361SJulian.Pullen@Sun.COM int retries; 39304520Snw141292 idmap_query_state_t *qs = NULL; 39314520Snw141292 idmap_retcode rc, retcode; 39328361SJulian.Pullen@Sun.COM int i; 39338361SJulian.Pullen@Sun.COM int found_ad = 0; 39348361SJulian.Pullen@Sun.COM 39358040SBaban.Kenkre@Sun.COM RDLOCK_CONFIG(); 393610504SKeyur.Desai@Sun.COM if (_idmapdstate.num_gcs > 0) { 393710504SKeyur.Desai@Sun.COM for (i = 0; i < _idmapdstate.num_gcs && !found_ad; i++) { 39388361SJulian.Pullen@Sun.COM retries = 0; 39398361SJulian.Pullen@Sun.COM retry: 394010504SKeyur.Desai@Sun.COM retcode = idmap_lookup_batch_start( 394110504SKeyur.Desai@Sun.COM _idmapdstate.gcs[i], 394210504SKeyur.Desai@Sun.COM 1, 394310504SKeyur.Desai@Sun.COM _idmapdstate.cfg->pgcfg.directory_based_mapping, 394410504SKeyur.Desai@Sun.COM _idmapdstate.cfg->pgcfg.default_domain, 394510504SKeyur.Desai@Sun.COM &qs); 39468361SJulian.Pullen@Sun.COM if (retcode != IDMAP_SUCCESS) { 39478361SJulian.Pullen@Sun.COM if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && 39488361SJulian.Pullen@Sun.COM retries++ < ADUTILS_DEF_NUM_RETRIES) 39498361SJulian.Pullen@Sun.COM goto retry; 39508361SJulian.Pullen@Sun.COM degrade_svc(1, "failed to create request for " 39518361SJulian.Pullen@Sun.COM "AD lookup by winname"); 39528361SJulian.Pullen@Sun.COM return (retcode); 39538361SJulian.Pullen@Sun.COM } 39548361SJulian.Pullen@Sun.COM 39558361SJulian.Pullen@Sun.COM restore_svc(); 39568361SJulian.Pullen@Sun.COM 39578361SJulian.Pullen@Sun.COM if (state != NULL && i == 0) { 39588361SJulian.Pullen@Sun.COM /* 39598361SJulian.Pullen@Sun.COM * Directory based name mapping is only 39608361SJulian.Pullen@Sun.COM * performed within the joined forest (i == 0). 39618361SJulian.Pullen@Sun.COM * We don't trust other "trusted" forests to 39628361SJulian.Pullen@Sun.COM * provide DS-based name mapping information 39638361SJulian.Pullen@Sun.COM * because AD's definition of "cross-forest 39648361SJulian.Pullen@Sun.COM * trust" does not encompass this sort of 39658361SJulian.Pullen@Sun.COM * behavior. 39668361SJulian.Pullen@Sun.COM */ 39678361SJulian.Pullen@Sun.COM idmap_lookup_batch_set_unixattr(qs, 39688361SJulian.Pullen@Sun.COM state->ad_unixuser_attr, 39698361SJulian.Pullen@Sun.COM state->ad_unixgroup_attr); 39708361SJulian.Pullen@Sun.COM } 39718361SJulian.Pullen@Sun.COM 39728361SJulian.Pullen@Sun.COM retcode = idmap_name2sid_batch_add1(qs, name, domain, 39738361SJulian.Pullen@Sun.COM eunixtype, dn, attr, value, canonname, sidprefix, 397410504SKeyur.Desai@Sun.COM rid, wintype, unixname, NULL, &rc); 39758361SJulian.Pullen@Sun.COM if (retcode == IDMAP_ERR_DOMAIN_NOTFOUND) { 39768361SJulian.Pullen@Sun.COM idmap_lookup_release_batch(&qs); 39778361SJulian.Pullen@Sun.COM continue; 39788361SJulian.Pullen@Sun.COM } 39798361SJulian.Pullen@Sun.COM found_ad = 1; 39808361SJulian.Pullen@Sun.COM if (retcode != IDMAP_SUCCESS) 39818361SJulian.Pullen@Sun.COM idmap_lookup_release_batch(&qs); 39828361SJulian.Pullen@Sun.COM else 39838361SJulian.Pullen@Sun.COM retcode = idmap_lookup_batch_end(&qs); 39848361SJulian.Pullen@Sun.COM 39858361SJulian.Pullen@Sun.COM if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR && 39868361SJulian.Pullen@Sun.COM retries++ < ADUTILS_DEF_NUM_RETRIES) 39878361SJulian.Pullen@Sun.COM goto retry; 39888361SJulian.Pullen@Sun.COM else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR) 39898361SJulian.Pullen@Sun.COM degrade_svc(1, 39908361SJulian.Pullen@Sun.COM "some AD lookups timed out repeatedly"); 39918361SJulian.Pullen@Sun.COM } 39928361SJulian.Pullen@Sun.COM } else { 39938361SJulian.Pullen@Sun.COM /* No AD case */ 39948361SJulian.Pullen@Sun.COM retcode = IDMAP_ERR_NO_ACTIVEDIRECTORY; 39954520Snw141292 } 39968361SJulian.Pullen@Sun.COM UNLOCK_CONFIG(); 39974520Snw141292 39984520Snw141292 if (retcode != IDMAP_SUCCESS) { 39995731Sbaban idmapdlog(LOG_NOTICE, "AD lookup by winname failed"); 40004520Snw141292 return (retcode); 40015731Sbaban } 40025731Sbaban return (rc); 40034520Snw141292 } 40044520Snw141292 40059422SAfshin.Ardakani@Sun.COM /* 40069422SAfshin.Ardakani@Sun.COM * Given: 40079422SAfshin.Ardakani@Sun.COM * cache sqlite handle to cache 40089422SAfshin.Ardakani@Sun.COM * name Windows user name 40099422SAfshin.Ardakani@Sun.COM * domain Windows domain name 40109422SAfshin.Ardakani@Sun.COM * local_only if true, don't try AD lookups 40119422SAfshin.Ardakani@Sun.COM * 40129422SAfshin.Ardakani@Sun.COM * Returns: Error code 40139422SAfshin.Ardakani@Sun.COM * 40149422SAfshin.Ardakani@Sun.COM * *canonname Canonical name (if non-NULL) [1] 40159422SAfshin.Ardakani@Sun.COM * *canondomain Canonical domain (if non-NULL) [1] 40169422SAfshin.Ardakani@Sun.COM * *sidprefix SID prefix [1] 40179422SAfshin.Ardakani@Sun.COM * *rid RID 40189422SAfshin.Ardakani@Sun.COM * *req Request (direction is updated) 40199422SAfshin.Ardakani@Sun.COM * 40209422SAfshin.Ardakani@Sun.COM * [1] malloc'ed, NULL on error 40219422SAfshin.Ardakani@Sun.COM */ 40225696Snw141292 idmap_retcode 40239422SAfshin.Ardakani@Sun.COM lookup_name2sid( 40249422SAfshin.Ardakani@Sun.COM sqlite *cache, 40259422SAfshin.Ardakani@Sun.COM const char *name, 40269422SAfshin.Ardakani@Sun.COM const char *domain, 40279422SAfshin.Ardakani@Sun.COM int *is_wuser, 40289422SAfshin.Ardakani@Sun.COM char **canonname, 40299422SAfshin.Ardakani@Sun.COM char **canondomain, 40309422SAfshin.Ardakani@Sun.COM char **sidprefix, 40319422SAfshin.Ardakani@Sun.COM idmap_rid_t *rid, 40329422SAfshin.Ardakani@Sun.COM idmap_mapping *req, 40339422SAfshin.Ardakani@Sun.COM int local_only) 40345696Snw141292 { 40354520Snw141292 int type; 40364520Snw141292 idmap_retcode retcode; 40374520Snw141292 40385696Snw141292 *sidprefix = NULL; 40395731Sbaban if (canonname != NULL) 40405731Sbaban *canonname = NULL; 40419422SAfshin.Ardakani@Sun.COM if (canondomain != NULL) 40429422SAfshin.Ardakani@Sun.COM *canondomain = NULL; 40435731Sbaban 40445731Sbaban /* Lookup well-known SIDs table */ 40459422SAfshin.Ardakani@Sun.COM retcode = lookup_wksids_name2sid(name, domain, canonname, canondomain, 40469422SAfshin.Ardakani@Sun.COM sidprefix, rid, &type); 40474864Sbaban if (retcode == IDMAP_SUCCESS) { 40485731Sbaban req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE; 40494864Sbaban goto out; 40504864Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 40514864Sbaban return (retcode); 40524864Sbaban } 40534864Sbaban 40545731Sbaban /* Lookup cache */ 40555696Snw141292 retcode = lookup_cache_name2sid(cache, name, domain, canonname, 40565696Snw141292 sidprefix, rid, &type); 40575731Sbaban if (retcode == IDMAP_SUCCESS) { 40585731Sbaban req->direction |= _IDMAP_F_DONT_UPDATE_NAMECACHE; 40595731Sbaban goto out; 40605731Sbaban } else if (retcode != IDMAP_ERR_NOTFOUND) { 40614520Snw141292 return (retcode); 40624520Snw141292 } 40634520Snw141292 40646616Sdm199847 /* 40656616Sdm199847 * The caller may be using this function to determine if this 40666616Sdm199847 * request needs to be marked for AD lookup or not 40676616Sdm199847 * (i.e. _IDMAP_F_LOOKUP_AD) and therefore may not want this 40686616Sdm199847 * function to AD lookup now. 40696616Sdm199847 */ 40706616Sdm199847 if (local_only) 40716616Sdm199847 return (retcode); 40726616Sdm199847 40735731Sbaban /* Lookup AD */ 40745731Sbaban retcode = ad_lookup_by_winname(NULL, name, domain, _IDMAP_T_UNDEF, 40756386Sjp151216 NULL, NULL, NULL, canonname, sidprefix, rid, &type, NULL); 40765731Sbaban if (retcode != IDMAP_SUCCESS) 40775731Sbaban return (retcode); 40785731Sbaban 40794864Sbaban out: 40804520Snw141292 /* 40814520Snw141292 * Entry found (cache or Windows lookup) 40825696Snw141292 * is_wuser is both input as well as output parameter 40834520Snw141292 */ 40845731Sbaban if (*is_wuser == 1 && type != _IDMAP_T_USER) 40855731Sbaban retcode = IDMAP_ERR_NOTUSER; 40865731Sbaban else if (*is_wuser == 0 && type != _IDMAP_T_GROUP) 40875731Sbaban retcode = IDMAP_ERR_NOTGROUP; 40885731Sbaban else if (*is_wuser == -1) { 40894520Snw141292 /* Caller wants to know if its user or group */ 40904520Snw141292 if (type == _IDMAP_T_USER) 40915696Snw141292 *is_wuser = 1; 40924520Snw141292 else if (type == _IDMAP_T_GROUP) 40935696Snw141292 *is_wuser = 0; 40945731Sbaban else 40955731Sbaban retcode = IDMAP_ERR_SID; 40965731Sbaban } 40975731Sbaban 40989422SAfshin.Ardakani@Sun.COM if (retcode == IDMAP_SUCCESS) { 40999422SAfshin.Ardakani@Sun.COM /* 41009422SAfshin.Ardakani@Sun.COM * If we were asked for a canonical domain and none 41019422SAfshin.Ardakani@Sun.COM * of the searches have provided one, assume it's the 41029422SAfshin.Ardakani@Sun.COM * supplied domain. 41039422SAfshin.Ardakani@Sun.COM */ 41049422SAfshin.Ardakani@Sun.COM if (canondomain != NULL && *canondomain == NULL) { 41059422SAfshin.Ardakani@Sun.COM *canondomain = strdup(domain); 41069422SAfshin.Ardakani@Sun.COM if (*canondomain == NULL) 41079422SAfshin.Ardakani@Sun.COM retcode = IDMAP_ERR_MEMORY; 41089422SAfshin.Ardakani@Sun.COM } 41099422SAfshin.Ardakani@Sun.COM } 41105731Sbaban if (retcode != IDMAP_SUCCESS) { 41115731Sbaban free(*sidprefix); 41125731Sbaban *sidprefix = NULL; 41135731Sbaban if (canonname != NULL) { 41145731Sbaban free(*canonname); 41155731Sbaban *canonname = NULL; 41165696Snw141292 } 41179422SAfshin.Ardakani@Sun.COM if (canondomain != NULL) { 41189422SAfshin.Ardakani@Sun.COM free(*canondomain); 41199422SAfshin.Ardakani@Sun.COM *canondomain = NULL; 41209422SAfshin.Ardakani@Sun.COM } 41214520Snw141292 } 41224520Snw141292 return (retcode); 41234520Snw141292 } 41244520Snw141292 41255696Snw141292 static 41265696Snw141292 idmap_retcode 41276616Sdm199847 name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname, 41285696Snw141292 int is_user, idmap_mapping *req, idmap_id_res *res) 41295696Snw141292 { 41304520Snw141292 const char *winname, *windomain; 41315696Snw141292 char *canonname; 41329422SAfshin.Ardakani@Sun.COM char *canondomain; 41334520Snw141292 char *sql = NULL, *errmsg = NULL; 41344520Snw141292 idmap_retcode retcode; 41354520Snw141292 char *end; 41364520Snw141292 const char **values; 41374520Snw141292 sqlite_vm *vm = NULL; 41386386Sjp151216 int ncol, r; 41395731Sbaban int is_wuser; 41404520Snw141292 const char *me = "name_based_mapping_pid2sid"; 41416386Sjp151216 int non_wild_match = FALSE; 41426386Sjp151216 idmap_namerule *rule = &res->info.how.idmap_how_u.rule; 41436386Sjp151216 int direction; 41445731Sbaban 41455731Sbaban assert(unixname != NULL); /* We have unixname */ 41465731Sbaban assert(req->id2name == NULL); /* We don't have winname */ 41475731Sbaban assert(res->id.idmap_id_u.sid.prefix == NULL); /* No SID either */ 41484520Snw141292 41494520Snw141292 sql = sqlite_mprintf( 41506386Sjp151216 "SELECT winname_display, windomain, w2u_order, " 41516386Sjp151216 "is_wuser, unixname, is_nt4 " 41526386Sjp151216 "FROM namerules WHERE " 41535696Snw141292 "u2w_order > 0 AND is_user = %d AND " 41545696Snw141292 "(unixname = %Q OR unixname = '*') " 41555696Snw141292 "ORDER BY u2w_order ASC;", is_user, unixname); 41564520Snw141292 if (sql == NULL) { 41574520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 41584520Snw141292 retcode = IDMAP_ERR_MEMORY; 41594520Snw141292 goto out; 41604520Snw141292 } 41614520Snw141292 41626616Sdm199847 if (sqlite_compile(state->db, sql, NULL, &vm, &errmsg) != SQLITE_OK) { 41634520Snw141292 retcode = IDMAP_ERR_INTERNAL; 41645696Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 41655696Snw141292 CHECK_NULL(errmsg)); 41664520Snw141292 sqlite_freemem(errmsg); 41674520Snw141292 goto out; 41684520Snw141292 } 41694520Snw141292 41706386Sjp151216 for (;;) { 41714520Snw141292 r = sqlite_step(vm, &ncol, &values, NULL); 41724884Sjp151216 assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); 41734884Sjp151216 if (r == SQLITE_ROW) { 41746386Sjp151216 if (ncol < 6) { 41754520Snw141292 retcode = IDMAP_ERR_INTERNAL; 41764520Snw141292 goto out; 41774520Snw141292 } 41784520Snw141292 if (values[0] == NULL) { 41794520Snw141292 /* values [1] and [2] can be null */ 41804520Snw141292 retcode = IDMAP_ERR_INTERNAL; 41814520Snw141292 goto out; 41824520Snw141292 } 41836386Sjp151216 41846386Sjp151216 if (values[2] != NULL) 41856386Sjp151216 direction = 41866386Sjp151216 (strtol(values[2], &end, 10) == 0)? 41876386Sjp151216 IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 41886386Sjp151216 else 41896386Sjp151216 direction = IDMAP_DIRECTION_U2W; 41906386Sjp151216 41914520Snw141292 if (EMPTY_NAME(values[0])) { 41926386Sjp151216 idmap_namerule_set(rule, values[1], values[0], 41936386Sjp151216 values[4], is_user, 41946386Sjp151216 strtol(values[3], &end, 10), 41956386Sjp151216 strtol(values[5], &end, 10), 41966386Sjp151216 direction); 41974520Snw141292 retcode = IDMAP_ERR_NOMAPPING; 41984520Snw141292 goto out; 41994520Snw141292 } 42005696Snw141292 42015696Snw141292 if (values[0][0] == '*') { 42026386Sjp151216 winname = unixname; 42036386Sjp151216 if (non_wild_match) { 42045696Snw141292 /* 42056386Sjp151216 * There were non-wildcard rules 42066386Sjp151216 * where the Windows identity doesn't 42076386Sjp151216 * exist. Return no mapping. 42085696Snw141292 */ 42095696Snw141292 retcode = IDMAP_ERR_NOMAPPING; 42105696Snw141292 goto out; 42115696Snw141292 } 42125696Snw141292 } else { 42136386Sjp151216 /* Save first non-wild match rule */ 42146386Sjp151216 if (!non_wild_match) { 42156386Sjp151216 idmap_namerule_set(rule, values[1], 42166386Sjp151216 values[0], values[4], 42176386Sjp151216 is_user, 42186386Sjp151216 strtol(values[3], &end, 10), 42196386Sjp151216 strtol(values[5], &end, 10), 42206386Sjp151216 direction); 42216386Sjp151216 non_wild_match = TRUE; 42226386Sjp151216 } 42235696Snw141292 winname = values[0]; 42245696Snw141292 } 42256386Sjp151216 is_wuser = res->id.idtype == IDMAP_USID ? 1 42266386Sjp151216 : res->id.idtype == IDMAP_GSID ? 0 42276386Sjp151216 : -1; 42284864Sbaban if (values[1] != NULL) 42294520Snw141292 windomain = values[1]; 42306616Sdm199847 else if (state->defdom != NULL) 42316616Sdm199847 windomain = state->defdom; 42324520Snw141292 else { 42335696Snw141292 idmapdlog(LOG_ERR, "%s: no domain", me); 42344520Snw141292 retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 42354520Snw141292 goto out; 42364520Snw141292 } 42375696Snw141292 42386616Sdm199847 retcode = lookup_name2sid(state->cache, 42396616Sdm199847 winname, windomain, 42409422SAfshin.Ardakani@Sun.COM &is_wuser, &canonname, &canondomain, 42415696Snw141292 &res->id.idmap_id_u.sid.prefix, 42426616Sdm199847 &res->id.idmap_id_u.sid.rid, req, 0); 42435731Sbaban 42444520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 42455696Snw141292 continue; 42464520Snw141292 } 42474520Snw141292 goto out; 42486386Sjp151216 42494520Snw141292 } else if (r == SQLITE_DONE) { 42506386Sjp151216 /* 42516386Sjp151216 * If there were non-wildcard rules where 42526386Sjp151216 * Windows identity doesn't exist 42536386Sjp151216 * return no mapping. 42546386Sjp151216 */ 42556386Sjp151216 if (non_wild_match) 42566386Sjp151216 retcode = IDMAP_ERR_NOMAPPING; 42576386Sjp151216 else 42586386Sjp151216 retcode = IDMAP_ERR_NOTFOUND; 42594520Snw141292 goto out; 42604520Snw141292 } else { 42614520Snw141292 (void) sqlite_finalize(vm, &errmsg); 42624520Snw141292 vm = NULL; 42635696Snw141292 idmapdlog(LOG_ERR, "%s: database error (%s)", me, 42645696Snw141292 CHECK_NULL(errmsg)); 42654520Snw141292 sqlite_freemem(errmsg); 42664520Snw141292 retcode = IDMAP_ERR_INTERNAL; 42674520Snw141292 goto out; 42684520Snw141292 } 42694520Snw141292 } 42704520Snw141292 42714520Snw141292 out: 42724864Sbaban if (sql != NULL) 42734520Snw141292 sqlite_freemem(sql); 42744520Snw141292 if (retcode == IDMAP_SUCCESS) { 42755696Snw141292 res->id.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID; 42765696Snw141292 42774864Sbaban if (values[2] != NULL) 42784520Snw141292 res->direction = 42794644Sbaban (strtol(values[2], &end, 10) == 0)? 42804644Sbaban IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; 42814520Snw141292 else 42824644Sbaban res->direction = IDMAP_DIRECTION_U2W; 42835064Sdm199847 42845696Snw141292 req->id2name = canonname; 42859422SAfshin.Ardakani@Sun.COM req->id2domain = canondomain; 42866616Sdm199847 } 42876616Sdm199847 42886616Sdm199847 if (retcode == IDMAP_SUCCESS) { 42896386Sjp151216 idmap_namerule_set(rule, values[1], values[0], values[4], 42906386Sjp151216 is_user, strtol(values[3], &end, 10), 42916386Sjp151216 strtol(values[5], &end, 10), 42926386Sjp151216 rule->direction); 42939021Samw@Sun.COM } 42949021Samw@Sun.COM 42959021Samw@Sun.COM if (retcode != IDMAP_ERR_NOTFOUND) { 42969021Samw@Sun.COM res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED; 42976386Sjp151216 res->info.src = IDMAP_MAP_SRC_NEW; 42984520Snw141292 } 42999021Samw@Sun.COM 43004864Sbaban if (vm != NULL) 43014520Snw141292 (void) sqlite_finalize(vm, NULL); 43024520Snw141292 return (retcode); 43034520Snw141292 } 43044520Snw141292 43055696Snw141292 /* 43065696Snw141292 * Convention when processing unix2win requests: 43075696Snw141292 * 43085696Snw141292 * Unix identity: 43095696Snw141292 * req->id1name = 43105696Snw141292 * unixname if given otherwise unixname found will be placed 43115696Snw141292 * here. 43125696Snw141292 * req->id1domain = 43135696Snw141292 * NOT USED 43145696Snw141292 * req->id1.idtype = 43155696Snw141292 * Given type (IDMAP_UID or IDMAP_GID) 43165696Snw141292 * req->id1..[uid or gid] = 43175696Snw141292 * UID/GID if given otherwise UID/GID found will be placed here. 43185696Snw141292 * 43195696Snw141292 * Windows identity: 43205696Snw141292 * req->id2name = 43215696Snw141292 * winname found will be placed here. 43225696Snw141292 * req->id2domain = 43235696Snw141292 * windomain found will be placed here. 43245696Snw141292 * res->id.idtype = 43255696Snw141292 * Target type initialized from req->id2.idtype. If 43265696Snw141292 * it is IDMAP_SID then actual type (IDMAP_USID/GSID) found 43275696Snw141292 * will be placed here. 43285696Snw141292 * req->id..sid.[prefix, rid] = 43295696Snw141292 * SID found will be placed here. 43305696Snw141292 * 43315696Snw141292 * Others: 43325696Snw141292 * res->retcode = 43335696Snw141292 * Return status for this request will be placed here. 43345696Snw141292 * res->direction = 43355696Snw141292 * Direction found will be placed here. Direction 43365696Snw141292 * meaning whether the resultant mapping is valid 43375696Snw141292 * only from unix2win or bi-directional. 43385696Snw141292 * req->direction = 43395696Snw141292 * INTERNAL USE. Used by idmapd to set various 43405696Snw141292 * flags (_IDMAP_F_xxxx) to aid in processing 43415696Snw141292 * of the request. 43425696Snw141292 * req->id2.idtype = 43435696Snw141292 * INTERNAL USE. Initially this is the requested target 43445696Snw141292 * type and is used to initialize res->id.idtype. 43455696Snw141292 * ad_lookup_batch() uses this field temporarily to store 43465696Snw141292 * sid_type obtained by the batched AD lookups and after 43475696Snw141292 * use resets it to IDMAP_NONE to prevent xdr from 43485696Snw141292 * mis-interpreting the contents of req->id2. 43495696Snw141292 * req->id2..[uid or gid or sid] = 43505696Snw141292 * NOT USED 43515696Snw141292 */ 43525696Snw141292 43535696Snw141292 /* 43545696Snw141292 * This function does the following: 43555696Snw141292 * 1. Lookup well-known SIDs table. 43565696Snw141292 * 2. Lookup cache. 43575696Snw141292 * 3. Check if the client does not want new mapping to be allocated 43585696Snw141292 * in which case this pass is the final pass. 43595731Sbaban * 4. Set AD/NLDAP lookup flags if it determines that the next stage needs 43605731Sbaban * to do AD/NLDAP lookup. 43615696Snw141292 */ 43624520Snw141292 idmap_retcode 43636616Sdm199847 pid2sid_first_pass(lookup_state_t *state, idmap_mapping *req, 43646616Sdm199847 idmap_id_res *res, int is_user, int getname) 43655696Snw141292 { 43665731Sbaban idmap_retcode retcode; 43675731Sbaban bool_t gen_localsid_on_err = FALSE; 43685731Sbaban 43695731Sbaban /* Initialize result */ 43704520Snw141292 res->id.idtype = req->id2.idtype; 43715731Sbaban res->direction = IDMAP_DIRECTION_UNDEF; 43725731Sbaban 43735731Sbaban if (req->id2.idmap_id_u.sid.prefix != NULL) { 43745731Sbaban /* sanitize sidprefix */ 43755731Sbaban free(req->id2.idmap_id_u.sid.prefix); 43765731Sbaban req->id2.idmap_id_u.sid.prefix = NULL; 43775731Sbaban } 43785731Sbaban 43796386Sjp151216 /* Find pid */ 43806386Sjp151216 if (req->id1.idmap_id_u.uid == SENTINEL_PID) { 43816386Sjp151216 if (ns_lookup_byname(req->id1name, NULL, &req->id1) 43826386Sjp151216 != IDMAP_SUCCESS) { 43836386Sjp151216 retcode = IDMAP_ERR_NOMAPPING; 43846386Sjp151216 goto out; 43856386Sjp151216 } 43866386Sjp151216 } 43876386Sjp151216 43889422SAfshin.Ardakani@Sun.COM /* Lookup in well-known SIDs table */ 43894520Snw141292 retcode = lookup_wksids_pid2sid(req, res, is_user); 43904520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 43914520Snw141292 goto out; 43924520Snw141292 43939422SAfshin.Ardakani@Sun.COM /* Lookup in cache */ 43946616Sdm199847 retcode = lookup_cache_pid2sid(state->cache, req, res, is_user, 43956616Sdm199847 getname); 43964520Snw141292 if (retcode != IDMAP_ERR_NOTFOUND) 43974520Snw141292 goto out; 43984520Snw141292 43994520Snw141292 /* Ephemeral ids cannot be allocated during pid2sid */ 44004520Snw141292 if (IS_EPHEMERAL(req->id1.idmap_id_u.uid)) { 44014864Sbaban retcode = IDMAP_ERR_NOMAPPING; 44024520Snw141292 goto out; 44034520Snw141292 } 44044520Snw141292 44056386Sjp151216 if (DO_NOT_ALLOC_NEW_ID_MAPPING(req)) { 44068361SJulian.Pullen@Sun.COM retcode = IDMAP_ERR_NONE_GENERATED; 44076386Sjp151216 goto out; 44086386Sjp151216 } 44096386Sjp151216 44106386Sjp151216 if (AVOID_NAMESERVICE(req)) { 44115731Sbaban gen_localsid_on_err = TRUE; 44124864Sbaban retcode = IDMAP_ERR_NOMAPPING; 44134520Snw141292 goto out; 44144520Snw141292 } 44154520Snw141292 44165731Sbaban /* Set flags for the next stage */ 441710504SKeyur.Desai@Sun.COM if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU) { 441810504SKeyur.Desai@Sun.COM req->direction |= _IDMAP_F_LOOKUP_AD; 441910504SKeyur.Desai@Sun.COM state->ad_nqueries++; 442010504SKeyur.Desai@Sun.COM } else if (AD_MODE(req->id1.idtype, state)) { 44215731Sbaban /* 44225731Sbaban * If AD-based name mapping is enabled then the next stage 44235731Sbaban * will need to lookup AD using unixname to get the 44245731Sbaban * corresponding winname. 44255731Sbaban */ 44265731Sbaban if (req->id1name == NULL) { 44275731Sbaban /* Get unixname if only pid is given. */ 44285731Sbaban retcode = ns_lookup_bypid(req->id1.idmap_id_u.uid, 44295731Sbaban is_user, &req->id1name); 44306616Sdm199847 if (retcode != IDMAP_SUCCESS) { 44316616Sdm199847 gen_localsid_on_err = TRUE; 44325731Sbaban goto out; 44336616Sdm199847 } 44344520Snw141292 } 44355731Sbaban req->direction |= _IDMAP_F_LOOKUP_AD; 44365731Sbaban state->ad_nqueries++; 44375731Sbaban } else if (NLDAP_OR_MIXED_MODE(req->id1.idtype, state)) { 44385731Sbaban /* 44395731Sbaban * If native LDAP or mixed mode is enabled for name mapping 44405731Sbaban * then the next stage will need to lookup native LDAP using 44415731Sbaban * unixname/pid to get the corresponding winname. 44425731Sbaban */ 44435731Sbaban req->direction |= _IDMAP_F_LOOKUP_NLDAP; 44445731Sbaban state->nldap_nqueries++; 44455731Sbaban } 44465731Sbaban 44475731Sbaban /* 44485731Sbaban * Failed to find non-expired entry in cache. Set the flag to 44495731Sbaban * indicate that we are not done yet. 44505731Sbaban */ 44515731Sbaban state->pid2sid_done = FALSE; 44525731Sbaban req->direction |= _IDMAP_F_NOTDONE; 44535731Sbaban retcode = IDMAP_SUCCESS; 44545731Sbaban 44555731Sbaban out: 44565731Sbaban res->retcode = idmap_stat4prot(retcode); 44575731Sbaban if (ARE_WE_DONE(req->direction) && res->retcode != IDMAP_SUCCESS) 44585731Sbaban if (gen_localsid_on_err == TRUE) 44596386Sjp151216 (void) generate_localsid(req, res, is_user, TRUE); 44605731Sbaban return (retcode); 44615731Sbaban } 44625731Sbaban 44635731Sbaban idmap_retcode 44646616Sdm199847 pid2sid_second_pass(lookup_state_t *state, idmap_mapping *req, 44656616Sdm199847 idmap_id_res *res, int is_user) 44665731Sbaban { 44675731Sbaban bool_t gen_localsid_on_err = TRUE; 44685731Sbaban idmap_retcode retcode = IDMAP_SUCCESS; 44695731Sbaban 44705731Sbaban /* Check if second pass is needed */ 44715731Sbaban if (ARE_WE_DONE(req->direction)) 44725731Sbaban return (res->retcode); 44735731Sbaban 44745731Sbaban /* Get status from previous pass */ 44755731Sbaban retcode = res->retcode; 44765731Sbaban if (retcode != IDMAP_SUCCESS) 44775731Sbaban goto out; 44785731Sbaban 44795731Sbaban /* 44805731Sbaban * If directory-based name mapping is enabled then the winname 44815731Sbaban * may already have been retrieved from the AD object (AD-mode) 44826616Sdm199847 * or from native LDAP object (nldap-mode or mixed-mode). 44836616Sdm199847 * Note that if we have winname but no SID then it's an error 44846616Sdm199847 * because this implies that the Native LDAP entry contains 44856616Sdm199847 * winname which does not exist and it's better that we return 44866616Sdm199847 * an error instead of doing rule-based mapping so that the user 44876616Sdm199847 * can detect the issue and take appropriate action. 44885731Sbaban */ 44896616Sdm199847 if (req->id2name != NULL) { 44906616Sdm199847 /* Return notfound if we've winname but no SID. */ 44916616Sdm199847 if (res->id.idmap_id_u.sid.prefix == NULL) { 44926616Sdm199847 retcode = IDMAP_ERR_NOTFOUND; 44936616Sdm199847 goto out; 44946616Sdm199847 } 449510504SKeyur.Desai@Sun.COM if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU) 449610504SKeyur.Desai@Sun.COM res->direction = IDMAP_DIRECTION_BI; 449710504SKeyur.Desai@Sun.COM else if (AD_MODE(req->id1.idtype, state)) 44985731Sbaban res->direction = IDMAP_DIRECTION_BI; 44995731Sbaban else if (NLDAP_MODE(req->id1.idtype, state)) 45005731Sbaban res->direction = IDMAP_DIRECTION_BI; 45015731Sbaban else if (MIXED_MODE(req->id1.idtype, state)) 45025731Sbaban res->direction = IDMAP_DIRECTION_W2U; 45035731Sbaban goto out; 45046616Sdm199847 } else if (res->id.idmap_id_u.sid.prefix != NULL) { 45056616Sdm199847 /* 45066616Sdm199847 * We've SID but no winname. This is fine because 45076616Sdm199847 * the caller may have only requested SID. 45086616Sdm199847 */ 45096616Sdm199847 goto out; 45105731Sbaban } 45115731Sbaban 45126616Sdm199847 /* Free any mapping info from Directory based mapping */ 45136616Sdm199847 if (res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN) 45146616Sdm199847 idmap_info_free(&res->info); 45156616Sdm199847 45165731Sbaban if (req->id1name == NULL) { 45175731Sbaban /* Get unixname from name service */ 45185731Sbaban retcode = ns_lookup_bypid(req->id1.idmap_id_u.uid, is_user, 45195731Sbaban &req->id1name); 45205731Sbaban if (retcode != IDMAP_SUCCESS) 45215731Sbaban goto out; 45225731Sbaban } else if (req->id1.idmap_id_u.uid == SENTINEL_PID) { 45235731Sbaban /* Get pid from name service */ 45245731Sbaban retcode = ns_lookup_byname(req->id1name, NULL, &req->id1); 45255731Sbaban if (retcode != IDMAP_SUCCESS) { 45265731Sbaban gen_localsid_on_err = FALSE; 45275731Sbaban goto out; 45284520Snw141292 } 45294520Snw141292 } 45304520Snw141292 45315731Sbaban /* Use unixname to evaluate local name-based mapping rules */ 45326616Sdm199847 retcode = name_based_mapping_pid2sid(state, req->id1name, is_user, 45335696Snw141292 req, res); 45344520Snw141292 if (retcode == IDMAP_ERR_NOTFOUND) { 45356386Sjp151216 retcode = generate_localsid(req, res, is_user, FALSE); 45365731Sbaban gen_localsid_on_err = FALSE; 45375731Sbaban } 45384520Snw141292 45394520Snw141292 out: 45405731Sbaban res->retcode = idmap_stat4prot(retcode); 45415731Sbaban if (res->retcode != IDMAP_SUCCESS) { 45425731Sbaban req->direction = _IDMAP_F_DONE; 45436616Sdm199847 free(req->id2name); 45446616Sdm199847 req->id2name = NULL; 45456616Sdm199847 free(req->id2domain); 45466616Sdm199847 req->id2domain = NULL; 45475731Sbaban if (gen_localsid_on_err == TRUE) 45486386Sjp151216 (void) generate_localsid(req, res, is_user, TRUE); 45496616Sdm199847 else 45506616Sdm199847 res->id.idtype = is_user ? IDMAP_USID : IDMAP_GSID; 45514520Snw141292 } 45525731Sbaban if (!ARE_WE_DONE(req->direction)) 45534520Snw141292 state->pid2sid_done = FALSE; 45544520Snw141292 return (retcode); 45554520Snw141292 } 45564520Snw141292 45575696Snw141292 static 45585696Snw141292 int 45594644Sbaban copy_mapping_request(idmap_mapping *mapping, idmap_mapping *request) 45604520Snw141292 { 45614644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 45624644Sbaban 45634520Snw141292 mapping->flag = request->flag; 45645731Sbaban mapping->direction = _IDMAP_F_DONE; 45654644Sbaban mapping->id2.idtype = request->id2.idtype; 45664520Snw141292 45674520Snw141292 mapping->id1.idtype = request->id1.idtype; 45685696Snw141292 if (IS_REQUEST_SID(*request, 1)) { 45694520Snw141292 mapping->id1.idmap_id_u.sid.rid = 45704520Snw141292 request->id1.idmap_id_u.sid.rid; 45714644Sbaban if (!EMPTY_STRING(request->id1.idmap_id_u.sid.prefix)) { 45724520Snw141292 mapping->id1.idmap_id_u.sid.prefix = 45734520Snw141292 strdup(request->id1.idmap_id_u.sid.prefix); 45744644Sbaban if (mapping->id1.idmap_id_u.sid.prefix == NULL) 45755064Sdm199847 goto errout; 45764644Sbaban } 45774520Snw141292 } else { 45784520Snw141292 mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; 45794520Snw141292 } 45804520Snw141292 45815731Sbaban if (!EMPTY_STRING(request->id1domain)) { 45825731Sbaban mapping->id1domain = strdup(request->id1domain); 45835731Sbaban if (mapping->id1domain == NULL) 45845731Sbaban goto errout; 45855731Sbaban } 45865731Sbaban 45875731Sbaban if (!EMPTY_STRING(request->id1name)) { 45885731Sbaban mapping->id1name = strdup(request->id1name); 45895731Sbaban if (mapping->id1name == NULL) 45905731Sbaban goto errout; 45915731Sbaban } 45924520Snw141292 45934644Sbaban /* We don't need the rest of the request i.e request->id2 */ 45944644Sbaban return (0); 45954644Sbaban 45964644Sbaban errout: 45975064Sdm199847 if (mapping->id1.idmap_id_u.sid.prefix != NULL) 45984644Sbaban free(mapping->id1.idmap_id_u.sid.prefix); 45995064Sdm199847 if (mapping->id1domain != NULL) 46005064Sdm199847 free(mapping->id1domain); 46015064Sdm199847 if (mapping->id1name != NULL) 46025064Sdm199847 free(mapping->id1name); 46034644Sbaban 46044644Sbaban (void) memset(mapping, 0, sizeof (*mapping)); 46054644Sbaban return (-1); 46064520Snw141292 } 46074520Snw141292 46084520Snw141292 46094520Snw141292 idmap_retcode 46104520Snw141292 get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 46115696Snw141292 idmap_mapping *mapping) 46125696Snw141292 { 46134520Snw141292 idmap_id_res idres; 46144520Snw141292 lookup_state_t state; 46155043Sbaban char *cp; 46164520Snw141292 idmap_retcode retcode; 46174520Snw141292 const char *winname, *windomain; 46184520Snw141292 46194520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 46204520Snw141292 (void) memset(&state, 0, sizeof (state)); 46216616Sdm199847 state.cache = cache; 46226616Sdm199847 state.db = db; 46234520Snw141292 46245731Sbaban /* Get directory-based name mapping info */ 46256616Sdm199847 retcode = load_cfg_in_state(&state); 46265731Sbaban if (retcode != IDMAP_SUCCESS) 46274520Snw141292 goto out; 46285731Sbaban 46295731Sbaban /* 46305731Sbaban * Copy data from "request" to "mapping". Note that 46315731Sbaban * empty strings are not copied from "request" to 46325731Sbaban * "mapping" and therefore the coresponding strings in 46335731Sbaban * "mapping" will be NULL. This eliminates having to 46345731Sbaban * check for empty strings henceforth. 46355731Sbaban */ 46364644Sbaban if (copy_mapping_request(mapping, request) < 0) { 46374644Sbaban retcode = IDMAP_ERR_MEMORY; 46384644Sbaban goto out; 46394644Sbaban } 46404520Snw141292 46415064Sdm199847 winname = mapping->id1name; 46425064Sdm199847 windomain = mapping->id1domain; 46434520Snw141292 46445731Sbaban if (winname == NULL && windomain != NULL) { 46455731Sbaban retcode = IDMAP_ERR_ARG; 46465731Sbaban goto out; 46475731Sbaban } 46485731Sbaban 46495731Sbaban /* Need atleast winname or sid to proceed */ 46505731Sbaban if (winname == NULL && mapping->id1.idmap_id_u.sid.prefix == NULL) { 46514520Snw141292 retcode = IDMAP_ERR_ARG; 46524520Snw141292 goto out; 46534520Snw141292 } 46544520Snw141292 46555731Sbaban /* 46565731Sbaban * If domainname is not given but we have a fully qualified 46575731Sbaban * winname then extract the domainname from the winname, 46585731Sbaban * otherwise use the default_domain from the config 46595731Sbaban */ 46605731Sbaban if (winname != NULL && windomain == NULL) { 46615064Sdm199847 retcode = IDMAP_SUCCESS; 46625043Sbaban if ((cp = strchr(winname, '@')) != NULL) { 46635043Sbaban *cp = '\0'; 46645064Sdm199847 mapping->id1domain = strdup(cp + 1); 46655064Sdm199847 if (mapping->id1domain == NULL) 46665064Sdm199847 retcode = IDMAP_ERR_MEMORY; 46675731Sbaban } else if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, 46689422SAfshin.Ardakani@Sun.COM NULL, NULL, NULL) != IDMAP_SUCCESS) { 46696950Sbaban if (state.defdom == NULL) { 46706950Sbaban /* 46716950Sbaban * We have a non-qualified winname which is 46726950Sbaban * neither the name of a well-known SID nor 46736950Sbaban * there is a default domain with which we can 46746950Sbaban * qualify it. 46756950Sbaban */ 46766950Sbaban retcode = IDMAP_ERR_DOMAIN_NOTFOUND; 46776950Sbaban } else { 46786950Sbaban mapping->id1domain = strdup(state.defdom); 46796950Sbaban if (mapping->id1domain == NULL) 46806950Sbaban retcode = IDMAP_ERR_MEMORY; 46816950Sbaban } 46825064Sdm199847 } 46834520Snw141292 if (retcode != IDMAP_SUCCESS) 46844520Snw141292 goto out; 46854520Snw141292 } 46864520Snw141292 46875731Sbaban /* 46885731Sbaban * First pass looks up the well-known SIDs table and cache 46895731Sbaban * and handles localSIDs 46905731Sbaban */ 46914520Snw141292 state.sid2pid_done = TRUE; 46926616Sdm199847 retcode = sid2pid_first_pass(&state, mapping, &idres); 46934520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 46944520Snw141292 goto out; 46954520Snw141292 46966616Sdm199847 /* AD lookup */ 46975731Sbaban if (state.ad_nqueries > 0) { 46986616Sdm199847 retcode = ad_lookup_one(&state, mapping, &idres); 46995731Sbaban if (IDMAP_ERROR(retcode)) 47005731Sbaban goto out; 47014520Snw141292 } 47024520Snw141292 47036616Sdm199847 /* nldap lookup */ 47046616Sdm199847 if (state.nldap_nqueries > 0) { 47056616Sdm199847 retcode = nldap_lookup_one(&state, mapping, &idres); 47066616Sdm199847 if (IDMAP_FATAL_ERROR(retcode)) 47075731Sbaban goto out; 47085731Sbaban } 47095731Sbaban 47105731Sbaban /* Next pass performs name-based mapping and ephemeral mapping. */ 47114520Snw141292 state.sid2pid_done = TRUE; 47126616Sdm199847 retcode = sid2pid_second_pass(&state, mapping, &idres); 47134520Snw141292 if (IDMAP_ERROR(retcode) || state.sid2pid_done == TRUE) 47144520Snw141292 goto out; 47154520Snw141292 47164520Snw141292 /* Update cache */ 47176616Sdm199847 (void) update_cache_sid2pid(&state, mapping, &idres); 47184520Snw141292 47194520Snw141292 out: 47205731Sbaban /* 47215731Sbaban * Note that "mapping" is returned to the client. Therefore 47225731Sbaban * copy whatever we have in "idres" to mapping->id2 and 47235731Sbaban * free idres. 47245731Sbaban */ 47255731Sbaban mapping->direction = idres.direction; 47265731Sbaban mapping->id2 = idres.id; 47276386Sjp151216 if (mapping->flag & IDMAP_REQ_FLG_MAPPING_INFO || 47286386Sjp151216 retcode != IDMAP_SUCCESS) 47296386Sjp151216 (void) idmap_info_mov(&mapping->info, &idres.info); 47306386Sjp151216 else 47316386Sjp151216 idmap_info_free(&idres.info); 47325731Sbaban (void) memset(&idres, 0, sizeof (idres)); 47335731Sbaban if (retcode != IDMAP_SUCCESS) 47344864Sbaban mapping->id2.idmap_id_u.uid = UID_NOBODY; 47354520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 47365731Sbaban cleanup_lookup_state(&state); 47374520Snw141292 return (retcode); 47384520Snw141292 } 47394520Snw141292 47404520Snw141292 idmap_retcode 47414520Snw141292 get_u2w_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, 47425696Snw141292 idmap_mapping *mapping, int is_user) 47435696Snw141292 { 47444520Snw141292 idmap_id_res idres; 47454520Snw141292 lookup_state_t state; 47464520Snw141292 idmap_retcode retcode; 47474520Snw141292 47484520Snw141292 /* 47494520Snw141292 * In order to re-use the pid2sid code, we convert 47504520Snw141292 * our input data into structs that are expected by 47514520Snw141292 * pid2sid_first_pass. 47524520Snw141292 */ 47534520Snw141292 47544520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 47554520Snw141292 (void) memset(&state, 0, sizeof (state)); 47566616Sdm199847 state.cache = cache; 47576616Sdm199847 state.db = db; 47584520Snw141292 47595731Sbaban /* Get directory-based name mapping info */ 47606616Sdm199847 retcode = load_cfg_in_state(&state); 47615731Sbaban if (retcode != IDMAP_SUCCESS) 47625731Sbaban goto out; 47635731Sbaban 47645731Sbaban /* 47655731Sbaban * Copy data from "request" to "mapping". Note that 47665731Sbaban * empty strings are not copied from "request" to 47675731Sbaban * "mapping" and therefore the coresponding strings in 47685731Sbaban * "mapping" will be NULL. This eliminates having to 47695731Sbaban * check for empty strings henceforth. 47705731Sbaban */ 47714644Sbaban if (copy_mapping_request(mapping, request) < 0) { 47724644Sbaban retcode = IDMAP_ERR_MEMORY; 47734644Sbaban goto out; 47744644Sbaban } 47754520Snw141292 47765731Sbaban /* 47775731Sbaban * For unix to windows mapping request, we need atleast a 47785731Sbaban * unixname or uid/gid to proceed 47795731Sbaban */ 47805731Sbaban if (mapping->id1name == NULL && 47815127Sdm199847 mapping->id1.idmap_id_u.uid == SENTINEL_PID) { 47824520Snw141292 retcode = IDMAP_ERR_ARG; 47834520Snw141292 goto out; 47844520Snw141292 } 47854520Snw141292 47865731Sbaban /* First pass looks up cache and well-known SIDs */ 47875731Sbaban state.pid2sid_done = TRUE; 47886616Sdm199847 retcode = pid2sid_first_pass(&state, mapping, &idres, is_user, 1); 47895731Sbaban if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 47905731Sbaban goto out; 47915731Sbaban 47926616Sdm199847 /* nldap lookup */ 47935731Sbaban if (state.nldap_nqueries > 0) { 47946616Sdm199847 retcode = nldap_lookup_one(&state, mapping, &idres); 47955731Sbaban if (IDMAP_FATAL_ERROR(retcode)) 47965731Sbaban goto out; 47976616Sdm199847 } 47986616Sdm199847 47996616Sdm199847 /* AD lookup */ 48006616Sdm199847 if (state.ad_nqueries > 0) { 48016616Sdm199847 retcode = ad_lookup_one(&state, mapping, &idres); 48025731Sbaban if (IDMAP_FATAL_ERROR(retcode)) 48035731Sbaban goto out; 48044520Snw141292 } 48054520Snw141292 48065731Sbaban /* 48075731Sbaban * Next pass processes the result of the preceding passes/lookups. 48085731Sbaban * It returns if there's nothing more to be done otherwise it 48095731Sbaban * evaluates local name-based mapping rules 48105731Sbaban */ 48114520Snw141292 state.pid2sid_done = TRUE; 48126616Sdm199847 retcode = pid2sid_second_pass(&state, mapping, &idres, is_user); 48134520Snw141292 if (IDMAP_ERROR(retcode) || state.pid2sid_done == TRUE) 48144520Snw141292 goto out; 48154520Snw141292 48164520Snw141292 /* Update cache */ 48176616Sdm199847 (void) update_cache_pid2sid(&state, mapping, &idres); 48184520Snw141292 48194520Snw141292 out: 48205731Sbaban /* 48215731Sbaban * Note that "mapping" is returned to the client. Therefore 48225731Sbaban * copy whatever we have in "idres" to mapping->id2 and 48235731Sbaban * free idres. 48245731Sbaban */ 48254520Snw141292 mapping->direction = idres.direction; 48264520Snw141292 mapping->id2 = idres.id; 48276386Sjp151216 if (mapping->flag & IDMAP_REQ_FLG_MAPPING_INFO || 48286386Sjp151216 retcode != IDMAP_SUCCESS) 48296386Sjp151216 (void) idmap_info_mov(&mapping->info, &idres.info); 48306386Sjp151216 else 48316386Sjp151216 idmap_info_free(&idres.info); 48324520Snw141292 (void) memset(&idres, 0, sizeof (idres)); 48334520Snw141292 xdr_free(xdr_idmap_id_res, (caddr_t)&idres); 48345731Sbaban cleanup_lookup_state(&state); 48354520Snw141292 return (retcode); 48364520Snw141292 } 48375731Sbaban 48386616Sdm199847 /*ARGSUSED*/ 48395731Sbaban static 48405731Sbaban idmap_retcode 48416616Sdm199847 ad_lookup_one(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res) 48425731Sbaban { 48436616Sdm199847 idmap_mapping_batch batch; 48446616Sdm199847 idmap_ids_res result; 48456616Sdm199847 48466616Sdm199847 batch.idmap_mapping_batch_len = 1; 48476616Sdm199847 batch.idmap_mapping_batch_val = req; 48486616Sdm199847 result.ids.ids_len = 1; 48496616Sdm199847 result.ids.ids_val = res; 48506616Sdm199847 return (ad_lookup_batch(state, &batch, &result)); 48515731Sbaban } 4852