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