xref: /illumos-gate/usr/src/cmd/idmap/idmapd/server.c (revision c5c4113d)
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