14520Snw141292 /* 24520Snw141292 * CDDL HEADER START 34520Snw141292 * 44520Snw141292 * The contents of this file are subject to the terms of the 54520Snw141292 * Common Development and Distribution License (the "License"). 64520Snw141292 * You may not use this file except in compliance with the License. 74520Snw141292 * 84520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94520Snw141292 * or http://www.opensolaris.org/os/licensing. 104520Snw141292 * See the License for the specific language governing permissions 114520Snw141292 * and limitations under the License. 124520Snw141292 * 134520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 144520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 164520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 174520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 184520Snw141292 * 194520Snw141292 * CDDL HEADER END 204520Snw141292 */ 214520Snw141292 /* 224520Snw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 234520Snw141292 * Use is subject to license terms. 244520Snw141292 */ 254520Snw141292 264520Snw141292 #pragma ident "%Z%%M% %I% %E% SMI" 274520Snw141292 284520Snw141292 /* 294520Snw141292 * Service routines 304520Snw141292 */ 314520Snw141292 324520Snw141292 #include "idmapd.h" 334520Snw141292 #include "idmap_priv.h" 34*5731Sbaban #include "nldaputils.h" 354520Snw141292 #include <signal.h> 364520Snw141292 #include <thread.h> 374520Snw141292 #include <string.h> 384520Snw141292 #include <strings.h> 394520Snw141292 #include <errno.h> 404520Snw141292 #include <assert.h> 414520Snw141292 #include <sys/types.h> 424520Snw141292 #include <sys/stat.h> 434520Snw141292 #include <ucred.h> 444520Snw141292 #include <pwd.h> 454520Snw141292 #include <auth_attr.h> 464520Snw141292 #include <secdb.h> 474520Snw141292 484520Snw141292 #define _VALIDATE_LIST_CB_DATA(col, val, siz)\ 494520Snw141292 retcode = validate_list_cb_data(cb_data, argc, argv, col,\ 504520Snw141292 (uchar_t **)val, siz);\ 514520Snw141292 if (retcode == IDMAP_NEXT) {\ 524520Snw141292 result->retcode = IDMAP_NEXT;\ 534520Snw141292 return (0);\ 544520Snw141292 } else if (retcode < 0) {\ 554520Snw141292 result->retcode = retcode;\ 564520Snw141292 return (1);\ 574520Snw141292 } 584520Snw141292 594520Snw141292 #define PROCESS_LIST_SVC_SQL(rcode, db, sql, limit, cb, res, len)\ 604520Snw141292 rcode = process_list_svc_sql(db, sql, limit, cb, res);\ 614520Snw141292 if (rcode == IDMAP_ERR_BUSY)\ 624520Snw141292 res->retcode = IDMAP_ERR_BUSY;\ 634520Snw141292 else if (rcode == IDMAP_SUCCESS && len == 0)\ 644520Snw141292 res->retcode = IDMAP_ERR_NOTFOUND; 654520Snw141292 664520Snw141292 675064Sdm199847 #define STRDUP_OR_FAIL(to, from) \ 685064Sdm199847 if ((from) == NULL) \ 695064Sdm199847 to = NULL; \ 705064Sdm199847 else { \ 715064Sdm199847 if ((to = strdup(from)) == NULL) \ 725064Sdm199847 return (1); \ 735064Sdm199847 } 745064Sdm199847 754520Snw141292 /* ARGSUSED */ 764520Snw141292 bool_t 775696Snw141292 idmap_null_1_svc(void *result, struct svc_req *rqstp) 785696Snw141292 { 794520Snw141292 return (TRUE); 804520Snw141292 } 814520Snw141292 825474Sbaban /* 835474Sbaban * RPC layer allocates empty strings to replace NULL char *. 845474Sbaban * This utility function frees these empty strings. 855474Sbaban */ 86*5731Sbaban static 87*5731Sbaban void 885474Sbaban sanitize_mapping_request(idmap_mapping *req) 895474Sbaban { 905474Sbaban free(req->id1name); 915474Sbaban req->id1name = NULL; 925474Sbaban free(req->id1domain); 935474Sbaban req->id1domain = NULL; 945474Sbaban free(req->id2name); 955474Sbaban req->id2name = NULL; 965474Sbaban free(req->id2domain); 975474Sbaban req->id2domain = NULL; 98*5731Sbaban req->direction = _IDMAP_F_DONE; 995474Sbaban } 1005474Sbaban 1014520Snw141292 /* ARGSUSED */ 1024520Snw141292 bool_t 1034520Snw141292 idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch, 1045696Snw141292 idmap_ids_res *result, struct svc_req *rqstp) 1055696Snw141292 { 1064520Snw141292 sqlite *cache = NULL, *db = NULL; 1074520Snw141292 lookup_state_t state; 108*5731Sbaban idmap_retcode retcode; 1094864Sbaban uint_t i; 1104520Snw141292 1114520Snw141292 /* Init */ 1124520Snw141292 (void) memset(result, 0, sizeof (*result)); 1134520Snw141292 (void) memset(&state, 0, sizeof (state)); 1144520Snw141292 1154520Snw141292 /* Return success if nothing was requested */ 1164520Snw141292 if (batch.idmap_mapping_batch_len < 1) 1174520Snw141292 goto out; 1184520Snw141292 1194520Snw141292 /* Get cache handle */ 1204520Snw141292 result->retcode = get_cache_handle(&cache); 1214520Snw141292 if (result->retcode != IDMAP_SUCCESS) 1224520Snw141292 goto out; 1234520Snw141292 1244520Snw141292 /* Get db handle */ 1254520Snw141292 result->retcode = get_db_handle(&db); 1264520Snw141292 if (result->retcode != IDMAP_SUCCESS) 1274520Snw141292 goto out; 1284520Snw141292 1294520Snw141292 /* Allocate result array */ 1304520Snw141292 result->ids.ids_val = calloc(batch.idmap_mapping_batch_len, 1315696Snw141292 sizeof (idmap_id_res)); 1324520Snw141292 if (result->ids.ids_val == NULL) { 1334520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 1344520Snw141292 result->retcode = IDMAP_ERR_MEMORY; 1354520Snw141292 goto out; 1364520Snw141292 } 1374520Snw141292 result->ids.ids_len = batch.idmap_mapping_batch_len; 1384520Snw141292 1394864Sbaban /* Allocate hash table to check for duplicate sids */ 1404864Sbaban state.sid_history = calloc(batch.idmap_mapping_batch_len, 1415696Snw141292 sizeof (*state.sid_history)); 1424864Sbaban if (state.sid_history == NULL) { 1434864Sbaban idmapdlog(LOG_ERR, "Out of memory"); 1444864Sbaban result->retcode = IDMAP_ERR_MEMORY; 1454864Sbaban goto out; 1464864Sbaban } 1474864Sbaban state.sid_history_size = batch.idmap_mapping_batch_len; 1484864Sbaban for (i = 0; i < state.sid_history_size; i++) { 1494864Sbaban state.sid_history[i].key = state.sid_history_size; 1504864Sbaban state.sid_history[i].next = state.sid_history_size; 1514864Sbaban } 1524864Sbaban state.batch = &batch; 1534864Sbaban state.result = result; 1544864Sbaban 155*5731Sbaban /* Get directory-based name mapping info */ 156*5731Sbaban result->retcode = get_ds_namemap_type(&state); 157*5731Sbaban if (result->retcode != IDMAP_SUCCESS) 158*5731Sbaban goto out; 159*5731Sbaban 1604520Snw141292 /* Init our 'done' flags */ 1614520Snw141292 state.sid2pid_done = state.pid2sid_done = TRUE; 1624520Snw141292 1634520Snw141292 /* First stage */ 1644520Snw141292 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 1654864Sbaban state.curpos = i; 1665474Sbaban (void) sanitize_mapping_request( 1675474Sbaban &batch.idmap_mapping_batch_val[i]); 1684520Snw141292 if (IS_BATCH_SID(batch, i)) { 1694520Snw141292 retcode = sid2pid_first_pass( 1705696Snw141292 &state, 1715696Snw141292 cache, 1725696Snw141292 &batch.idmap_mapping_batch_val[i], 1735696Snw141292 &result->ids.ids_val[i]); 1744520Snw141292 } else if (IS_BATCH_UID(batch, i)) { 1754520Snw141292 retcode = pid2sid_first_pass( 1765696Snw141292 &state, 1775696Snw141292 cache, 1785696Snw141292 &batch.idmap_mapping_batch_val[i], 1795696Snw141292 &result->ids.ids_val[i], 1, 0); 1804520Snw141292 } else if (IS_BATCH_GID(batch, i)) { 1814520Snw141292 retcode = pid2sid_first_pass( 1825696Snw141292 &state, 1835696Snw141292 cache, 1845696Snw141292 &batch.idmap_mapping_batch_val[i], 1855696Snw141292 &result->ids.ids_val[i], 0, 0); 1864520Snw141292 } else { 1874520Snw141292 result->ids.ids_val[i].retcode = IDMAP_ERR_IDTYPE; 1884520Snw141292 continue; 1894520Snw141292 } 1904520Snw141292 if (IDMAP_FATAL_ERROR(retcode)) { 1914520Snw141292 result->retcode = retcode; 1924520Snw141292 goto out; 1934520Snw141292 } 1944520Snw141292 } 1954520Snw141292 1964520Snw141292 /* Check if we are done */ 1974520Snw141292 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE) 1984520Snw141292 goto out; 1994520Snw141292 200*5731Sbaban /* 201*5731Sbaban * native LDAP lookups: 202*5731Sbaban * If nldap or mixed mode is enabled then pid2sid mapping requests 203*5731Sbaban * need to lookup native LDAP directory service by uid/gid to get 204*5731Sbaban * winname and unixname. 205*5731Sbaban */ 206*5731Sbaban if (state.nldap_nqueries) { 207*5731Sbaban retcode = nldap_lookup_batch(&state, &batch, result); 208*5731Sbaban if (IDMAP_FATAL_ERROR(retcode)) { 209*5731Sbaban result->retcode = retcode; 2104520Snw141292 goto out; 2114520Snw141292 } 212*5731Sbaban } 2134520Snw141292 214*5731Sbaban /* 215*5731Sbaban * AD lookups: 216*5731Sbaban * 1. The pid2sid requests in the preceding step which successfully 217*5731Sbaban * retrieved winname from native LDAP objects will now need to 218*5731Sbaban * lookup AD by winname to get sid. 219*5731Sbaban * 2. The sid2pid requests will need to lookup AD by sid to get 220*5731Sbaban * winname and unixname (AD or mixed mode). 221*5731Sbaban * 3. If AD-based name mapping is enabled then pid2sid mapping 222*5731Sbaban * requests need to lookup AD by unixname to get winname and sid. 223*5731Sbaban */ 224*5731Sbaban if (state.ad_nqueries) { 225*5731Sbaban retcode = ad_lookup_batch(&state, &batch, result); 226*5731Sbaban if (IDMAP_FATAL_ERROR(retcode)) { 227*5731Sbaban result->retcode = retcode; 228*5731Sbaban goto out; 229*5731Sbaban } 230*5731Sbaban } 231*5731Sbaban 232*5731Sbaban /* 233*5731Sbaban * native LDAP lookups: 234*5731Sbaban * If nldap mode is enabled then sid2pid mapping requests 235*5731Sbaban * which successfully retrieved winname from AD objects in the 236*5731Sbaban * preceding step, will now need to lookup native LDAP directory 237*5731Sbaban * service by winname to get unixname and pid. 238*5731Sbaban */ 239*5731Sbaban if (state.nldap_nqueries) { 240*5731Sbaban retcode = nldap_lookup_batch(&state, &batch, result); 241*5731Sbaban if (IDMAP_FATAL_ERROR(retcode)) { 242*5731Sbaban result->retcode = retcode; 243*5731Sbaban goto out; 244*5731Sbaban } 245*5731Sbaban } 246*5731Sbaban 247*5731Sbaban /* Reset 'done' flags */ 248*5731Sbaban state.sid2pid_done = state.pid2sid_done = TRUE; 2494520Snw141292 2504520Snw141292 /* Second stage */ 2514520Snw141292 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 2524864Sbaban state.curpos = i; 2534520Snw141292 if (IS_BATCH_SID(batch, i)) { 2544520Snw141292 retcode = sid2pid_second_pass( 2555696Snw141292 &state, 2565696Snw141292 cache, 2575696Snw141292 db, 2585696Snw141292 &batch.idmap_mapping_batch_val[i], 2595696Snw141292 &result->ids.ids_val[i]); 260*5731Sbaban } else if (IS_BATCH_UID(batch, i)) { 261*5731Sbaban retcode = pid2sid_second_pass( 262*5731Sbaban &state, 263*5731Sbaban cache, 264*5731Sbaban db, 265*5731Sbaban &batch.idmap_mapping_batch_val[i], 266*5731Sbaban &result->ids.ids_val[i], 1); 267*5731Sbaban } else if (IS_BATCH_GID(batch, i)) { 268*5731Sbaban retcode = pid2sid_second_pass( 269*5731Sbaban &state, 270*5731Sbaban cache, 271*5731Sbaban db, 272*5731Sbaban &batch.idmap_mapping_batch_val[i], 273*5731Sbaban &result->ids.ids_val[i], 0); 274*5731Sbaban } else { 275*5731Sbaban /* First stage has already set the error */ 276*5731Sbaban continue; 277*5731Sbaban } 278*5731Sbaban if (IDMAP_FATAL_ERROR(retcode)) { 279*5731Sbaban result->retcode = retcode; 280*5731Sbaban goto out; 2814520Snw141292 } 2824520Snw141292 } 2834520Snw141292 2844520Snw141292 /* Check if we are done */ 2854520Snw141292 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE) 2864520Snw141292 goto out; 2874520Snw141292 2884520Snw141292 /* Reset our 'done' flags */ 2894520Snw141292 state.sid2pid_done = state.pid2sid_done = TRUE; 2904520Snw141292 2914520Snw141292 /* Update cache in a single transaction */ 2924520Snw141292 if (sql_exec_no_cb(cache, "BEGIN TRANSACTION;") != IDMAP_SUCCESS) 2934520Snw141292 goto out; 2944520Snw141292 2954520Snw141292 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 2964864Sbaban state.curpos = i; 2974520Snw141292 if (IS_BATCH_SID(batch, i)) { 2984520Snw141292 (void) update_cache_sid2pid( 2995696Snw141292 &state, 3005696Snw141292 cache, 3015696Snw141292 &batch.idmap_mapping_batch_val[i], 3025696Snw141292 &result->ids.ids_val[i]); 3034520Snw141292 } else if ((IS_BATCH_UID(batch, i)) || 3045696Snw141292 (IS_BATCH_GID(batch, i))) { 3054520Snw141292 (void) update_cache_pid2sid( 3065696Snw141292 &state, 3075696Snw141292 cache, 3085696Snw141292 &batch.idmap_mapping_batch_val[i], 3095696Snw141292 &result->ids.ids_val[i]); 3104520Snw141292 } 3114520Snw141292 } 3124520Snw141292 3135331Samw /* Commit if we have at least one successful update */ 3144520Snw141292 if (state.sid2pid_done == FALSE || state.pid2sid_done == FALSE) 3154520Snw141292 (void) sql_exec_no_cb(cache, "COMMIT TRANSACTION;"); 3164520Snw141292 else 3174520Snw141292 (void) sql_exec_no_cb(cache, "END TRANSACTION;"); 3184520Snw141292 3194520Snw141292 out: 320*5731Sbaban cleanup_lookup_state(&state); 3214520Snw141292 if (IDMAP_ERROR(result->retcode)) { 3224520Snw141292 xdr_free(xdr_idmap_ids_res, (caddr_t)result); 3234520Snw141292 result->ids.ids_len = 0; 3244520Snw141292 result->ids.ids_val = NULL; 3254520Snw141292 } 3264520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 3274520Snw141292 return (TRUE); 3284520Snw141292 } 3294520Snw141292 3304520Snw141292 3314520Snw141292 /* ARGSUSED */ 3325696Snw141292 static 3335696Snw141292 int 3345696Snw141292 list_mappings_cb(void *parg, int argc, char **argv, char **colnames) 3355696Snw141292 { 3364520Snw141292 list_cb_data_t *cb_data; 3374520Snw141292 char *str; 3384520Snw141292 idmap_mappings_res *result; 3394520Snw141292 idmap_retcode retcode; 3404520Snw141292 int w2u, u2w; 3414520Snw141292 char *end; 3425696Snw141292 static int validated_column_names = 0; 3435696Snw141292 3445696Snw141292 if (!validated_column_names) { 3455696Snw141292 assert(strcmp(colnames[0], "rowid") == 0); 3465696Snw141292 assert(strcmp(colnames[1], "sidprefix") == 0); 3475696Snw141292 assert(strcmp(colnames[2], "rid") == 0); 3485696Snw141292 assert(strcmp(colnames[3], "pid") == 0); 3495696Snw141292 assert(strcmp(colnames[4], "w2u") == 0); 3505696Snw141292 assert(strcmp(colnames[5], "u2w") == 0); 3515696Snw141292 assert(strcmp(colnames[6], "windomain") == 0); 3525696Snw141292 assert(strcmp(colnames[7], "canon_winname") == 0); 3535696Snw141292 assert(strcmp(colnames[8], "unixname") == 0); 3545696Snw141292 assert(strcmp(colnames[9], "is_user") == 0); 3555696Snw141292 assert(strcmp(colnames[10], "is_wuser") == 0); 3565696Snw141292 validated_column_names = 1; 3575696Snw141292 } 3585696Snw141292 3594520Snw141292 3604520Snw141292 cb_data = (list_cb_data_t *)parg; 3614520Snw141292 result = (idmap_mappings_res *)cb_data->result; 3624520Snw141292 3635696Snw141292 _VALIDATE_LIST_CB_DATA(11, &result->mappings.mappings_val, 3645696Snw141292 sizeof (idmap_mapping)); 3654520Snw141292 3664520Snw141292 result->mappings.mappings_len++; 3674520Snw141292 3684520Snw141292 if ((str = strdup(argv[1])) == NULL) 3694520Snw141292 return (1); 3704520Snw141292 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.prefix = 3715696Snw141292 str; 3724520Snw141292 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.rid = 3735696Snw141292 strtoul(argv[2], &end, 10); 3745696Snw141292 result->mappings.mappings_val[cb_data->next].id1.idtype = 3755696Snw141292 strtol(argv[10], &end, 10) ? IDMAP_USID : IDMAP_GSID; 3764520Snw141292 3774520Snw141292 result->mappings.mappings_val[cb_data->next].id2.idmap_id_u.uid = 3785696Snw141292 strtoul(argv[3], &end, 10); 3795696Snw141292 result->mappings.mappings_val[cb_data->next].id2.idtype = 3805696Snw141292 strtol(argv[9], &end, 10) ? IDMAP_UID : IDMAP_GID; 3814520Snw141292 3825696Snw141292 w2u = argv[4] ? strtol(argv[4], &end, 10) : 0; 3835696Snw141292 u2w = argv[5] ? strtol(argv[5], &end, 10) : 0; 3844520Snw141292 3854520Snw141292 if (w2u > 0 && u2w == 0) 3864644Sbaban result->mappings.mappings_val[cb_data->next].direction = 3874644Sbaban IDMAP_DIRECTION_W2U; 3884520Snw141292 else if (w2u == 0 && u2w > 0) 3894644Sbaban result->mappings.mappings_val[cb_data->next].direction = 3904644Sbaban IDMAP_DIRECTION_U2W; 3914520Snw141292 else 3924644Sbaban result->mappings.mappings_val[cb_data->next].direction = 3934644Sbaban IDMAP_DIRECTION_BI; 3944520Snw141292 3955064Sdm199847 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1domain, 3965064Sdm199847 argv[6]); 3974520Snw141292 3985064Sdm199847 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1name, 3995064Sdm199847 argv[7]); 4004520Snw141292 4015064Sdm199847 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id2name, 4025064Sdm199847 argv[8]); 4035064Sdm199847 4044520Snw141292 4054520Snw141292 result->lastrowid = strtoll(argv[0], &end, 10); 4064520Snw141292 cb_data->next++; 4074520Snw141292 result->retcode = IDMAP_SUCCESS; 4084520Snw141292 return (0); 4094520Snw141292 } 4104520Snw141292 4114520Snw141292 4124520Snw141292 /* ARGSUSED */ 4134520Snw141292 bool_t 4145696Snw141292 idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, 4155696Snw141292 idmap_mappings_res *result, struct svc_req *rqstp) 4165696Snw141292 { 4174520Snw141292 sqlite *cache = NULL; 4184520Snw141292 char lbuf[30], rbuf[30]; 4194520Snw141292 uint64_t maxlimit; 4204520Snw141292 idmap_retcode retcode; 4214520Snw141292 char *sql = NULL; 4224520Snw141292 4234520Snw141292 (void) memset(result, 0, sizeof (*result)); 4244520Snw141292 lbuf[0] = rbuf[0] = 0; 4254520Snw141292 4264520Snw141292 RDLOCK_CONFIG(); 4274520Snw141292 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; 4284520Snw141292 UNLOCK_CONFIG(); 4294520Snw141292 4304520Snw141292 /* Get cache handle */ 4314520Snw141292 result->retcode = get_cache_handle(&cache); 4324520Snw141292 if (result->retcode != IDMAP_SUCCESS) 4334520Snw141292 goto out; 4344520Snw141292 4354520Snw141292 result->retcode = IDMAP_ERR_INTERNAL; 4364520Snw141292 4374520Snw141292 /* Create LIMIT expression. */ 4384520Snw141292 if (limit == 0 || (maxlimit > 0 && maxlimit < limit)) 4394520Snw141292 limit = maxlimit; 4404520Snw141292 if (limit > 0) 4414520Snw141292 (void) snprintf(lbuf, sizeof (lbuf), 4425696Snw141292 "LIMIT %" PRIu64, limit + 1ULL); 4434520Snw141292 4444520Snw141292 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid); 4454520Snw141292 4464520Snw141292 /* 4474520Snw141292 * Combine all the above into a giant SELECT statement that 4484520Snw141292 * will return the requested mappings 4494520Snw141292 */ 4505696Snw141292 sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, u2w, " 4515696Snw141292 "windomain, canon_winname, unixname, is_user, is_wuser " 4525696Snw141292 " FROM idmap_cache WHERE " 4535696Snw141292 " %s %s;", 4545696Snw141292 rbuf, lbuf); 4554520Snw141292 if (sql == NULL) { 4564520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 4574520Snw141292 goto out; 4584520Snw141292 } 4594520Snw141292 4604520Snw141292 /* Execute the SQL statement and update the return buffer */ 4614520Snw141292 PROCESS_LIST_SVC_SQL(retcode, cache, sql, limit, list_mappings_cb, 4625696Snw141292 result, result->mappings.mappings_len); 4634520Snw141292 4644520Snw141292 out: 4654520Snw141292 if (sql) 4664520Snw141292 sqlite_freemem(sql); 4674520Snw141292 if (IDMAP_ERROR(result->retcode)) 4684520Snw141292 (void) xdr_free(xdr_idmap_mappings_res, (caddr_t)result); 4694520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 4704520Snw141292 return (TRUE); 4714520Snw141292 } 4724520Snw141292 4734520Snw141292 4744520Snw141292 /* ARGSUSED */ 4755696Snw141292 static 4765696Snw141292 int 4775696Snw141292 list_namerules_cb(void *parg, int argc, char **argv, char **colnames) 4785696Snw141292 { 4794520Snw141292 list_cb_data_t *cb_data; 4804520Snw141292 idmap_namerules_res *result; 4814520Snw141292 idmap_retcode retcode; 4824520Snw141292 int w2u_order, u2w_order; 4834520Snw141292 char *end; 4845696Snw141292 static int validated_column_names = 0; 4855696Snw141292 4865696Snw141292 if (!validated_column_names) { 4875696Snw141292 assert(strcmp(colnames[0], "rowid") == 0); 4885696Snw141292 assert(strcmp(colnames[1], "is_user") == 0); 4895696Snw141292 assert(strcmp(colnames[2], "is_wuser") == 0); 4905696Snw141292 assert(strcmp(colnames[3], "windomain") == 0); 4915696Snw141292 assert(strcmp(colnames[4], "winname_display") == 0); 4925696Snw141292 assert(strcmp(colnames[5], "is_nt4") == 0); 4935696Snw141292 assert(strcmp(colnames[6], "unixname") == 0); 4945696Snw141292 assert(strcmp(colnames[7], "w2u_order") == 0); 4955696Snw141292 assert(strcmp(colnames[8], "u2w_order") == 0); 4965696Snw141292 validated_column_names = 1; 4975696Snw141292 } 4984520Snw141292 4994520Snw141292 cb_data = (list_cb_data_t *)parg; 5004520Snw141292 result = (idmap_namerules_res *)cb_data->result; 5014520Snw141292 5025696Snw141292 _VALIDATE_LIST_CB_DATA(9, &result->rules.rules_val, 5035696Snw141292 sizeof (idmap_namerule)); 5044520Snw141292 5054520Snw141292 result->rules.rules_len++; 5064520Snw141292 5074520Snw141292 result->rules.rules_val[cb_data->next].is_user = 5085696Snw141292 strtol(argv[1], &end, 10); 5095696Snw141292 5105696Snw141292 result->rules.rules_val[cb_data->next].is_wuser = 5115696Snw141292 strtol(argv[2], &end, 10); 5124520Snw141292 5135064Sdm199847 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].windomain, 5145064Sdm199847 argv[3]); 5154520Snw141292 5165696Snw141292 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].winname, 5175696Snw141292 argv[4]); 5185696Snw141292 5194520Snw141292 result->rules.rules_val[cb_data->next].is_nt4 = 5205696Snw141292 strtol(argv[5], &end, 10); 5214520Snw141292 5225064Sdm199847 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].unixname, 5235696Snw141292 argv[6]); 5244520Snw141292 5255696Snw141292 w2u_order = argv[7] ? strtol(argv[7], &end, 10) : 0; 5265696Snw141292 u2w_order = argv[8] ? strtol(argv[8], &end, 10) : 0; 5274520Snw141292 5284520Snw141292 if (w2u_order > 0 && u2w_order == 0) 5294644Sbaban result->rules.rules_val[cb_data->next].direction = 5304644Sbaban IDMAP_DIRECTION_W2U; 5314520Snw141292 else if (w2u_order == 0 && u2w_order > 0) 5324644Sbaban result->rules.rules_val[cb_data->next].direction = 5334644Sbaban IDMAP_DIRECTION_U2W; 5344520Snw141292 else 5354644Sbaban result->rules.rules_val[cb_data->next].direction = 5364644Sbaban IDMAP_DIRECTION_BI; 5374520Snw141292 5384520Snw141292 result->lastrowid = strtoll(argv[0], &end, 10); 5394520Snw141292 cb_data->next++; 5404520Snw141292 result->retcode = IDMAP_SUCCESS; 5414520Snw141292 return (0); 5424520Snw141292 } 5434520Snw141292 5444520Snw141292 5454520Snw141292 /* ARGSUSED */ 5464520Snw141292 bool_t 5474520Snw141292 idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid, 5484520Snw141292 uint64_t limit, idmap_namerules_res *result, 5495696Snw141292 struct svc_req *rqstp) 5505696Snw141292 { 5514520Snw141292 5524520Snw141292 sqlite *db = NULL; 5534520Snw141292 char w2ubuf[15], u2wbuf[15]; 5544520Snw141292 char lbuf[30], rbuf[30]; 5554520Snw141292 char *sql = NULL; 5565696Snw141292 char *expr = NULL; 5574520Snw141292 uint64_t maxlimit; 5584520Snw141292 idmap_retcode retcode; 5594520Snw141292 5604520Snw141292 (void) memset(result, 0, sizeof (*result)); 5614520Snw141292 lbuf[0] = rbuf[0] = 0; 5624520Snw141292 5634520Snw141292 RDLOCK_CONFIG(); 5644520Snw141292 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; 5654520Snw141292 UNLOCK_CONFIG(); 5664520Snw141292 5674520Snw141292 /* Get db handle */ 5684520Snw141292 result->retcode = get_db_handle(&db); 5694520Snw141292 if (result->retcode != IDMAP_SUCCESS) 5704520Snw141292 goto out; 5714520Snw141292 5724520Snw141292 result->retcode = IDMAP_ERR_INTERNAL; 5734520Snw141292 5745696Snw141292 w2ubuf[0] = u2wbuf[0] = 0; 5755696Snw141292 if (rule.direction == IDMAP_DIRECTION_BI) { 5764520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0"); 5774520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0"); 5784644Sbaban } else if (rule.direction == IDMAP_DIRECTION_W2U) { 5794520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0"); 5804520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), 5815696Snw141292 "AND (u2w_order = 0 OR u2w_order ISNULL)"); 5824644Sbaban } else if (rule.direction == IDMAP_DIRECTION_U2W) { 5834520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), 5845696Snw141292 "AND (w2u_order = 0 OR w2u_order ISNULL)"); 5854520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0"); 5864520Snw141292 } 5874520Snw141292 5885696Snw141292 retcode = gen_sql_expr_from_rule(&rule, &expr); 5895696Snw141292 if (retcode != IDMAP_SUCCESS) 5905696Snw141292 goto out; 5914520Snw141292 5924520Snw141292 /* Create LIMIT expression. */ 5934520Snw141292 if (limit == 0 || (maxlimit > 0 && maxlimit < limit)) 5944520Snw141292 limit = maxlimit; 5954520Snw141292 if (limit > 0) 5964520Snw141292 (void) snprintf(lbuf, sizeof (lbuf), 5975696Snw141292 "LIMIT %" PRIu64, limit + 1ULL); 5984520Snw141292 5994520Snw141292 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid); 6004520Snw141292 6014520Snw141292 /* 6024520Snw141292 * Combine all the above into a giant SELECT statement that 6034520Snw141292 * will return the requested rules 6044520Snw141292 */ 6055696Snw141292 sql = sqlite_mprintf("SELECT rowid, is_user, is_wuser, windomain, " 6065696Snw141292 "winname_display, is_nt4, unixname, w2u_order, u2w_order " 6075696Snw141292 "FROM namerules WHERE " 6085696Snw141292 " %s %s %s %s %s;", 6095696Snw141292 rbuf, expr, w2ubuf, u2wbuf, lbuf); 6105696Snw141292 6114520Snw141292 if (sql == NULL) { 6124520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 6134520Snw141292 goto out; 6144520Snw141292 } 6154520Snw141292 6164520Snw141292 /* Execute the SQL statement and update the return buffer */ 6174520Snw141292 PROCESS_LIST_SVC_SQL(retcode, db, sql, limit, list_namerules_cb, 6185696Snw141292 result, result->rules.rules_len); 6194520Snw141292 6204520Snw141292 out: 6215696Snw141292 if (expr) 6225696Snw141292 sqlite_freemem(expr); 6234520Snw141292 if (sql) 6244520Snw141292 sqlite_freemem(sql); 6254520Snw141292 if (IDMAP_ERROR(result->retcode)) 6264520Snw141292 (void) xdr_free(xdr_idmap_namerules_res, (caddr_t)result); 6274520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 6284520Snw141292 return (TRUE); 6294520Snw141292 } 6304520Snw141292 6314520Snw141292 #define IDMAP_RULES_AUTH "solaris.admin.idmap.rules" 6324520Snw141292 static int 6335696Snw141292 verify_rules_auth(struct svc_req *rqstp) 6345696Snw141292 { 6354520Snw141292 ucred_t *uc = NULL; 6364520Snw141292 uid_t uid; 6374520Snw141292 char buf[1024]; 6384520Snw141292 struct passwd pwd; 6394520Snw141292 const char *me = "verify_rules_auth"; 6404520Snw141292 6414520Snw141292 if (svc_getcallerucred(rqstp->rq_xprt, &uc) != 0) { 6424520Snw141292 idmapdlog(LOG_ERR, 6435696Snw141292 "%s: svc_getcallerucred failed (errno=%d)", 6445696Snw141292 me, errno); 6454520Snw141292 return (-1); 6464520Snw141292 } 6474520Snw141292 6484520Snw141292 uid = ucred_geteuid(uc); 6494520Snw141292 if (uid == (uid_t)-1) { 6504520Snw141292 idmapdlog(LOG_ERR, 6515696Snw141292 "%s: ucred_geteuid failed (errno=%d)", 6525696Snw141292 me, errno); 6534520Snw141292 ucred_free(uc); 6544520Snw141292 return (-1); 6554520Snw141292 } 6564520Snw141292 6574520Snw141292 if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) { 6584520Snw141292 idmapdlog(LOG_ERR, 6595696Snw141292 "%s: getpwuid_r(%u) failed (errno=%d)", 6605696Snw141292 me, uid, errno); 6614520Snw141292 ucred_free(uc); 6624520Snw141292 return (-1); 6634520Snw141292 } 6644520Snw141292 6654520Snw141292 if (chkauthattr(IDMAP_RULES_AUTH, pwd.pw_name) != 1) { 6664520Snw141292 idmapdlog(LOG_INFO, 6675696Snw141292 "%s: %s does not have authorization.", 6685696Snw141292 me, pwd.pw_name); 6694520Snw141292 ucred_free(uc); 6704520Snw141292 return (-1); 6714520Snw141292 } 6724520Snw141292 6734520Snw141292 ucred_free(uc); 6744520Snw141292 return (1); 6754520Snw141292 } 6764520Snw141292 6775064Sdm199847 /* 6785064Sdm199847 * Meaning of the return values is the following: For retcode == 6795064Sdm199847 * IDMAP_SUCCESS, everything went OK and error_index is 6805064Sdm199847 * undefined. Otherwise, error_index >=0 shows the failed batch 6815064Sdm199847 * element. errro_index == -1 indicates failure at the beginning, 6825064Sdm199847 * error_index == -2 at the end. 6835064Sdm199847 */ 6845064Sdm199847 6854520Snw141292 /* ARGSUSED */ 6864520Snw141292 bool_t 6875064Sdm199847 idmap_update_1_svc(idmap_update_batch batch, idmap_update_res *res, 6885696Snw141292 struct svc_req *rqstp) 6895696Snw141292 { 6904520Snw141292 sqlite *db = NULL; 6914520Snw141292 idmap_update_op *up; 6924520Snw141292 int i; 6934884Sjp151216 int trans = FALSE; 6944520Snw141292 6955064Sdm199847 res->error_index = -1; 6965064Sdm199847 (void) memset(&res->error_rule, 0, sizeof (res->error_rule)); 6975064Sdm199847 (void) memset(&res->conflict_rule, 0, sizeof (res->conflict_rule)); 6985064Sdm199847 6994520Snw141292 if (verify_rules_auth(rqstp) < 0) { 7005064Sdm199847 res->retcode = IDMAP_ERR_PERMISSION_DENIED; 7014520Snw141292 goto out; 7024520Snw141292 } 7034520Snw141292 7044520Snw141292 if (batch.idmap_update_batch_len == 0 || 7055696Snw141292 batch.idmap_update_batch_val == NULL) { 7065064Sdm199847 res->retcode = IDMAP_SUCCESS; 7074520Snw141292 goto out; 7084520Snw141292 } 7094520Snw141292 7104520Snw141292 /* Get db handle */ 7115064Sdm199847 res->retcode = get_db_handle(&db); 7125064Sdm199847 if (res->retcode != IDMAP_SUCCESS) 7134520Snw141292 goto out; 7144520Snw141292 7155064Sdm199847 res->retcode = sql_exec_no_cb(db, "BEGIN TRANSACTION;"); 7165064Sdm199847 if (res->retcode != IDMAP_SUCCESS) 7174520Snw141292 goto out; 7184884Sjp151216 trans = TRUE; 7194520Snw141292 7204520Snw141292 for (i = 0; i < batch.idmap_update_batch_len; i++) { 7214520Snw141292 up = &batch.idmap_update_batch_val[i]; 7224520Snw141292 switch (up->opnum) { 7234520Snw141292 case OP_NONE: 7245064Sdm199847 res->retcode = IDMAP_SUCCESS; 7254520Snw141292 break; 7264520Snw141292 case OP_ADD_NAMERULE: 7275064Sdm199847 res->retcode = add_namerule(db, 7285696Snw141292 &up->idmap_update_op_u.rule); 7294520Snw141292 break; 7304520Snw141292 case OP_RM_NAMERULE: 7315064Sdm199847 res->retcode = rm_namerule(db, 7325696Snw141292 &up->idmap_update_op_u.rule); 7334520Snw141292 break; 7344520Snw141292 case OP_FLUSH_NAMERULES: 7355696Snw141292 res->retcode = flush_namerules(db); 7364520Snw141292 break; 7374520Snw141292 default: 7385064Sdm199847 res->retcode = IDMAP_ERR_NOTSUPPORTED; 7395064Sdm199847 break; 7404520Snw141292 }; 7414520Snw141292 7425064Sdm199847 if (res->retcode != IDMAP_SUCCESS) { 7435064Sdm199847 res->error_index = i; 7445064Sdm199847 if (up->opnum == OP_ADD_NAMERULE || 7455064Sdm199847 up->opnum == OP_RM_NAMERULE) { 7465064Sdm199847 idmap_stat r2 = 7475064Sdm199847 idmap_namerule_cpy(&res->error_rule, 7485696Snw141292 &up->idmap_update_op_u.rule); 7495064Sdm199847 if (r2 != IDMAP_SUCCESS) 7505064Sdm199847 res->retcode = r2; 7515064Sdm199847 } 7524520Snw141292 goto out; 7535064Sdm199847 } 7544520Snw141292 } 7554520Snw141292 7564520Snw141292 out: 7574884Sjp151216 if (trans) { 7585064Sdm199847 if (res->retcode == IDMAP_SUCCESS) { 7595064Sdm199847 res->retcode = 7605064Sdm199847 sql_exec_no_cb(db, "COMMIT TRANSACTION;"); 7615064Sdm199847 if (res->retcode != IDMAP_SUCCESS) 7625064Sdm199847 res->error_index = -2; 7635064Sdm199847 } 7644884Sjp151216 else 7654884Sjp151216 (void) sql_exec_no_cb(db, "ROLLBACK TRANSACTION;"); 7664520Snw141292 } 7675064Sdm199847 7685064Sdm199847 res->retcode = idmap_stat4prot(res->retcode); 7695064Sdm199847 7704520Snw141292 return (TRUE); 7714520Snw141292 } 7724520Snw141292 7734520Snw141292 7744520Snw141292 /* ARGSUSED */ 7754520Snw141292 bool_t 7764520Snw141292 idmap_get_mapped_id_by_name_1_svc(idmap_mapping request, 7775696Snw141292 idmap_mappings_res *result, struct svc_req *rqstp) 7785696Snw141292 { 7794520Snw141292 sqlite *cache = NULL, *db = NULL; 7804520Snw141292 7814520Snw141292 /* Init */ 7824520Snw141292 (void) memset(result, 0, sizeof (*result)); 7834520Snw141292 7844520Snw141292 /* Get cache handle */ 7854520Snw141292 result->retcode = get_cache_handle(&cache); 7864520Snw141292 if (result->retcode != IDMAP_SUCCESS) 7874520Snw141292 goto out; 7884520Snw141292 7894520Snw141292 /* Get db handle */ 7904520Snw141292 result->retcode = get_db_handle(&db); 7914520Snw141292 if (result->retcode != IDMAP_SUCCESS) 7924520Snw141292 goto out; 7934520Snw141292 7944520Snw141292 /* Allocate result */ 7954520Snw141292 result->mappings.mappings_val = calloc(1, sizeof (idmap_mapping)); 7964520Snw141292 if (result->mappings.mappings_val == NULL) { 7974520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 7984520Snw141292 result->retcode = IDMAP_ERR_MEMORY; 7994520Snw141292 goto out; 8004520Snw141292 } 8014520Snw141292 result->mappings.mappings_len = 1; 8024520Snw141292 8035696Snw141292 8045696Snw141292 if (IS_REQUEST_SID(request, 1)) { 8054520Snw141292 result->retcode = get_w2u_mapping( 8065696Snw141292 cache, 8075696Snw141292 db, 8085696Snw141292 &request, 8095696Snw141292 result->mappings.mappings_val); 8104520Snw141292 } else if (IS_REQUEST_UID(request)) { 8114520Snw141292 result->retcode = get_u2w_mapping( 8125696Snw141292 cache, 8135696Snw141292 db, 8145696Snw141292 &request, 8155696Snw141292 result->mappings.mappings_val, 8165696Snw141292 1); 8174520Snw141292 } else if (IS_REQUEST_GID(request)) { 8184520Snw141292 result->retcode = get_u2w_mapping( 8195696Snw141292 cache, 8205696Snw141292 db, 8215696Snw141292 &request, 8225696Snw141292 result->mappings.mappings_val, 8235696Snw141292 0); 8244520Snw141292 } else { 8254520Snw141292 result->retcode = IDMAP_ERR_IDTYPE; 8264520Snw141292 } 8274520Snw141292 8284520Snw141292 out: 8294520Snw141292 if (IDMAP_FATAL_ERROR(result->retcode)) { 8304520Snw141292 xdr_free(xdr_idmap_mappings_res, (caddr_t)result); 8314520Snw141292 result->mappings.mappings_len = 0; 8324520Snw141292 result->mappings.mappings_val = NULL; 8334520Snw141292 } 8344520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 8354520Snw141292 return (TRUE); 8364520Snw141292 } 8374520Snw141292 8384520Snw141292 8394520Snw141292 /* ARGSUSED */ 8404520Snw141292 int 8414520Snw141292 idmap_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, 8425696Snw141292 caddr_t result) 8435696Snw141292 { 8444520Snw141292 (void) xdr_free(xdr_result, result); 8454520Snw141292 return (TRUE); 8464520Snw141292 } 847