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