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