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