1*4520Snw141292 /* 2*4520Snw141292 * CDDL HEADER START 3*4520Snw141292 * 4*4520Snw141292 * The contents of this file are subject to the terms of the 5*4520Snw141292 * Common Development and Distribution License (the "License"). 6*4520Snw141292 * You may not use this file except in compliance with the License. 7*4520Snw141292 * 8*4520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4520Snw141292 * or http://www.opensolaris.org/os/licensing. 10*4520Snw141292 * See the License for the specific language governing permissions 11*4520Snw141292 * and limitations under the License. 12*4520Snw141292 * 13*4520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 14*4520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 16*4520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17*4520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18*4520Snw141292 * 19*4520Snw141292 * CDDL HEADER END 20*4520Snw141292 */ 21*4520Snw141292 /* 22*4520Snw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*4520Snw141292 * Use is subject to license terms. 24*4520Snw141292 */ 25*4520Snw141292 26*4520Snw141292 #pragma ident "%Z%%M% %I% %E% SMI" 27*4520Snw141292 28*4520Snw141292 /* 29*4520Snw141292 * Service routines 30*4520Snw141292 */ 31*4520Snw141292 32*4520Snw141292 #include "idmapd.h" 33*4520Snw141292 #include "idmap_priv.h" 34*4520Snw141292 #include <signal.h> 35*4520Snw141292 #include <thread.h> 36*4520Snw141292 #include <string.h> 37*4520Snw141292 #include <strings.h> 38*4520Snw141292 #include <errno.h> 39*4520Snw141292 #include <assert.h> 40*4520Snw141292 #include <sys/types.h> 41*4520Snw141292 #include <sys/stat.h> 42*4520Snw141292 #include <ucred.h> 43*4520Snw141292 #include <pwd.h> 44*4520Snw141292 #include <auth_attr.h> 45*4520Snw141292 #include <secdb.h> 46*4520Snw141292 47*4520Snw141292 #define _VALIDATE_LIST_CB_DATA(col, val, siz)\ 48*4520Snw141292 retcode = validate_list_cb_data(cb_data, argc, argv, col,\ 49*4520Snw141292 (uchar_t **)val, siz);\ 50*4520Snw141292 if (retcode == IDMAP_NEXT) {\ 51*4520Snw141292 result->retcode = IDMAP_NEXT;\ 52*4520Snw141292 return (0);\ 53*4520Snw141292 } else if (retcode < 0) {\ 54*4520Snw141292 result->retcode = retcode;\ 55*4520Snw141292 return (1);\ 56*4520Snw141292 } 57*4520Snw141292 58*4520Snw141292 #define PROCESS_LIST_SVC_SQL(rcode, db, sql, limit, cb, res, len)\ 59*4520Snw141292 rcode = process_list_svc_sql(db, sql, limit, cb, res);\ 60*4520Snw141292 if (rcode == IDMAP_ERR_BUSY)\ 61*4520Snw141292 res->retcode = IDMAP_ERR_BUSY;\ 62*4520Snw141292 else if (rcode == IDMAP_SUCCESS && len == 0)\ 63*4520Snw141292 res->retcode = IDMAP_ERR_NOTFOUND; 64*4520Snw141292 65*4520Snw141292 66*4520Snw141292 /* ARGSUSED */ 67*4520Snw141292 bool_t 68*4520Snw141292 idmap_null_1_svc(void *result, struct svc_req *rqstp) { 69*4520Snw141292 return (TRUE); 70*4520Snw141292 } 71*4520Snw141292 72*4520Snw141292 #define IS_BATCH_SID(batch, i)\ 73*4520Snw141292 batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_SID 74*4520Snw141292 75*4520Snw141292 #define IS_BATCH_UID(batch, i)\ 76*4520Snw141292 batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_UID 77*4520Snw141292 78*4520Snw141292 #define IS_BATCH_GID(batch, i)\ 79*4520Snw141292 batch.idmap_mapping_batch_val[i].id1.idtype == IDMAP_GID 80*4520Snw141292 81*4520Snw141292 #define IS_REQUEST_SID(request)\ 82*4520Snw141292 request.id1.idtype == IDMAP_SID 83*4520Snw141292 84*4520Snw141292 #define IS_REQUEST_UID(request)\ 85*4520Snw141292 request.id1.idtype == IDMAP_UID 86*4520Snw141292 87*4520Snw141292 #define IS_REQUEST_GID(request)\ 88*4520Snw141292 request.id1.idtype == IDMAP_GID 89*4520Snw141292 90*4520Snw141292 /* ARGSUSED */ 91*4520Snw141292 bool_t 92*4520Snw141292 idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch, 93*4520Snw141292 idmap_ids_res *result, struct svc_req *rqstp) { 94*4520Snw141292 sqlite *cache = NULL, *db = NULL; 95*4520Snw141292 lookup_state_t state; 96*4520Snw141292 idmap_retcode retcode, winrc; 97*4520Snw141292 int i; 98*4520Snw141292 99*4520Snw141292 /* Init */ 100*4520Snw141292 (void) memset(result, 0, sizeof (*result)); 101*4520Snw141292 (void) memset(&state, 0, sizeof (state)); 102*4520Snw141292 103*4520Snw141292 /* Return success if nothing was requested */ 104*4520Snw141292 if (batch.idmap_mapping_batch_len < 1) 105*4520Snw141292 goto out; 106*4520Snw141292 107*4520Snw141292 /* Get cache handle */ 108*4520Snw141292 result->retcode = get_cache_handle(&cache); 109*4520Snw141292 if (result->retcode != IDMAP_SUCCESS) 110*4520Snw141292 goto out; 111*4520Snw141292 112*4520Snw141292 /* Get db handle */ 113*4520Snw141292 result->retcode = get_db_handle(&db); 114*4520Snw141292 if (result->retcode != IDMAP_SUCCESS) 115*4520Snw141292 goto out; 116*4520Snw141292 117*4520Snw141292 /* Allocate result array */ 118*4520Snw141292 result->ids.ids_val = calloc(batch.idmap_mapping_batch_len, 119*4520Snw141292 sizeof (idmap_id_res)); 120*4520Snw141292 if (result->ids.ids_val == NULL) { 121*4520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 122*4520Snw141292 result->retcode = IDMAP_ERR_MEMORY; 123*4520Snw141292 goto out; 124*4520Snw141292 } 125*4520Snw141292 result->ids.ids_len = batch.idmap_mapping_batch_len; 126*4520Snw141292 127*4520Snw141292 /* Init our 'done' flags */ 128*4520Snw141292 state.sid2pid_done = state.pid2sid_done = TRUE; 129*4520Snw141292 130*4520Snw141292 /* First stage */ 131*4520Snw141292 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 132*4520Snw141292 if (IS_BATCH_SID(batch, i)) { 133*4520Snw141292 retcode = sid2pid_first_pass( 134*4520Snw141292 &state, 135*4520Snw141292 cache, 136*4520Snw141292 &batch.idmap_mapping_batch_val[i], 137*4520Snw141292 &result->ids.ids_val[i]); 138*4520Snw141292 } else if (IS_BATCH_UID(batch, i)) { 139*4520Snw141292 retcode = pid2sid_first_pass( 140*4520Snw141292 &state, 141*4520Snw141292 cache, 142*4520Snw141292 db, 143*4520Snw141292 &batch.idmap_mapping_batch_val[i], 144*4520Snw141292 &result->ids.ids_val[i], 1, 0); 145*4520Snw141292 } else if (IS_BATCH_GID(batch, i)) { 146*4520Snw141292 retcode = pid2sid_first_pass( 147*4520Snw141292 &state, 148*4520Snw141292 cache, 149*4520Snw141292 db, 150*4520Snw141292 &batch.idmap_mapping_batch_val[i], 151*4520Snw141292 &result->ids.ids_val[i], 0, 0); 152*4520Snw141292 } else { 153*4520Snw141292 result->ids.ids_val[i].retcode = IDMAP_ERR_IDTYPE; 154*4520Snw141292 continue; 155*4520Snw141292 } 156*4520Snw141292 if (IDMAP_FATAL_ERROR(retcode)) { 157*4520Snw141292 result->retcode = retcode; 158*4520Snw141292 goto out; 159*4520Snw141292 } 160*4520Snw141292 } 161*4520Snw141292 162*4520Snw141292 /* Check if we are done */ 163*4520Snw141292 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE) 164*4520Snw141292 goto out; 165*4520Snw141292 166*4520Snw141292 /* Process Windows server lookups for sid2name */ 167*4520Snw141292 if (state.ad_nqueries) { 168*4520Snw141292 winrc = lookup_win_batch_sid2name(&state, &batch, 169*4520Snw141292 result); 170*4520Snw141292 if (IDMAP_FATAL_ERROR(winrc)) { 171*4520Snw141292 result->retcode = winrc; 172*4520Snw141292 goto out; 173*4520Snw141292 } 174*4520Snw141292 } else 175*4520Snw141292 winrc = IDMAP_SUCCESS; 176*4520Snw141292 177*4520Snw141292 /* Reset sid2pid 'done' flag */ 178*4520Snw141292 state.sid2pid_done = TRUE; 179*4520Snw141292 180*4520Snw141292 /* Second stage */ 181*4520Snw141292 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 182*4520Snw141292 /* Process sid to pid ONLY */ 183*4520Snw141292 if (IS_BATCH_SID(batch, i)) { 184*4520Snw141292 if (IDMAP_ERROR(winrc)) 185*4520Snw141292 result->ids.ids_val[i].retcode = winrc; 186*4520Snw141292 retcode = sid2pid_second_pass( 187*4520Snw141292 &state, 188*4520Snw141292 cache, 189*4520Snw141292 db, 190*4520Snw141292 &batch.idmap_mapping_batch_val[i], 191*4520Snw141292 &result->ids.ids_val[i]); 192*4520Snw141292 if (IDMAP_FATAL_ERROR(retcode)) { 193*4520Snw141292 result->retcode = retcode; 194*4520Snw141292 goto out; 195*4520Snw141292 } 196*4520Snw141292 } 197*4520Snw141292 } 198*4520Snw141292 199*4520Snw141292 /* Check if we are done */ 200*4520Snw141292 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE) 201*4520Snw141292 goto out; 202*4520Snw141292 203*4520Snw141292 /* Reset our 'done' flags */ 204*4520Snw141292 state.sid2pid_done = state.pid2sid_done = TRUE; 205*4520Snw141292 206*4520Snw141292 /* Update cache in a single transaction */ 207*4520Snw141292 if (sql_exec_no_cb(cache, "BEGIN TRANSACTION;") != IDMAP_SUCCESS) 208*4520Snw141292 goto out; 209*4520Snw141292 210*4520Snw141292 for (i = 0; i < batch.idmap_mapping_batch_len; i++) { 211*4520Snw141292 if (IS_BATCH_SID(batch, i)) { 212*4520Snw141292 (void) update_cache_sid2pid( 213*4520Snw141292 &state, 214*4520Snw141292 cache, 215*4520Snw141292 &batch.idmap_mapping_batch_val[i], 216*4520Snw141292 &result->ids.ids_val[i]); 217*4520Snw141292 } else if ((IS_BATCH_UID(batch, i)) || 218*4520Snw141292 (IS_BATCH_GID(batch, i))) { 219*4520Snw141292 (void) update_cache_pid2sid( 220*4520Snw141292 &state, 221*4520Snw141292 cache, 222*4520Snw141292 &batch.idmap_mapping_batch_val[i], 223*4520Snw141292 &result->ids.ids_val[i]); 224*4520Snw141292 } 225*4520Snw141292 } 226*4520Snw141292 227*4520Snw141292 /* Commit if we have atleast one successful update */ 228*4520Snw141292 if (state.sid2pid_done == FALSE || state.pid2sid_done == FALSE) 229*4520Snw141292 (void) sql_exec_no_cb(cache, "COMMIT TRANSACTION;"); 230*4520Snw141292 else 231*4520Snw141292 (void) sql_exec_no_cb(cache, "END TRANSACTION;"); 232*4520Snw141292 233*4520Snw141292 out: 234*4520Snw141292 if (IDMAP_ERROR(result->retcode)) { 235*4520Snw141292 xdr_free(xdr_idmap_ids_res, (caddr_t)result); 236*4520Snw141292 result->ids.ids_len = 0; 237*4520Snw141292 result->ids.ids_val = NULL; 238*4520Snw141292 } 239*4520Snw141292 if (cache) 240*4520Snw141292 (void) sqlite_close(cache); 241*4520Snw141292 if (db) 242*4520Snw141292 (void) sqlite_close(db); 243*4520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 244*4520Snw141292 return (TRUE); 245*4520Snw141292 } 246*4520Snw141292 247*4520Snw141292 248*4520Snw141292 /* ARGSUSED */ 249*4520Snw141292 static int 250*4520Snw141292 list_mappings_cb(void *parg, int argc, char **argv, char **colnames) { 251*4520Snw141292 list_cb_data_t *cb_data; 252*4520Snw141292 char *str; 253*4520Snw141292 idmap_mappings_res *result; 254*4520Snw141292 idmap_utf8str *ptr; 255*4520Snw141292 idmap_retcode retcode; 256*4520Snw141292 int w2u, u2w; 257*4520Snw141292 char *end; 258*4520Snw141292 259*4520Snw141292 cb_data = (list_cb_data_t *)parg; 260*4520Snw141292 result = (idmap_mappings_res *)cb_data->result; 261*4520Snw141292 262*4520Snw141292 _VALIDATE_LIST_CB_DATA(9, &result->mappings.mappings_val, 263*4520Snw141292 sizeof (idmap_mapping)); 264*4520Snw141292 265*4520Snw141292 result->mappings.mappings_len++; 266*4520Snw141292 267*4520Snw141292 if ((str = strdup(argv[1])) == NULL) 268*4520Snw141292 return (1); 269*4520Snw141292 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.prefix = 270*4520Snw141292 str; 271*4520Snw141292 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.rid = 272*4520Snw141292 strtoul(argv[2], &end, 10); 273*4520Snw141292 result->mappings.mappings_val[cb_data->next].id1.idtype = IDMAP_SID; 274*4520Snw141292 275*4520Snw141292 result->mappings.mappings_val[cb_data->next].id2.idmap_id_u.uid = 276*4520Snw141292 strtoul(argv[3], &end, 10); 277*4520Snw141292 result->mappings.mappings_val[cb_data->next].id2.idtype = IDMAP_UID; 278*4520Snw141292 279*4520Snw141292 w2u = argv[4]?strtol(argv[4], &end, 10):0; 280*4520Snw141292 u2w = argv[5]?strtol(argv[5], &end, 10):0; 281*4520Snw141292 282*4520Snw141292 if (w2u > 0 && u2w == 0) 283*4520Snw141292 result->mappings.mappings_val[cb_data->next].direction = 1; 284*4520Snw141292 else if (w2u == 0 && u2w > 0) 285*4520Snw141292 result->mappings.mappings_val[cb_data->next].direction = 2; 286*4520Snw141292 else 287*4520Snw141292 result->mappings.mappings_val[cb_data->next].direction = 0; 288*4520Snw141292 289*4520Snw141292 ptr = &result->mappings.mappings_val[cb_data->next].id1domain; 290*4520Snw141292 if (idmap_str2utf8(&ptr, argv[6], 0) != IDMAP_SUCCESS) 291*4520Snw141292 return (1); 292*4520Snw141292 293*4520Snw141292 ptr = &result->mappings.mappings_val[cb_data->next].id1name; 294*4520Snw141292 if (idmap_str2utf8(&ptr, argv[7], 0) != IDMAP_SUCCESS) 295*4520Snw141292 return (1); 296*4520Snw141292 297*4520Snw141292 ptr = &result->mappings.mappings_val[cb_data->next].id2name; 298*4520Snw141292 if (idmap_str2utf8(&ptr, argv[8], 0) != IDMAP_SUCCESS) 299*4520Snw141292 return (1); 300*4520Snw141292 301*4520Snw141292 result->lastrowid = strtoll(argv[0], &end, 10); 302*4520Snw141292 cb_data->next++; 303*4520Snw141292 result->retcode = IDMAP_SUCCESS; 304*4520Snw141292 return (0); 305*4520Snw141292 } 306*4520Snw141292 307*4520Snw141292 308*4520Snw141292 /* ARGSUSED */ 309*4520Snw141292 bool_t 310*4520Snw141292 idmap_list_mappings_1_svc(bool_t is_user, int64_t lastrowid, 311*4520Snw141292 uint64_t limit, idmap_mappings_res *result, 312*4520Snw141292 struct svc_req *rqstp) { 313*4520Snw141292 sqlite *cache = NULL; 314*4520Snw141292 char lbuf[30], rbuf[30]; 315*4520Snw141292 uint64_t maxlimit; 316*4520Snw141292 idmap_retcode retcode; 317*4520Snw141292 char *sql = NULL; 318*4520Snw141292 319*4520Snw141292 (void) memset(result, 0, sizeof (*result)); 320*4520Snw141292 lbuf[0] = rbuf[0] = 0; 321*4520Snw141292 322*4520Snw141292 RDLOCK_CONFIG(); 323*4520Snw141292 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; 324*4520Snw141292 UNLOCK_CONFIG(); 325*4520Snw141292 326*4520Snw141292 /* Get cache handle */ 327*4520Snw141292 result->retcode = get_cache_handle(&cache); 328*4520Snw141292 if (result->retcode != IDMAP_SUCCESS) 329*4520Snw141292 goto out; 330*4520Snw141292 331*4520Snw141292 result->retcode = IDMAP_ERR_INTERNAL; 332*4520Snw141292 333*4520Snw141292 /* Create LIMIT expression. */ 334*4520Snw141292 if (limit == 0 || (maxlimit > 0 && maxlimit < limit)) 335*4520Snw141292 limit = maxlimit; 336*4520Snw141292 if (limit > 0) 337*4520Snw141292 (void) snprintf(lbuf, sizeof (lbuf), 338*4520Snw141292 "LIMIT %" PRIu64, limit + 1ULL); 339*4520Snw141292 340*4520Snw141292 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid); 341*4520Snw141292 342*4520Snw141292 /* 343*4520Snw141292 * Combine all the above into a giant SELECT statement that 344*4520Snw141292 * will return the requested mappings 345*4520Snw141292 */ 346*4520Snw141292 sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, u2w," 347*4520Snw141292 " windomain, winname, unixname" 348*4520Snw141292 " FROM idmap_cache WHERE " 349*4520Snw141292 " %s AND is_user = %d %s;", 350*4520Snw141292 rbuf, is_user?1:0, lbuf); 351*4520Snw141292 if (sql == NULL) { 352*4520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 353*4520Snw141292 goto out; 354*4520Snw141292 } 355*4520Snw141292 356*4520Snw141292 /* Execute the SQL statement and update the return buffer */ 357*4520Snw141292 PROCESS_LIST_SVC_SQL(retcode, cache, sql, limit, list_mappings_cb, 358*4520Snw141292 result, result->mappings.mappings_len); 359*4520Snw141292 360*4520Snw141292 out: 361*4520Snw141292 if (sql) 362*4520Snw141292 sqlite_freemem(sql); 363*4520Snw141292 if (IDMAP_ERROR(result->retcode)) 364*4520Snw141292 (void) xdr_free(xdr_idmap_mappings_res, (caddr_t)result); 365*4520Snw141292 if (cache) 366*4520Snw141292 (void) sqlite_close(cache); 367*4520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 368*4520Snw141292 return (TRUE); 369*4520Snw141292 } 370*4520Snw141292 371*4520Snw141292 372*4520Snw141292 /* ARGSUSED */ 373*4520Snw141292 static int 374*4520Snw141292 list_namerules_cb(void *parg, int argc, char **argv, char **colnames) { 375*4520Snw141292 list_cb_data_t *cb_data; 376*4520Snw141292 idmap_namerules_res *result; 377*4520Snw141292 idmap_retcode retcode; 378*4520Snw141292 idmap_utf8str *ptr; 379*4520Snw141292 int w2u_order, u2w_order; 380*4520Snw141292 char *end; 381*4520Snw141292 382*4520Snw141292 cb_data = (list_cb_data_t *)parg; 383*4520Snw141292 result = (idmap_namerules_res *)cb_data->result; 384*4520Snw141292 385*4520Snw141292 _VALIDATE_LIST_CB_DATA(8, &result->rules.rules_val, 386*4520Snw141292 sizeof (idmap_namerule)); 387*4520Snw141292 388*4520Snw141292 result->rules.rules_len++; 389*4520Snw141292 390*4520Snw141292 result->rules.rules_val[cb_data->next].is_user = 391*4520Snw141292 strtol(argv[1], &end, 10); 392*4520Snw141292 393*4520Snw141292 ptr = &result->rules.rules_val[cb_data->next].windomain; 394*4520Snw141292 if (idmap_str2utf8(&ptr, argv[2], 0) != IDMAP_SUCCESS) 395*4520Snw141292 return (1); 396*4520Snw141292 397*4520Snw141292 ptr = &result->rules.rules_val[cb_data->next].winname; 398*4520Snw141292 if (idmap_str2utf8(&ptr, argv[3], 0) != IDMAP_SUCCESS) 399*4520Snw141292 return (1); 400*4520Snw141292 401*4520Snw141292 result->rules.rules_val[cb_data->next].is_nt4 = 402*4520Snw141292 strtol(argv[4], &end, 10); 403*4520Snw141292 404*4520Snw141292 ptr = &result->rules.rules_val[cb_data->next].unixname; 405*4520Snw141292 if (idmap_str2utf8(&ptr, argv[5], 0) != IDMAP_SUCCESS) 406*4520Snw141292 return (1); 407*4520Snw141292 408*4520Snw141292 w2u_order = argv[6]?strtol(argv[6], &end, 10):0; 409*4520Snw141292 u2w_order = argv[7]?strtol(argv[7], &end, 10):0; 410*4520Snw141292 411*4520Snw141292 if (w2u_order > 0 && u2w_order == 0) 412*4520Snw141292 result->rules.rules_val[cb_data->next].direction = 1; 413*4520Snw141292 else if (w2u_order == 0 && u2w_order > 0) 414*4520Snw141292 result->rules.rules_val[cb_data->next].direction = 2; 415*4520Snw141292 else 416*4520Snw141292 result->rules.rules_val[cb_data->next].direction = 0; 417*4520Snw141292 418*4520Snw141292 result->lastrowid = strtoll(argv[0], &end, 10); 419*4520Snw141292 cb_data->next++; 420*4520Snw141292 result->retcode = IDMAP_SUCCESS; 421*4520Snw141292 return (0); 422*4520Snw141292 } 423*4520Snw141292 424*4520Snw141292 425*4520Snw141292 /* ARGSUSED */ 426*4520Snw141292 bool_t 427*4520Snw141292 idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid, 428*4520Snw141292 uint64_t limit, idmap_namerules_res *result, 429*4520Snw141292 struct svc_req *rqstp) { 430*4520Snw141292 431*4520Snw141292 sqlite *db = NULL; 432*4520Snw141292 char w2ubuf[15], u2wbuf[15]; 433*4520Snw141292 char lbuf[30], rbuf[30]; 434*4520Snw141292 char *sql = NULL; 435*4520Snw141292 char *s_windomain = NULL, *s_winname = NULL; 436*4520Snw141292 char *s_unixname = NULL; 437*4520Snw141292 uint64_t maxlimit; 438*4520Snw141292 idmap_retcode retcode; 439*4520Snw141292 440*4520Snw141292 (void) memset(result, 0, sizeof (*result)); 441*4520Snw141292 lbuf[0] = rbuf[0] = 0; 442*4520Snw141292 443*4520Snw141292 RDLOCK_CONFIG(); 444*4520Snw141292 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; 445*4520Snw141292 UNLOCK_CONFIG(); 446*4520Snw141292 447*4520Snw141292 /* Get db handle */ 448*4520Snw141292 result->retcode = get_db_handle(&db); 449*4520Snw141292 if (result->retcode != IDMAP_SUCCESS) 450*4520Snw141292 goto out; 451*4520Snw141292 452*4520Snw141292 result->retcode = IDMAP_ERR_INTERNAL; 453*4520Snw141292 454*4520Snw141292 if (rule.direction < 0) { 455*4520Snw141292 w2ubuf[0] = u2wbuf[0] = 0; 456*4520Snw141292 } else if (rule.direction == 0) { 457*4520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0"); 458*4520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0"); 459*4520Snw141292 } else if (rule.direction == 1) { 460*4520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0"); 461*4520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), 462*4520Snw141292 "AND (u2w_order = 0 OR u2w_order ISNULL)"); 463*4520Snw141292 } else if (rule.direction == 2) { 464*4520Snw141292 (void) snprintf(w2ubuf, sizeof (w2ubuf), 465*4520Snw141292 "AND (w2u_order = 0 OR w2u_order ISNULL)"); 466*4520Snw141292 (void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0"); 467*4520Snw141292 } 468*4520Snw141292 469*4520Snw141292 /* Create where statement for windomain */ 470*4520Snw141292 if (rule.windomain.idmap_utf8str_len > 0) { 471*4520Snw141292 if (gen_sql_expr_from_utf8str("AND", "windomain", "=", 472*4520Snw141292 &rule.windomain, 473*4520Snw141292 "", &s_windomain) != IDMAP_SUCCESS) 474*4520Snw141292 goto out; 475*4520Snw141292 } 476*4520Snw141292 477*4520Snw141292 /* Create where statement for winname */ 478*4520Snw141292 if (rule.winname.idmap_utf8str_len > 0) { 479*4520Snw141292 if (gen_sql_expr_from_utf8str("AND", "winname", "=", 480*4520Snw141292 &rule.winname, 481*4520Snw141292 "", &s_winname) != IDMAP_SUCCESS) 482*4520Snw141292 goto out; 483*4520Snw141292 } 484*4520Snw141292 485*4520Snw141292 /* Create where statement for unixname */ 486*4520Snw141292 if (rule.unixname.idmap_utf8str_len > 0) { 487*4520Snw141292 if (gen_sql_expr_from_utf8str("AND", "unixname", "=", 488*4520Snw141292 &rule.unixname, 489*4520Snw141292 "", &s_unixname) != IDMAP_SUCCESS) 490*4520Snw141292 goto out; 491*4520Snw141292 } 492*4520Snw141292 493*4520Snw141292 /* Create LIMIT expression. */ 494*4520Snw141292 if (limit == 0 || (maxlimit > 0 && maxlimit < limit)) 495*4520Snw141292 limit = maxlimit; 496*4520Snw141292 if (limit > 0) 497*4520Snw141292 (void) snprintf(lbuf, sizeof (lbuf), 498*4520Snw141292 "LIMIT %" PRIu64, limit + 1ULL); 499*4520Snw141292 500*4520Snw141292 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid); 501*4520Snw141292 502*4520Snw141292 /* 503*4520Snw141292 * Combine all the above into a giant SELECT statement that 504*4520Snw141292 * will return the requested rules 505*4520Snw141292 */ 506*4520Snw141292 sql = sqlite_mprintf("SELECT rowid, is_user, windomain, winname, " 507*4520Snw141292 "is_nt4, unixname, w2u_order, u2w_order " 508*4520Snw141292 "FROM namerules WHERE " 509*4520Snw141292 " %s AND is_user = %d %s %s %s %s %s %s;", 510*4520Snw141292 rbuf, rule.is_user?1:0, 511*4520Snw141292 s_windomain?s_windomain:"", 512*4520Snw141292 s_winname?s_winname:"", 513*4520Snw141292 s_unixname?s_unixname:"", 514*4520Snw141292 w2ubuf, u2wbuf, lbuf); 515*4520Snw141292 if (sql == NULL) { 516*4520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 517*4520Snw141292 goto out; 518*4520Snw141292 } 519*4520Snw141292 520*4520Snw141292 /* Execute the SQL statement and update the return buffer */ 521*4520Snw141292 PROCESS_LIST_SVC_SQL(retcode, db, sql, limit, list_namerules_cb, 522*4520Snw141292 result, result->rules.rules_len); 523*4520Snw141292 524*4520Snw141292 out: 525*4520Snw141292 if (s_windomain) 526*4520Snw141292 sqlite_freemem(s_windomain); 527*4520Snw141292 if (s_winname) 528*4520Snw141292 sqlite_freemem(s_winname); 529*4520Snw141292 if (s_unixname) 530*4520Snw141292 sqlite_freemem(s_unixname); 531*4520Snw141292 if (sql) 532*4520Snw141292 sqlite_freemem(sql); 533*4520Snw141292 if (IDMAP_ERROR(result->retcode)) 534*4520Snw141292 (void) xdr_free(xdr_idmap_namerules_res, (caddr_t)result); 535*4520Snw141292 if (db) 536*4520Snw141292 (void) sqlite_close(db); 537*4520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 538*4520Snw141292 return (TRUE); 539*4520Snw141292 } 540*4520Snw141292 541*4520Snw141292 #define IDMAP_RULES_AUTH "solaris.admin.idmap.rules" 542*4520Snw141292 static int 543*4520Snw141292 verify_rules_auth(struct svc_req *rqstp) { 544*4520Snw141292 ucred_t *uc = NULL; 545*4520Snw141292 uid_t uid; 546*4520Snw141292 char buf[1024]; 547*4520Snw141292 struct passwd pwd; 548*4520Snw141292 const char *me = "verify_rules_auth"; 549*4520Snw141292 550*4520Snw141292 if (svc_getcallerucred(rqstp->rq_xprt, &uc) != 0) { 551*4520Snw141292 idmapdlog(LOG_ERR, 552*4520Snw141292 "%s: svc_getcallerucred failed (errno=%d)", 553*4520Snw141292 me, errno); 554*4520Snw141292 return (-1); 555*4520Snw141292 } 556*4520Snw141292 557*4520Snw141292 uid = ucred_geteuid(uc); 558*4520Snw141292 if (uid == (uid_t)-1) { 559*4520Snw141292 idmapdlog(LOG_ERR, 560*4520Snw141292 "%s: ucred_geteuid failed (errno=%d)", 561*4520Snw141292 me, errno); 562*4520Snw141292 ucred_free(uc); 563*4520Snw141292 return (-1); 564*4520Snw141292 } 565*4520Snw141292 566*4520Snw141292 if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) { 567*4520Snw141292 idmapdlog(LOG_ERR, 568*4520Snw141292 "%s: getpwuid_r(%u) failed (errno=%d)", 569*4520Snw141292 me, uid, errno); 570*4520Snw141292 ucred_free(uc); 571*4520Snw141292 return (-1); 572*4520Snw141292 } 573*4520Snw141292 574*4520Snw141292 if (chkauthattr(IDMAP_RULES_AUTH, pwd.pw_name) != 1) { 575*4520Snw141292 idmapdlog(LOG_INFO, 576*4520Snw141292 "%s: %s does not have authorization.", 577*4520Snw141292 me, pwd.pw_name); 578*4520Snw141292 ucred_free(uc); 579*4520Snw141292 return (-1); 580*4520Snw141292 } 581*4520Snw141292 582*4520Snw141292 ucred_free(uc); 583*4520Snw141292 return (1); 584*4520Snw141292 } 585*4520Snw141292 586*4520Snw141292 /* ARGSUSED */ 587*4520Snw141292 bool_t 588*4520Snw141292 idmap_update_1_svc(idmap_update_batch batch, idmap_retcode *result, 589*4520Snw141292 struct svc_req *rqstp) { 590*4520Snw141292 sqlite *db = NULL; 591*4520Snw141292 idmap_update_op *up; 592*4520Snw141292 int i; 593*4520Snw141292 594*4520Snw141292 if (verify_rules_auth(rqstp) < 0) { 595*4520Snw141292 *result = IDMAP_ERR_PERMISSION_DENIED; 596*4520Snw141292 goto out; 597*4520Snw141292 } 598*4520Snw141292 599*4520Snw141292 if (batch.idmap_update_batch_len == 0 || 600*4520Snw141292 batch.idmap_update_batch_val == NULL) { 601*4520Snw141292 *result = IDMAP_SUCCESS; 602*4520Snw141292 goto out; 603*4520Snw141292 } 604*4520Snw141292 605*4520Snw141292 /* Get db handle */ 606*4520Snw141292 *result = get_db_handle(&db); 607*4520Snw141292 if (*result != IDMAP_SUCCESS) 608*4520Snw141292 goto out; 609*4520Snw141292 610*4520Snw141292 *result = sql_exec_no_cb(db, "BEGIN TRANSACTION;"); 611*4520Snw141292 if (*result != IDMAP_SUCCESS) 612*4520Snw141292 goto out; 613*4520Snw141292 614*4520Snw141292 for (i = 0; i < batch.idmap_update_batch_len; i++) { 615*4520Snw141292 up = &batch.idmap_update_batch_val[i]; 616*4520Snw141292 switch (up->opnum) { 617*4520Snw141292 case OP_NONE: 618*4520Snw141292 *result = IDMAP_SUCCESS; 619*4520Snw141292 break; 620*4520Snw141292 case OP_ADD_NAMERULE: 621*4520Snw141292 *result = add_namerule(db, 622*4520Snw141292 &up->idmap_update_op_u.rule); 623*4520Snw141292 break; 624*4520Snw141292 case OP_RM_NAMERULE: 625*4520Snw141292 *result = rm_namerule(db, 626*4520Snw141292 &up->idmap_update_op_u.rule); 627*4520Snw141292 break; 628*4520Snw141292 case OP_FLUSH_NAMERULES: 629*4520Snw141292 *result = flush_namerules(db, 630*4520Snw141292 up->idmap_update_op_u.is_user); 631*4520Snw141292 break; 632*4520Snw141292 default: 633*4520Snw141292 *result = IDMAP_ERR_NOTSUPPORTED; 634*4520Snw141292 goto out; 635*4520Snw141292 }; 636*4520Snw141292 637*4520Snw141292 if (*result != IDMAP_SUCCESS) 638*4520Snw141292 goto out; 639*4520Snw141292 } 640*4520Snw141292 641*4520Snw141292 out: 642*4520Snw141292 if (*result == IDMAP_SUCCESS && db) { 643*4520Snw141292 *result = sql_exec_no_cb(db, "COMMIT TRANSACTION;"); 644*4520Snw141292 } 645*4520Snw141292 646*4520Snw141292 if (db) 647*4520Snw141292 (void) sqlite_close(db); 648*4520Snw141292 *result = idmap_stat4prot(*result); 649*4520Snw141292 return (TRUE); 650*4520Snw141292 } 651*4520Snw141292 652*4520Snw141292 653*4520Snw141292 /* ARGSUSED */ 654*4520Snw141292 bool_t 655*4520Snw141292 idmap_get_mapped_id_by_name_1_svc(idmap_mapping request, 656*4520Snw141292 idmap_mappings_res *result, struct svc_req *rqstp) { 657*4520Snw141292 sqlite *cache = NULL, *db = NULL; 658*4520Snw141292 659*4520Snw141292 /* Init */ 660*4520Snw141292 (void) memset(result, 0, sizeof (*result)); 661*4520Snw141292 662*4520Snw141292 /* Get cache handle */ 663*4520Snw141292 result->retcode = get_cache_handle(&cache); 664*4520Snw141292 if (result->retcode != IDMAP_SUCCESS) 665*4520Snw141292 goto out; 666*4520Snw141292 667*4520Snw141292 /* Get db handle */ 668*4520Snw141292 result->retcode = get_db_handle(&db); 669*4520Snw141292 if (result->retcode != IDMAP_SUCCESS) 670*4520Snw141292 goto out; 671*4520Snw141292 672*4520Snw141292 /* Allocate result */ 673*4520Snw141292 result->mappings.mappings_val = calloc(1, sizeof (idmap_mapping)); 674*4520Snw141292 if (result->mappings.mappings_val == NULL) { 675*4520Snw141292 idmapdlog(LOG_ERR, "Out of memory"); 676*4520Snw141292 result->retcode = IDMAP_ERR_MEMORY; 677*4520Snw141292 goto out; 678*4520Snw141292 } 679*4520Snw141292 result->mappings.mappings_len = 1; 680*4520Snw141292 681*4520Snw141292 if (IS_REQUEST_SID(request)) { 682*4520Snw141292 result->retcode = get_w2u_mapping( 683*4520Snw141292 cache, 684*4520Snw141292 db, 685*4520Snw141292 &request, 686*4520Snw141292 result->mappings.mappings_val); 687*4520Snw141292 } else if (IS_REQUEST_UID(request)) { 688*4520Snw141292 result->retcode = get_u2w_mapping( 689*4520Snw141292 cache, 690*4520Snw141292 db, 691*4520Snw141292 &request, 692*4520Snw141292 result->mappings.mappings_val, 693*4520Snw141292 1); 694*4520Snw141292 } else if (IS_REQUEST_GID(request)) { 695*4520Snw141292 result->retcode = get_u2w_mapping( 696*4520Snw141292 cache, 697*4520Snw141292 db, 698*4520Snw141292 &request, 699*4520Snw141292 result->mappings.mappings_val, 700*4520Snw141292 0); 701*4520Snw141292 } else { 702*4520Snw141292 result->retcode = IDMAP_ERR_IDTYPE; 703*4520Snw141292 } 704*4520Snw141292 705*4520Snw141292 out: 706*4520Snw141292 if (IDMAP_FATAL_ERROR(result->retcode)) { 707*4520Snw141292 xdr_free(xdr_idmap_mappings_res, (caddr_t)result); 708*4520Snw141292 result->mappings.mappings_len = 0; 709*4520Snw141292 result->mappings.mappings_val = NULL; 710*4520Snw141292 } 711*4520Snw141292 if (cache) 712*4520Snw141292 (void) sqlite_close(cache); 713*4520Snw141292 if (db) 714*4520Snw141292 (void) sqlite_close(db); 715*4520Snw141292 result->retcode = idmap_stat4prot(result->retcode); 716*4520Snw141292 return (TRUE); 717*4520Snw141292 } 718*4520Snw141292 719*4520Snw141292 720*4520Snw141292 /* ARGSUSED */ 721*4520Snw141292 int 722*4520Snw141292 idmap_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, 723*4520Snw141292 caddr_t result) { 724*4520Snw141292 (void) xdr_free(xdr_result, result); 725*4520Snw141292 return (TRUE); 726*4520Snw141292 } 727