xref: /illumos-gate/usr/src/cmd/idmap/idmapd/server.c (revision 651c0131ccc65381cbda174bee44a4fd7a518d6b)
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 	int		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 	/* Init our 'done' flags */
128 	state.sid2pid_done = state.pid2sid_done = TRUE;
129 
130 	/* First stage */
131 	for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
132 		if (IS_BATCH_SID(batch, i)) {
133 			retcode = sid2pid_first_pass(
134 				&state,
135 				cache,
136 				&batch.idmap_mapping_batch_val[i],
137 				&result->ids.ids_val[i]);
138 		} else if (IS_BATCH_UID(batch, i)) {
139 			retcode = pid2sid_first_pass(
140 				&state,
141 				cache,
142 				db,
143 				&batch.idmap_mapping_batch_val[i],
144 				&result->ids.ids_val[i], 1, 0);
145 		} else if (IS_BATCH_GID(batch, i)) {
146 			retcode = pid2sid_first_pass(
147 				&state,
148 				cache,
149 				db,
150 				&batch.idmap_mapping_batch_val[i],
151 				&result->ids.ids_val[i], 0, 0);
152 		} else {
153 			result->ids.ids_val[i].retcode = IDMAP_ERR_IDTYPE;
154 			continue;
155 		}
156 		if (IDMAP_FATAL_ERROR(retcode)) {
157 			result->retcode = retcode;
158 			goto out;
159 		}
160 	}
161 
162 	/* Check if we are done */
163 	if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE)
164 		goto out;
165 
166 	/* Process Windows server lookups for sid2name */
167 	if (state.ad_nqueries) {
168 		winrc = lookup_win_batch_sid2name(&state, &batch,
169 				result);
170 		if (IDMAP_FATAL_ERROR(winrc)) {
171 			result->retcode = winrc;
172 			goto out;
173 		}
174 	} else
175 		winrc = IDMAP_SUCCESS;
176 
177 	/* Reset sid2pid 'done' flag */
178 	state.sid2pid_done = TRUE;
179 
180 	/* Second stage */
181 	for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
182 		/* Process sid to pid ONLY */
183 		if (IS_BATCH_SID(batch, i)) {
184 			if (IDMAP_ERROR(winrc))
185 				result->ids.ids_val[i].retcode = winrc;
186 			retcode = sid2pid_second_pass(
187 				&state,
188 				cache,
189 				db,
190 				&batch.idmap_mapping_batch_val[i],
191 				&result->ids.ids_val[i]);
192 			if (IDMAP_FATAL_ERROR(retcode)) {
193 				result->retcode = retcode;
194 				goto out;
195 			}
196 		}
197 	}
198 
199 	/* Check if we are done */
200 	if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE)
201 		goto out;
202 
203 	/* Reset our 'done' flags */
204 	state.sid2pid_done = state.pid2sid_done = TRUE;
205 
206 	/* Update cache in a single transaction */
207 	if (sql_exec_no_cb(cache, "BEGIN TRANSACTION;") != IDMAP_SUCCESS)
208 		goto out;
209 
210 	for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
211 		if (IS_BATCH_SID(batch, i)) {
212 			(void) update_cache_sid2pid(
213 				&state,
214 				cache,
215 				&batch.idmap_mapping_batch_val[i],
216 				&result->ids.ids_val[i]);
217 		} else if ((IS_BATCH_UID(batch, i)) ||
218 				(IS_BATCH_GID(batch, i))) {
219 			(void) update_cache_pid2sid(
220 				&state,
221 				cache,
222 				&batch.idmap_mapping_batch_val[i],
223 				&result->ids.ids_val[i]);
224 		}
225 	}
226 
227 	/* Commit if we have atleast one successful update */
228 	if (state.sid2pid_done == FALSE || state.pid2sid_done == FALSE)
229 		(void) sql_exec_no_cb(cache, "COMMIT TRANSACTION;");
230 	else
231 		(void) sql_exec_no_cb(cache, "END TRANSACTION;");
232 
233 out:
234 	if (IDMAP_ERROR(result->retcode)) {
235 		xdr_free(xdr_idmap_ids_res, (caddr_t)result);
236 		result->ids.ids_len = 0;
237 		result->ids.ids_val = NULL;
238 	}
239 	if (cache)
240 		(void) sqlite_close(cache);
241 	if (db)
242 		(void) sqlite_close(db);
243 	result->retcode = idmap_stat4prot(result->retcode);
244 	return (TRUE);
245 }
246 
247 
248 /* ARGSUSED */
249 static int
250 list_mappings_cb(void *parg, int argc, char **argv, char **colnames) {
251 	list_cb_data_t		*cb_data;
252 	char			*str;
253 	idmap_mappings_res	*result;
254 	idmap_utf8str		*ptr;
255 	idmap_retcode		retcode;
256 	int			w2u, u2w;
257 	char			*end;
258 
259 	cb_data = (list_cb_data_t *)parg;
260 	result = (idmap_mappings_res *)cb_data->result;
261 
262 	_VALIDATE_LIST_CB_DATA(9, &result->mappings.mappings_val,
263 		sizeof (idmap_mapping));
264 
265 	result->mappings.mappings_len++;
266 
267 	if ((str = strdup(argv[1])) == NULL)
268 		return (1);
269 	result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.prefix =
270 		str;
271 	result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.rid =
272 		strtoul(argv[2], &end, 10);
273 	result->mappings.mappings_val[cb_data->next].id1.idtype = IDMAP_SID;
274 
275 	result->mappings.mappings_val[cb_data->next].id2.idmap_id_u.uid =
276 		strtoul(argv[3], &end, 10);
277 	result->mappings.mappings_val[cb_data->next].id2.idtype = IDMAP_UID;
278 
279 	w2u = argv[4]?strtol(argv[4], &end, 10):0;
280 	u2w = argv[5]?strtol(argv[5], &end, 10):0;
281 
282 	if (w2u > 0 && u2w == 0)
283 		result->mappings.mappings_val[cb_data->next].direction =
284 		    IDMAP_DIRECTION_W2U;
285 	else if (w2u == 0 && u2w > 0)
286 		result->mappings.mappings_val[cb_data->next].direction =
287 		    IDMAP_DIRECTION_U2W;
288 	else
289 		result->mappings.mappings_val[cb_data->next].direction =
290 		    IDMAP_DIRECTION_BI;
291 
292 	ptr = &result->mappings.mappings_val[cb_data->next].id1domain;
293 	if (idmap_str2utf8(&ptr, argv[6], 0) != IDMAP_SUCCESS)
294 		return (1);
295 
296 	ptr = &result->mappings.mappings_val[cb_data->next].id1name;
297 	if (idmap_str2utf8(&ptr, argv[7], 0) != IDMAP_SUCCESS)
298 		return (1);
299 
300 	ptr = &result->mappings.mappings_val[cb_data->next].id2name;
301 	if (idmap_str2utf8(&ptr, argv[8], 0) != IDMAP_SUCCESS)
302 		return (1);
303 
304 	result->lastrowid = strtoll(argv[0], &end, 10);
305 	cb_data->next++;
306 	result->retcode = IDMAP_SUCCESS;
307 	return (0);
308 }
309 
310 
311 /* ARGSUSED */
312 bool_t
313 idmap_list_mappings_1_svc(bool_t is_user, int64_t lastrowid,
314 		uint64_t limit, idmap_mappings_res *result,
315 		struct svc_req *rqstp) {
316 	sqlite		*cache = NULL;
317 	char		lbuf[30], rbuf[30];
318 	uint64_t	maxlimit;
319 	idmap_retcode	retcode;
320 	char		*sql = NULL;
321 
322 	(void) memset(result, 0, sizeof (*result));
323 	lbuf[0] = rbuf[0] = 0;
324 
325 	RDLOCK_CONFIG();
326 	maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit;
327 	UNLOCK_CONFIG();
328 
329 	/* Get cache handle */
330 	result->retcode = get_cache_handle(&cache);
331 	if (result->retcode != IDMAP_SUCCESS)
332 		goto out;
333 
334 	result->retcode = IDMAP_ERR_INTERNAL;
335 
336 	/* Create LIMIT expression. */
337 	if (limit == 0 || (maxlimit > 0 && maxlimit < limit))
338 		limit = maxlimit;
339 	if (limit > 0)
340 		(void) snprintf(lbuf, sizeof (lbuf),
341 			"LIMIT %" PRIu64, limit + 1ULL);
342 
343 	(void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid);
344 
345 	/*
346 	 * Combine all the above into a giant SELECT statement that
347 	 * will return the requested mappings
348 	 */
349 	sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, u2w,"
350 			" windomain, winname, unixname"
351 			" FROM idmap_cache WHERE "
352 			" %s AND is_user = %d %s;",
353 			rbuf, is_user?1:0, lbuf);
354 	if (sql == NULL) {
355 		idmapdlog(LOG_ERR, "Out of memory");
356 		goto out;
357 	}
358 
359 	/* Execute the SQL statement and update the return buffer */
360 	PROCESS_LIST_SVC_SQL(retcode, cache, sql, limit, list_mappings_cb,
361 		result, result->mappings.mappings_len);
362 
363 out:
364 	if (sql)
365 		sqlite_freemem(sql);
366 	if (IDMAP_ERROR(result->retcode))
367 		(void) xdr_free(xdr_idmap_mappings_res, (caddr_t)result);
368 	if (cache)
369 		(void) sqlite_close(cache);
370 	result->retcode = idmap_stat4prot(result->retcode);
371 	return (TRUE);
372 }
373 
374 
375 /* ARGSUSED */
376 static int
377 list_namerules_cb(void *parg, int argc, char **argv, char **colnames) {
378 	list_cb_data_t		*cb_data;
379 	idmap_namerules_res	*result;
380 	idmap_retcode		retcode;
381 	idmap_utf8str		*ptr;
382 	int			w2u_order, u2w_order;
383 	char			*end;
384 
385 	cb_data = (list_cb_data_t *)parg;
386 	result = (idmap_namerules_res *)cb_data->result;
387 
388 	_VALIDATE_LIST_CB_DATA(8, &result->rules.rules_val,
389 		sizeof (idmap_namerule));
390 
391 	result->rules.rules_len++;
392 
393 	result->rules.rules_val[cb_data->next].is_user =
394 		strtol(argv[1], &end, 10);
395 
396 	ptr = &result->rules.rules_val[cb_data->next].windomain;
397 	if (idmap_str2utf8(&ptr, argv[2], 0) != IDMAP_SUCCESS)
398 		return (1);
399 
400 	ptr = &result->rules.rules_val[cb_data->next].winname;
401 	if (idmap_str2utf8(&ptr, argv[3], 0) != IDMAP_SUCCESS)
402 		return (1);
403 
404 	result->rules.rules_val[cb_data->next].is_nt4 =
405 		strtol(argv[4], &end, 10);
406 
407 	ptr = &result->rules.rules_val[cb_data->next].unixname;
408 	if (idmap_str2utf8(&ptr, argv[5], 0) != IDMAP_SUCCESS)
409 		return (1);
410 
411 	w2u_order = argv[6]?strtol(argv[6], &end, 10):0;
412 	u2w_order = argv[7]?strtol(argv[7], &end, 10):0;
413 
414 	if (w2u_order > 0 && u2w_order == 0)
415 		result->rules.rules_val[cb_data->next].direction =
416 		    IDMAP_DIRECTION_W2U;
417 	else if (w2u_order == 0 && u2w_order > 0)
418 		result->rules.rules_val[cb_data->next].direction =
419 		    IDMAP_DIRECTION_U2W;
420 	else
421 		result->rules.rules_val[cb_data->next].direction =
422 		    IDMAP_DIRECTION_BI;
423 
424 	result->lastrowid = strtoll(argv[0], &end, 10);
425 	cb_data->next++;
426 	result->retcode = IDMAP_SUCCESS;
427 	return (0);
428 }
429 
430 
431 /* ARGSUSED */
432 bool_t
433 idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid,
434 		uint64_t limit, idmap_namerules_res *result,
435 		struct svc_req *rqstp) {
436 
437 	sqlite		*db = NULL;
438 	char		w2ubuf[15], u2wbuf[15];
439 	char		lbuf[30], rbuf[30];
440 	char		*sql = NULL;
441 	char		*s_windomain = NULL, *s_winname = NULL;
442 	char		*s_unixname = NULL;
443 	uint64_t	maxlimit;
444 	idmap_retcode	retcode;
445 
446 	(void) memset(result, 0, sizeof (*result));
447 	lbuf[0] = rbuf[0] = 0;
448 
449 	RDLOCK_CONFIG();
450 	maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit;
451 	UNLOCK_CONFIG();
452 
453 	/* Get db handle */
454 	result->retcode = get_db_handle(&db);
455 	if (result->retcode != IDMAP_SUCCESS)
456 		goto out;
457 
458 	result->retcode = IDMAP_ERR_INTERNAL;
459 
460 	if (rule.direction < 0) {
461 		w2ubuf[0] = u2wbuf[0] = 0;
462 	} else if (rule.direction == IDMAP_DIRECTION_BI) {
463 		(void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0");
464 		(void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0");
465 	} else if (rule.direction == IDMAP_DIRECTION_W2U) {
466 		(void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0");
467 		(void) snprintf(u2wbuf, sizeof (u2wbuf),
468 				"AND (u2w_order = 0 OR u2w_order ISNULL)");
469 	} else if (rule.direction == IDMAP_DIRECTION_U2W) {
470 		(void) snprintf(w2ubuf, sizeof (w2ubuf),
471 				"AND (w2u_order = 0 OR w2u_order ISNULL)");
472 		(void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0");
473 	}
474 
475 	/* Create where statement for windomain */
476 	if (rule.windomain.idmap_utf8str_len > 0) {
477 		if (gen_sql_expr_from_utf8str("AND", "windomain", "=",
478 				&rule.windomain,
479 				"", &s_windomain) != IDMAP_SUCCESS)
480 			goto out;
481 	}
482 
483 	/* Create where statement for winname */
484 	if (rule.winname.idmap_utf8str_len > 0) {
485 		if (gen_sql_expr_from_utf8str("AND", "winname", "=",
486 				&rule.winname,
487 				"", &s_winname) != IDMAP_SUCCESS)
488 			goto out;
489 	}
490 
491 	/* Create where statement for unixname */
492 	if (rule.unixname.idmap_utf8str_len > 0) {
493 		if (gen_sql_expr_from_utf8str("AND", "unixname", "=",
494 				&rule.unixname,
495 				"", &s_unixname) != IDMAP_SUCCESS)
496 			goto out;
497 	}
498 
499 	/* Create LIMIT expression. */
500 	if (limit == 0 || (maxlimit > 0 && maxlimit < limit))
501 		limit = maxlimit;
502 	if (limit > 0)
503 		(void) snprintf(lbuf, sizeof (lbuf),
504 			"LIMIT %" PRIu64, limit + 1ULL);
505 
506 	(void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid);
507 
508 	/*
509 	 * Combine all the above into a giant SELECT statement that
510 	 * will return the requested rules
511 	 */
512 	sql = sqlite_mprintf("SELECT rowid, is_user, windomain, winname, "
513 			"is_nt4, unixname, w2u_order, u2w_order "
514 			"FROM namerules WHERE "
515 			" %s AND is_user = %d %s %s %s %s %s %s;",
516 			rbuf, rule.is_user?1:0,
517 			s_windomain?s_windomain:"",
518 			s_winname?s_winname:"",
519 			s_unixname?s_unixname:"",
520 			w2ubuf, u2wbuf, lbuf);
521 	if (sql == NULL) {
522 		idmapdlog(LOG_ERR, "Out of memory");
523 		goto out;
524 	}
525 
526 	/* Execute the SQL statement and update the return buffer */
527 	PROCESS_LIST_SVC_SQL(retcode, db, sql, limit, list_namerules_cb,
528 		result, result->rules.rules_len);
529 
530 out:
531 	if (s_windomain)
532 		sqlite_freemem(s_windomain);
533 	if (s_winname)
534 		sqlite_freemem(s_winname);
535 	if (s_unixname)
536 		sqlite_freemem(s_unixname);
537 	if (sql)
538 		sqlite_freemem(sql);
539 	if (IDMAP_ERROR(result->retcode))
540 		(void) xdr_free(xdr_idmap_namerules_res, (caddr_t)result);
541 	if (db)
542 		(void) sqlite_close(db);
543 	result->retcode = idmap_stat4prot(result->retcode);
544 	return (TRUE);
545 }
546 
547 #define	IDMAP_RULES_AUTH	"solaris.admin.idmap.rules"
548 static int
549 verify_rules_auth(struct svc_req *rqstp) {
550 	ucred_t		*uc = NULL;
551 	uid_t		uid;
552 	char		buf[1024];
553 	struct passwd	pwd;
554 	const char	*me = "verify_rules_auth";
555 
556 	if (svc_getcallerucred(rqstp->rq_xprt, &uc) != 0) {
557 		idmapdlog(LOG_ERR,
558 			"%s: svc_getcallerucred failed (errno=%d)",
559 			me, errno);
560 		return (-1);
561 	}
562 
563 	uid = ucred_geteuid(uc);
564 	if (uid == (uid_t)-1) {
565 		idmapdlog(LOG_ERR,
566 			"%s: ucred_geteuid failed (errno=%d)",
567 			me, errno);
568 		ucred_free(uc);
569 		return (-1);
570 	}
571 
572 	if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) {
573 		idmapdlog(LOG_ERR,
574 			"%s: getpwuid_r(%u) failed (errno=%d)",
575 			me, uid, errno);
576 		ucred_free(uc);
577 		return (-1);
578 	}
579 
580 	if (chkauthattr(IDMAP_RULES_AUTH, pwd.pw_name) != 1) {
581 		idmapdlog(LOG_INFO,
582 			"%s: %s does not have authorization.",
583 			me, pwd.pw_name);
584 		ucred_free(uc);
585 		return (-1);
586 	}
587 
588 	ucred_free(uc);
589 	return (1);
590 }
591 
592 /* ARGSUSED */
593 bool_t
594 idmap_update_1_svc(idmap_update_batch batch, idmap_retcode *result,
595 		struct svc_req *rqstp) {
596 	sqlite		*db = NULL;
597 	idmap_update_op	*up;
598 	int		i;
599 
600 	if (verify_rules_auth(rqstp) < 0) {
601 		*result = IDMAP_ERR_PERMISSION_DENIED;
602 		goto out;
603 	}
604 
605 	if (batch.idmap_update_batch_len == 0 ||
606 			batch.idmap_update_batch_val == NULL) {
607 		*result = IDMAP_SUCCESS;
608 		goto out;
609 	}
610 
611 	/* Get db handle */
612 	*result = get_db_handle(&db);
613 	if (*result != IDMAP_SUCCESS)
614 		goto out;
615 
616 	*result = sql_exec_no_cb(db, "BEGIN TRANSACTION;");
617 	if (*result != IDMAP_SUCCESS)
618 		goto out;
619 
620 	for (i = 0; i < batch.idmap_update_batch_len; i++) {
621 		up = &batch.idmap_update_batch_val[i];
622 		switch (up->opnum) {
623 		case OP_NONE:
624 			*result = IDMAP_SUCCESS;
625 			break;
626 		case OP_ADD_NAMERULE:
627 			*result = add_namerule(db,
628 				&up->idmap_update_op_u.rule);
629 			break;
630 		case OP_RM_NAMERULE:
631 			*result = rm_namerule(db,
632 				&up->idmap_update_op_u.rule);
633 			break;
634 		case OP_FLUSH_NAMERULES:
635 			*result = flush_namerules(db,
636 				up->idmap_update_op_u.is_user);
637 			break;
638 		default:
639 			*result = IDMAP_ERR_NOTSUPPORTED;
640 			goto out;
641 		};
642 
643 		if (*result != IDMAP_SUCCESS)
644 			goto out;
645 	}
646 
647 out:
648 	if (*result == IDMAP_SUCCESS && db) {
649 		*result = sql_exec_no_cb(db, "COMMIT TRANSACTION;");
650 	}
651 
652 	if (db)
653 		(void) sqlite_close(db);
654 	*result = idmap_stat4prot(*result);
655 	return (TRUE);
656 }
657 
658 
659 /* ARGSUSED */
660 bool_t
661 idmap_get_mapped_id_by_name_1_svc(idmap_mapping request,
662 		idmap_mappings_res *result, struct svc_req *rqstp) {
663 	sqlite		*cache = NULL, *db = NULL;
664 
665 	/* Init */
666 	(void) memset(result, 0, sizeof (*result));
667 
668 	/* Get cache handle */
669 	result->retcode = get_cache_handle(&cache);
670 	if (result->retcode != IDMAP_SUCCESS)
671 		goto out;
672 
673 	/* Get db handle */
674 	result->retcode = get_db_handle(&db);
675 	if (result->retcode != IDMAP_SUCCESS)
676 		goto out;
677 
678 	/* Allocate result */
679 	result->mappings.mappings_val = calloc(1, sizeof (idmap_mapping));
680 	if (result->mappings.mappings_val == NULL) {
681 		idmapdlog(LOG_ERR, "Out of memory");
682 		result->retcode = IDMAP_ERR_MEMORY;
683 		goto out;
684 	}
685 	result->mappings.mappings_len = 1;
686 
687 	if (IS_REQUEST_SID(request)) {
688 		result->retcode = get_w2u_mapping(
689 			cache,
690 			db,
691 			&request,
692 			result->mappings.mappings_val);
693 	} else if (IS_REQUEST_UID(request)) {
694 		result->retcode = get_u2w_mapping(
695 			cache,
696 			db,
697 			&request,
698 			result->mappings.mappings_val,
699 			1);
700 	} else if (IS_REQUEST_GID(request)) {
701 		result->retcode = get_u2w_mapping(
702 			cache,
703 			db,
704 			&request,
705 			result->mappings.mappings_val,
706 			0);
707 	} else {
708 		result->retcode = IDMAP_ERR_IDTYPE;
709 	}
710 
711 out:
712 	if (IDMAP_FATAL_ERROR(result->retcode)) {
713 		xdr_free(xdr_idmap_mappings_res, (caddr_t)result);
714 		result->mappings.mappings_len = 0;
715 		result->mappings.mappings_val = NULL;
716 	}
717 	if (cache)
718 		(void) sqlite_close(cache);
719 	if (db)
720 		(void) sqlite_close(db);
721 	result->retcode = idmap_stat4prot(result->retcode);
722 	return (TRUE);
723 }
724 
725 
726 /* ARGSUSED */
727 int
728 idmap_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result,
729 		caddr_t result) {
730 	(void) xdr_free(xdr_result, result);
731 	return (TRUE);
732 }
733