xref: /titanic_50/usr/src/cmd/idmap/idmapd/server.c (revision 1100f00d5652de2808b73c61bcfdb3fc87ef1fc8)
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 = 1;
284 	else if (w2u == 0 && u2w > 0)
285 		result->mappings.mappings_val[cb_data->next].direction = 2;
286 	else
287 		result->mappings.mappings_val[cb_data->next].direction = 0;
288 
289 	ptr = &result->mappings.mappings_val[cb_data->next].id1domain;
290 	if (idmap_str2utf8(&ptr, argv[6], 0) != IDMAP_SUCCESS)
291 		return (1);
292 
293 	ptr = &result->mappings.mappings_val[cb_data->next].id1name;
294 	if (idmap_str2utf8(&ptr, argv[7], 0) != IDMAP_SUCCESS)
295 		return (1);
296 
297 	ptr = &result->mappings.mappings_val[cb_data->next].id2name;
298 	if (idmap_str2utf8(&ptr, argv[8], 0) != IDMAP_SUCCESS)
299 		return (1);
300 
301 	result->lastrowid = strtoll(argv[0], &end, 10);
302 	cb_data->next++;
303 	result->retcode = IDMAP_SUCCESS;
304 	return (0);
305 }
306 
307 
308 /* ARGSUSED */
309 bool_t
310 idmap_list_mappings_1_svc(bool_t is_user, int64_t lastrowid,
311 		uint64_t limit, idmap_mappings_res *result,
312 		struct svc_req *rqstp) {
313 	sqlite		*cache = NULL;
314 	char		lbuf[30], rbuf[30];
315 	uint64_t	maxlimit;
316 	idmap_retcode	retcode;
317 	char		*sql = NULL;
318 
319 	(void) memset(result, 0, sizeof (*result));
320 	lbuf[0] = rbuf[0] = 0;
321 
322 	RDLOCK_CONFIG();
323 	maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit;
324 	UNLOCK_CONFIG();
325 
326 	/* Get cache handle */
327 	result->retcode = get_cache_handle(&cache);
328 	if (result->retcode != IDMAP_SUCCESS)
329 		goto out;
330 
331 	result->retcode = IDMAP_ERR_INTERNAL;
332 
333 	/* Create LIMIT expression. */
334 	if (limit == 0 || (maxlimit > 0 && maxlimit < limit))
335 		limit = maxlimit;
336 	if (limit > 0)
337 		(void) snprintf(lbuf, sizeof (lbuf),
338 			"LIMIT %" PRIu64, limit + 1ULL);
339 
340 	(void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid);
341 
342 	/*
343 	 * Combine all the above into a giant SELECT statement that
344 	 * will return the requested mappings
345 	 */
346 	sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, u2w,"
347 			" windomain, winname, unixname"
348 			" FROM idmap_cache WHERE "
349 			" %s AND is_user = %d %s;",
350 			rbuf, is_user?1:0, lbuf);
351 	if (sql == NULL) {
352 		idmapdlog(LOG_ERR, "Out of memory");
353 		goto out;
354 	}
355 
356 	/* Execute the SQL statement and update the return buffer */
357 	PROCESS_LIST_SVC_SQL(retcode, cache, sql, limit, list_mappings_cb,
358 		result, result->mappings.mappings_len);
359 
360 out:
361 	if (sql)
362 		sqlite_freemem(sql);
363 	if (IDMAP_ERROR(result->retcode))
364 		(void) xdr_free(xdr_idmap_mappings_res, (caddr_t)result);
365 	if (cache)
366 		(void) sqlite_close(cache);
367 	result->retcode = idmap_stat4prot(result->retcode);
368 	return (TRUE);
369 }
370 
371 
372 /* ARGSUSED */
373 static int
374 list_namerules_cb(void *parg, int argc, char **argv, char **colnames) {
375 	list_cb_data_t		*cb_data;
376 	idmap_namerules_res	*result;
377 	idmap_retcode		retcode;
378 	idmap_utf8str		*ptr;
379 	int			w2u_order, u2w_order;
380 	char			*end;
381 
382 	cb_data = (list_cb_data_t *)parg;
383 	result = (idmap_namerules_res *)cb_data->result;
384 
385 	_VALIDATE_LIST_CB_DATA(8, &result->rules.rules_val,
386 		sizeof (idmap_namerule));
387 
388 	result->rules.rules_len++;
389 
390 	result->rules.rules_val[cb_data->next].is_user =
391 		strtol(argv[1], &end, 10);
392 
393 	ptr = &result->rules.rules_val[cb_data->next].windomain;
394 	if (idmap_str2utf8(&ptr, argv[2], 0) != IDMAP_SUCCESS)
395 		return (1);
396 
397 	ptr = &result->rules.rules_val[cb_data->next].winname;
398 	if (idmap_str2utf8(&ptr, argv[3], 0) != IDMAP_SUCCESS)
399 		return (1);
400 
401 	result->rules.rules_val[cb_data->next].is_nt4 =
402 		strtol(argv[4], &end, 10);
403 
404 	ptr = &result->rules.rules_val[cb_data->next].unixname;
405 	if (idmap_str2utf8(&ptr, argv[5], 0) != IDMAP_SUCCESS)
406 		return (1);
407 
408 	w2u_order = argv[6]?strtol(argv[6], &end, 10):0;
409 	u2w_order = argv[7]?strtol(argv[7], &end, 10):0;
410 
411 	if (w2u_order > 0 && u2w_order == 0)
412 		result->rules.rules_val[cb_data->next].direction = 1;
413 	else if (w2u_order == 0 && u2w_order > 0)
414 		result->rules.rules_val[cb_data->next].direction = 2;
415 	else
416 		result->rules.rules_val[cb_data->next].direction = 0;
417 
418 	result->lastrowid = strtoll(argv[0], &end, 10);
419 	cb_data->next++;
420 	result->retcode = IDMAP_SUCCESS;
421 	return (0);
422 }
423 
424 
425 /* ARGSUSED */
426 bool_t
427 idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid,
428 		uint64_t limit, idmap_namerules_res *result,
429 		struct svc_req *rqstp) {
430 
431 	sqlite		*db = NULL;
432 	char		w2ubuf[15], u2wbuf[15];
433 	char		lbuf[30], rbuf[30];
434 	char		*sql = NULL;
435 	char		*s_windomain = NULL, *s_winname = NULL;
436 	char		*s_unixname = NULL;
437 	uint64_t	maxlimit;
438 	idmap_retcode	retcode;
439 
440 	(void) memset(result, 0, sizeof (*result));
441 	lbuf[0] = rbuf[0] = 0;
442 
443 	RDLOCK_CONFIG();
444 	maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit;
445 	UNLOCK_CONFIG();
446 
447 	/* Get db handle */
448 	result->retcode = get_db_handle(&db);
449 	if (result->retcode != IDMAP_SUCCESS)
450 		goto out;
451 
452 	result->retcode = IDMAP_ERR_INTERNAL;
453 
454 	if (rule.direction < 0) {
455 		w2ubuf[0] = u2wbuf[0] = 0;
456 	} else if (rule.direction == 0) {
457 		(void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0");
458 		(void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0");
459 	} else if (rule.direction == 1) {
460 		(void) snprintf(w2ubuf, sizeof (w2ubuf), "AND w2u_order > 0");
461 		(void) snprintf(u2wbuf, sizeof (u2wbuf),
462 				"AND (u2w_order = 0 OR u2w_order ISNULL)");
463 	} else if (rule.direction == 2) {
464 		(void) snprintf(w2ubuf, sizeof (w2ubuf),
465 				"AND (w2u_order = 0 OR w2u_order ISNULL)");
466 		(void) snprintf(u2wbuf, sizeof (u2wbuf), "AND u2w_order > 0");
467 	}
468 
469 	/* Create where statement for windomain */
470 	if (rule.windomain.idmap_utf8str_len > 0) {
471 		if (gen_sql_expr_from_utf8str("AND", "windomain", "=",
472 				&rule.windomain,
473 				"", &s_windomain) != IDMAP_SUCCESS)
474 			goto out;
475 	}
476 
477 	/* Create where statement for winname */
478 	if (rule.winname.idmap_utf8str_len > 0) {
479 		if (gen_sql_expr_from_utf8str("AND", "winname", "=",
480 				&rule.winname,
481 				"", &s_winname) != IDMAP_SUCCESS)
482 			goto out;
483 	}
484 
485 	/* Create where statement for unixname */
486 	if (rule.unixname.idmap_utf8str_len > 0) {
487 		if (gen_sql_expr_from_utf8str("AND", "unixname", "=",
488 				&rule.unixname,
489 				"", &s_unixname) != IDMAP_SUCCESS)
490 			goto out;
491 	}
492 
493 	/* Create LIMIT expression. */
494 	if (limit == 0 || (maxlimit > 0 && maxlimit < limit))
495 		limit = maxlimit;
496 	if (limit > 0)
497 		(void) snprintf(lbuf, sizeof (lbuf),
498 			"LIMIT %" PRIu64, limit + 1ULL);
499 
500 	(void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid);
501 
502 	/*
503 	 * Combine all the above into a giant SELECT statement that
504 	 * will return the requested rules
505 	 */
506 	sql = sqlite_mprintf("SELECT rowid, is_user, windomain, winname, "
507 			"is_nt4, unixname, w2u_order, u2w_order "
508 			"FROM namerules WHERE "
509 			" %s AND is_user = %d %s %s %s %s %s %s;",
510 			rbuf, rule.is_user?1:0,
511 			s_windomain?s_windomain:"",
512 			s_winname?s_winname:"",
513 			s_unixname?s_unixname:"",
514 			w2ubuf, u2wbuf, lbuf);
515 	if (sql == NULL) {
516 		idmapdlog(LOG_ERR, "Out of memory");
517 		goto out;
518 	}
519 
520 	/* Execute the SQL statement and update the return buffer */
521 	PROCESS_LIST_SVC_SQL(retcode, db, sql, limit, list_namerules_cb,
522 		result, result->rules.rules_len);
523 
524 out:
525 	if (s_windomain)
526 		sqlite_freemem(s_windomain);
527 	if (s_winname)
528 		sqlite_freemem(s_winname);
529 	if (s_unixname)
530 		sqlite_freemem(s_unixname);
531 	if (sql)
532 		sqlite_freemem(sql);
533 	if (IDMAP_ERROR(result->retcode))
534 		(void) xdr_free(xdr_idmap_namerules_res, (caddr_t)result);
535 	if (db)
536 		(void) sqlite_close(db);
537 	result->retcode = idmap_stat4prot(result->retcode);
538 	return (TRUE);
539 }
540 
541 #define	IDMAP_RULES_AUTH	"solaris.admin.idmap.rules"
542 static int
543 verify_rules_auth(struct svc_req *rqstp) {
544 	ucred_t		*uc = NULL;
545 	uid_t		uid;
546 	char		buf[1024];
547 	struct passwd	pwd;
548 	const char	*me = "verify_rules_auth";
549 
550 	if (svc_getcallerucred(rqstp->rq_xprt, &uc) != 0) {
551 		idmapdlog(LOG_ERR,
552 			"%s: svc_getcallerucred failed (errno=%d)",
553 			me, errno);
554 		return (-1);
555 	}
556 
557 	uid = ucred_geteuid(uc);
558 	if (uid == (uid_t)-1) {
559 		idmapdlog(LOG_ERR,
560 			"%s: ucred_geteuid failed (errno=%d)",
561 			me, errno);
562 		ucred_free(uc);
563 		return (-1);
564 	}
565 
566 	if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) {
567 		idmapdlog(LOG_ERR,
568 			"%s: getpwuid_r(%u) failed (errno=%d)",
569 			me, uid, errno);
570 		ucred_free(uc);
571 		return (-1);
572 	}
573 
574 	if (chkauthattr(IDMAP_RULES_AUTH, pwd.pw_name) != 1) {
575 		idmapdlog(LOG_INFO,
576 			"%s: %s does not have authorization.",
577 			me, pwd.pw_name);
578 		ucred_free(uc);
579 		return (-1);
580 	}
581 
582 	ucred_free(uc);
583 	return (1);
584 }
585 
586 /* ARGSUSED */
587 bool_t
588 idmap_update_1_svc(idmap_update_batch batch, idmap_retcode *result,
589 		struct svc_req *rqstp) {
590 	sqlite		*db = NULL;
591 	idmap_update_op	*up;
592 	int		i;
593 
594 	if (verify_rules_auth(rqstp) < 0) {
595 		*result = IDMAP_ERR_PERMISSION_DENIED;
596 		goto out;
597 	}
598 
599 	if (batch.idmap_update_batch_len == 0 ||
600 			batch.idmap_update_batch_val == NULL) {
601 		*result = IDMAP_SUCCESS;
602 		goto out;
603 	}
604 
605 	/* Get db handle */
606 	*result = get_db_handle(&db);
607 	if (*result != IDMAP_SUCCESS)
608 		goto out;
609 
610 	*result = sql_exec_no_cb(db, "BEGIN TRANSACTION;");
611 	if (*result != IDMAP_SUCCESS)
612 		goto out;
613 
614 	for (i = 0; i < batch.idmap_update_batch_len; i++) {
615 		up = &batch.idmap_update_batch_val[i];
616 		switch (up->opnum) {
617 		case OP_NONE:
618 			*result = IDMAP_SUCCESS;
619 			break;
620 		case OP_ADD_NAMERULE:
621 			*result = add_namerule(db,
622 				&up->idmap_update_op_u.rule);
623 			break;
624 		case OP_RM_NAMERULE:
625 			*result = rm_namerule(db,
626 				&up->idmap_update_op_u.rule);
627 			break;
628 		case OP_FLUSH_NAMERULES:
629 			*result = flush_namerules(db,
630 				up->idmap_update_op_u.is_user);
631 			break;
632 		default:
633 			*result = IDMAP_ERR_NOTSUPPORTED;
634 			goto out;
635 		};
636 
637 		if (*result != IDMAP_SUCCESS)
638 			goto out;
639 	}
640 
641 out:
642 	if (*result == IDMAP_SUCCESS && db) {
643 		*result = sql_exec_no_cb(db, "COMMIT TRANSACTION;");
644 	}
645 
646 	if (db)
647 		(void) sqlite_close(db);
648 	*result = idmap_stat4prot(*result);
649 	return (TRUE);
650 }
651 
652 
653 /* ARGSUSED */
654 bool_t
655 idmap_get_mapped_id_by_name_1_svc(idmap_mapping request,
656 		idmap_mappings_res *result, struct svc_req *rqstp) {
657 	sqlite		*cache = NULL, *db = NULL;
658 
659 	/* Init */
660 	(void) memset(result, 0, sizeof (*result));
661 
662 	/* Get cache handle */
663 	result->retcode = get_cache_handle(&cache);
664 	if (result->retcode != IDMAP_SUCCESS)
665 		goto out;
666 
667 	/* Get db handle */
668 	result->retcode = get_db_handle(&db);
669 	if (result->retcode != IDMAP_SUCCESS)
670 		goto out;
671 
672 	/* Allocate result */
673 	result->mappings.mappings_val = calloc(1, sizeof (idmap_mapping));
674 	if (result->mappings.mappings_val == NULL) {
675 		idmapdlog(LOG_ERR, "Out of memory");
676 		result->retcode = IDMAP_ERR_MEMORY;
677 		goto out;
678 	}
679 	result->mappings.mappings_len = 1;
680 
681 	if (IS_REQUEST_SID(request)) {
682 		result->retcode = get_w2u_mapping(
683 			cache,
684 			db,
685 			&request,
686 			result->mappings.mappings_val);
687 	} else if (IS_REQUEST_UID(request)) {
688 		result->retcode = get_u2w_mapping(
689 			cache,
690 			db,
691 			&request,
692 			result->mappings.mappings_val,
693 			1);
694 	} else if (IS_REQUEST_GID(request)) {
695 		result->retcode = get_u2w_mapping(
696 			cache,
697 			db,
698 			&request,
699 			result->mappings.mappings_val,
700 			0);
701 	} else {
702 		result->retcode = IDMAP_ERR_IDTYPE;
703 	}
704 
705 out:
706 	if (IDMAP_FATAL_ERROR(result->retcode)) {
707 		xdr_free(xdr_idmap_mappings_res, (caddr_t)result);
708 		result->mappings.mappings_len = 0;
709 		result->mappings.mappings_val = NULL;
710 	}
711 	if (cache)
712 		(void) sqlite_close(cache);
713 	if (db)
714 		(void) sqlite_close(db);
715 	result->retcode = idmap_stat4prot(result->retcode);
716 	return (TRUE);
717 }
718 
719 
720 /* ARGSUSED */
721 int
722 idmap_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result,
723 		caddr_t result) {
724 	(void) xdr_free(xdr_result, result);
725 	return (TRUE);
726 }
727