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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2022 RackTop Systems, Inc.
24 */
25
26
27 /*
28 * Service routines
29 */
30
31 #include "idmapd.h"
32 #include "idmap_priv.h"
33 #include "nldaputils.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 <sys/sid.h>
43 #include <ucred.h>
44 #include <pwd.h>
45 #include <auth_attr.h>
46 #include <secdb.h>
47 #include <sys/u8_textprep.h>
48 #include <note.h>
49
50 #define _VALIDATE_LIST_CB_DATA(col, val, siz)\
51 retcode = validate_list_cb_data(cb_data, argc, argv, col,\
52 (uchar_t **)val, siz);\
53 if (retcode == IDMAP_NEXT) {\
54 result->retcode = IDMAP_NEXT;\
55 return (0);\
56 } else if (retcode < 0) {\
57 result->retcode = retcode;\
58 return (1);\
59 }
60
61 #define PROCESS_LIST_SVC_SQL(rcode, db, dbname, sql, limit, flag, cb, res, len)\
62 rcode = process_list_svc_sql(db, dbname, sql, limit, flag, cb, res);\
63 if (rcode == IDMAP_ERR_BUSY)\
64 res->retcode = IDMAP_ERR_BUSY;\
65 else if (rcode == IDMAP_SUCCESS && len == 0)\
66 res->retcode = IDMAP_ERR_NOTFOUND;
67
68
69 #define STRDUP_OR_FAIL(to, from) \
70 if ((from) == NULL) \
71 to = NULL; \
72 else { \
73 if ((to = strdup(from)) == NULL) \
74 return (1); \
75 }
76
77 #define STRDUP_CHECK(to, from) \
78 if ((from) != NULL) { \
79 to = strdup(from); \
80 if (to == NULL) { \
81 result->retcode = IDMAP_ERR_MEMORY; \
82 goto out; \
83 } \
84 }
85
86 /* ARGSUSED */
87 bool_t
idmap_null_1_svc(void * result,struct svc_req * rqstp)88 idmap_null_1_svc(void *result, struct svc_req *rqstp)
89 {
90 return (TRUE);
91 }
92
93 /*
94 * RPC layer allocates empty strings to replace NULL char *.
95 * This utility function frees these empty strings.
96 */
97 static
98 void
sanitize_mapping_request(idmap_mapping * req)99 sanitize_mapping_request(idmap_mapping *req)
100 {
101 if (EMPTY_STRING(req->id1name)) {
102 free(req->id1name);
103 req->id1name = NULL;
104 }
105 if (EMPTY_STRING(req->id1domain)) {
106 free(req->id1domain);
107 req->id1domain = NULL;
108 }
109 if (EMPTY_STRING(req->id2name)) {
110 free(req->id2name);
111 req->id2name = NULL;
112 }
113 if (EMPTY_STRING(req->id2domain)) {
114 free(req->id2domain);
115 req->id2domain = NULL;
116 }
117 req->direction = _IDMAP_F_DONE;
118 }
119
120 static
121 int
validate_mapped_id_by_name_req(idmap_mapping * req)122 validate_mapped_id_by_name_req(idmap_mapping *req)
123 {
124 int e;
125
126 if (IS_ID_UID(req->id1) || IS_ID_GID(req->id1))
127 return (IDMAP_SUCCESS);
128
129 if (IS_ID_SID(req->id1)) {
130 if (!EMPTY_STRING(req->id1name) &&
131 u8_validate(req->id1name, strlen(req->id1name),
132 NULL, U8_VALIDATE_ENTIRE, &e) < 0)
133 return (IDMAP_ERR_BAD_UTF8);
134 if (!EMPTY_STRING(req->id1domain) &&
135 u8_validate(req->id1domain, strlen(req->id1domain),
136 NULL, U8_VALIDATE_ENTIRE, &e) < 0)
137 return (IDMAP_ERR_BAD_UTF8);
138 }
139
140 return (IDMAP_SUCCESS);
141 }
142
143 static
144 int
validate_rule(idmap_namerule * rule)145 validate_rule(idmap_namerule *rule)
146 {
147 int e;
148
149 if (!EMPTY_STRING(rule->winname) &&
150 u8_validate(rule->winname, strlen(rule->winname),
151 NULL, U8_VALIDATE_ENTIRE, &e) < 0)
152 return (IDMAP_ERR_BAD_UTF8);
153
154 if (!EMPTY_STRING(rule->windomain) &&
155 u8_validate(rule->windomain, strlen(rule->windomain),
156 NULL, U8_VALIDATE_ENTIRE, &e) < 0)
157 return (IDMAP_ERR_BAD_UTF8);
158
159 return (IDMAP_SUCCESS);
160
161 }
162
163 static
164 bool_t
validate_rules(idmap_update_batch * batch)165 validate_rules(idmap_update_batch *batch)
166 {
167 idmap_update_op *up;
168 int i;
169
170 for (i = 0; i < batch->idmap_update_batch_len; i++) {
171 up = &(batch->idmap_update_batch_val[i]);
172 if (validate_rule(&(up->idmap_update_op_u.rule))
173 != IDMAP_SUCCESS)
174 return (IDMAP_ERR_BAD_UTF8);
175 }
176
177 return (IDMAP_SUCCESS);
178 }
179
180 /* ARGSUSED */
181 bool_t
idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,idmap_ids_res * result,struct svc_req * rqstp)182 idmap_get_mapped_ids_1_svc(idmap_mapping_batch batch,
183 idmap_ids_res *result, struct svc_req *rqstp)
184 {
185 sqlite *cache = NULL, *db = NULL;
186 lookup_state_t state;
187 idmap_retcode retcode;
188 uint_t i;
189 idmap_mapping *req;
190 idmap_id_res *res;
191 boolean_t any_tracing;
192 int rc;
193
194 /* Init */
195 (void) memset(result, 0, sizeof (*result));
196 (void) memset(&state, 0, sizeof (state));
197
198 /* Return success if nothing was requested */
199 if (batch.idmap_mapping_batch_len < 1)
200 goto out;
201
202 /* Get cache handle */
203 result->retcode = get_cache_handle(&cache);
204 if (result->retcode != IDMAP_SUCCESS)
205 goto out;
206 state.cache = cache;
207
208 /* Get db handle */
209 result->retcode = get_db_handle(&db);
210 if (result->retcode != IDMAP_SUCCESS)
211 goto out;
212 state.db = db;
213
214 /* Allocate result array */
215 result->ids.ids_val = calloc(batch.idmap_mapping_batch_len,
216 sizeof (idmap_id_res));
217 if (result->ids.ids_val == NULL) {
218 idmapdlog(LOG_ERR, "Out of memory");
219 result->retcode = IDMAP_ERR_MEMORY;
220 goto out;
221 }
222 result->ids.ids_len = batch.idmap_mapping_batch_len;
223
224 /* Allocate hash table to check for duplicate sids */
225 state.sid_history = calloc(batch.idmap_mapping_batch_len,
226 sizeof (*state.sid_history));
227 if (state.sid_history == NULL) {
228 idmapdlog(LOG_ERR, "Out of memory");
229 result->retcode = IDMAP_ERR_MEMORY;
230 goto out;
231 }
232 state.sid_history_size = batch.idmap_mapping_batch_len;
233 for (i = 0; i < state.sid_history_size; i++) {
234 state.sid_history[i].key = state.sid_history_size;
235 state.sid_history[i].next = state.sid_history_size;
236 }
237 state.batch = &batch;
238 state.result = result;
239
240 /* Get directory-based name mapping info */
241 result->retcode = load_cfg_in_state(&state);
242 if (result->retcode != IDMAP_SUCCESS)
243 goto out;
244
245 /* Init our 'done' flags */
246 state.sid2pid_done = state.pid2sid_done = TRUE;
247
248 any_tracing = B_FALSE;
249
250 /* First stage */
251 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
252 req = &batch.idmap_mapping_batch_val[i];
253 res = &result->ids.ids_val[i];
254 if (TRACING(req))
255 any_tracing = B_TRUE;
256 state.curpos = i;
257 (void) sanitize_mapping_request(req);
258 TRACE(req, res, "Start mapping");
259 if (IS_ID_SID(req->id1)) {
260 retcode = sid2pid_first_pass(
261 &state,
262 req,
263 res);
264 } else if (IS_ID_UID(req->id1)) {
265 retcode = pid2sid_first_pass(
266 &state,
267 req,
268 res, 1);
269 } else if (IS_ID_GID(req->id1)) {
270 retcode = pid2sid_first_pass(
271 &state,
272 req,
273 res, 0);
274 } else {
275 res->retcode = IDMAP_ERR_IDTYPE;
276 continue;
277 }
278 if (IDMAP_FATAL_ERROR(retcode)) {
279 result->retcode = retcode;
280 goto out;
281 }
282 }
283
284 /* Check if we are done */
285 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE)
286 goto out;
287
288 /*
289 * native LDAP lookups:
290 * pid2sid:
291 * - nldap or mixed mode. Lookup nldap by pid or unixname to get
292 * winname.
293 * sid2pid:
294 * - nldap mode. Got winname and sid (either given or found in
295 * name_cache). Lookup nldap by winname to get pid and
296 * unixname.
297 */
298 if (state.nldap_nqueries) {
299 retcode = nldap_lookup_batch(&state, &batch, result);
300 if (IDMAP_FATAL_ERROR(retcode)) {
301 TRACE(req, res, "Native LDAP lookup error=%d", retcode);
302 result->retcode = retcode;
303 goto out;
304 }
305 if (any_tracing) {
306 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
307 res = &result->ids.ids_val[i];
308 req = &batch.idmap_mapping_batch_val[i];
309 if (IDMAP_ERROR(res->retcode)) {
310 TRACE(req, res,
311 "Native LDAP lookup error=%d",
312 res->retcode);
313 } else {
314 TRACE(req, res, "Native LDAP lookup");
315 }
316 }
317 }
318 }
319
320 /*
321 * AD lookups:
322 * pid2sid:
323 * - nldap or mixed mode. Got winname from nldap lookup.
324 * winname2sid could not be resolved locally. Lookup AD
325 * by winname to get sid.
326 * - ad mode. Got unixname. Lookup AD by unixname to get
327 * winname and sid.
328 * sid2pid:
329 * - ad or mixed mode. Lookup AD by sid or winname to get
330 * winname, sid and unixname.
331 * - any mode. Got either sid or winname but not both. Lookup
332 * AD by sid or winname to get winname, sid.
333 */
334 if (state.ad_nqueries) {
335 retcode = ad_lookup_batch(&state, &batch, result);
336 if (IDMAP_FATAL_ERROR(retcode)) {
337 TRACE(req, res, "AD lookup error=%d", retcode);
338 result->retcode = retcode;
339 goto out;
340 }
341 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
342 res = &result->ids.ids_val[i];
343 req = &batch.idmap_mapping_batch_val[i];
344 if (res->retcode == IDMAP_ERR_DOMAIN_NOTFOUND &&
345 req->id1.idmap_id_u.sid.prefix != NULL &&
346 req->id1name != NULL) {
347 /*
348 * If AD lookup failed Domain Not Found but
349 * we have a winname and SID, it means that
350 * - LSA succeeded
351 * - it's a request a cross-forest trust
352 * and
353 * - we were looking for directory-based
354 * mapping information.
355 * In that case, we're OK, just go on.
356 *
357 * If this seems more convoluted than it
358 * should be, it is - really, we probably
359 * shouldn't even be attempting AD lookups
360 * in this situation, but that's a more
361 * intricate cleanup that will have to wait
362 * for later.
363 */
364 res->retcode = IDMAP_SUCCESS;
365 TRACE(req, res,
366 "AD lookup - domain not found (ignored)");
367 continue;
368 }
369 }
370 }
371
372 /*
373 * native LDAP lookups:
374 * sid2pid:
375 * - nldap mode. Got winname and sid from AD lookup. Lookup nldap
376 * by winname to get pid and unixname.
377 */
378 if (state.nldap_nqueries) {
379 retcode = nldap_lookup_batch(&state, &batch, result);
380 if (IDMAP_FATAL_ERROR(retcode)) {
381 TRACE(req, res, "Native LDAP lookup error=%d", retcode);
382 result->retcode = retcode;
383 goto out;
384 }
385 if (any_tracing) {
386 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
387 res = &result->ids.ids_val[i];
388 req = &batch.idmap_mapping_batch_val[i];
389 TRACE(req, res, "Native LDAP lookup");
390 }
391 }
392 }
393
394 /* Reset 'done' flags */
395 state.sid2pid_done = state.pid2sid_done = TRUE;
396
397 /* Second stage */
398 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
399 req = &batch.idmap_mapping_batch_val[i];
400 res = &result->ids.ids_val[i];
401 state.curpos = i;
402 if (IS_ID_SID(req->id1)) {
403 retcode = sid2pid_second_pass(
404 &state,
405 req,
406 res);
407 } else if (IS_ID_UID(req->id1)) {
408 retcode = pid2sid_second_pass(
409 &state,
410 req,
411 res, 1);
412 } else if (IS_ID_GID(req->id1)) {
413 retcode = pid2sid_second_pass(
414 &state,
415 req,
416 res, 0);
417 } else {
418 /* First stage has already set the error */
419 continue;
420 }
421 if (IDMAP_FATAL_ERROR(retcode)) {
422 result->retcode = retcode;
423 goto out;
424 }
425 }
426
427 /* Check if we are done */
428 if (state.sid2pid_done == TRUE && state.pid2sid_done == TRUE)
429 goto out;
430
431 /* Reset our 'done' flags */
432 state.sid2pid_done = state.pid2sid_done = TRUE;
433
434 /* Update cache in a single transaction */
435 rc = sql_exec_no_cb(cache, IDMAP_CACHENAME, "BEGIN TRANSACTION;");
436 if (rc != IDMAP_SUCCESS)
437 goto out;
438
439 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
440 req = &batch.idmap_mapping_batch_val[i];
441 res = &result->ids.ids_val[i];
442 state.curpos = i;
443 if (IS_ID_SID(req->id1)) {
444 (void) update_cache_sid2pid(
445 &state,
446 req,
447 res);
448 } else if ((IS_ID_UID(req->id1)) ||
449 (IS_ID_GID(req->id1))) {
450 (void) update_cache_pid2sid(
451 &state,
452 req,
453 res);
454 }
455 }
456
457 /* Commit if we have at least one successful update */
458 if (state.sid2pid_done == FALSE || state.pid2sid_done == FALSE)
459 rc = sql_exec_no_cb(cache, IDMAP_CACHENAME,
460 "COMMIT TRANSACTION;");
461 else
462 rc = sql_exec_no_cb(cache, IDMAP_CACHENAME,
463 "END TRANSACTION;");
464 if (rc != IDMAP_SUCCESS) {
465 /* If (eg.) commit fails, make sure to close the TX. */
466 (void) sql_exec_no_cb(cache, IDMAP_CACHENAME,
467 "ROLLBACK TRANSACTION;");
468 }
469 out:
470 if (rc == IDMAP_ERR_DB || result->retcode == IDMAP_ERR_DB)
471 kill_cache_handle(cache);
472
473 cleanup_lookup_state(&state);
474 if (IDMAP_ERROR(result->retcode)) {
475 if (any_tracing) {
476 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
477 req = &batch.idmap_mapping_batch_val[i];
478 res = &result->ids.ids_val[i];
479 TRACE(req, res,
480 "Failure code %d", result->retcode);
481 }
482 }
483 xdr_free(xdr_idmap_ids_res, (caddr_t)result);
484 result->ids.ids_len = 0;
485 result->ids.ids_val = NULL;
486 } else {
487 if (any_tracing) {
488 for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
489 req = &batch.idmap_mapping_batch_val[i];
490 res = &result->ids.ids_val[i];
491 TRACE(req, res, "Done");
492 }
493 }
494 }
495 result->retcode = idmap_stat4prot(result->retcode);
496
497 for (i = 0; i < result->ids.ids_len; i++) {
498 req = &batch.idmap_mapping_batch_val[i];
499 res = &result->ids.ids_val[i];
500
501 if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO) &&
502 res->retcode == IDMAP_SUCCESS)
503 idmap_how_clear(&res->info.how);
504 }
505 return (TRUE);
506 }
507
508
509 /* ARGSUSED */
510 static
511 int
list_mappings_cb(void * parg,int argc,char ** argv,char ** colnames)512 list_mappings_cb(void *parg, int argc, char **argv, char **colnames)
513 {
514 list_cb_data_t *cb_data;
515 char *str;
516 idmap_mappings_res *result;
517 idmap_retcode retcode;
518 int w2u, u2w;
519 char *end;
520 static int validated_column_names = 0;
521 idmap_how *how;
522
523 cb_data = (list_cb_data_t *)parg;
524
525 if (!validated_column_names) {
526 assert(strcmp(colnames[0], "rowid") == 0);
527 assert(strcmp(colnames[1], "sidprefix") == 0);
528 assert(strcmp(colnames[2], "rid") == 0);
529 assert(strcmp(colnames[3], "pid") == 0);
530 assert(strcmp(colnames[4], "w2u") == 0);
531 assert(strcmp(colnames[5], "u2w") == 0);
532 assert(strcmp(colnames[6], "windomain") == 0);
533 assert(strcmp(colnames[7], "canon_winname") == 0);
534 assert(strcmp(colnames[8], "unixname") == 0);
535 assert(strcmp(colnames[9], "is_user") == 0);
536 assert(strcmp(colnames[10], "is_wuser") == 0);
537 assert(strcmp(colnames[11], "map_type") == 0);
538 assert(strcmp(colnames[12], "map_dn") == 0);
539 assert(strcmp(colnames[13], "map_attr") == 0);
540 assert(strcmp(colnames[14], "map_value") == 0);
541 assert(strcmp(colnames[15], "map_windomain") == 0);
542 assert(strcmp(colnames[16], "map_winname") == 0);
543 assert(strcmp(colnames[17], "map_unixname") == 0);
544 assert(strcmp(colnames[18], "map_is_nt4") == 0);
545 validated_column_names = 1;
546 }
547
548 result = (idmap_mappings_res *)cb_data->result;
549
550 _VALIDATE_LIST_CB_DATA(19, &result->mappings.mappings_val,
551 sizeof (idmap_mapping));
552
553 result->mappings.mappings_len++;
554
555 if ((str = strdup(argv[1])) == NULL)
556 return (1);
557 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.prefix =
558 str;
559 result->mappings.mappings_val[cb_data->next].id1.idmap_id_u.sid.rid =
560 strtoul(argv[2], &end, 10);
561 result->mappings.mappings_val[cb_data->next].id1.idtype =
562 strtol(argv[10], &end, 10) ? IDMAP_USID : IDMAP_GSID;
563
564 result->mappings.mappings_val[cb_data->next].id2.idmap_id_u.uid =
565 strtoul(argv[3], &end, 10);
566 result->mappings.mappings_val[cb_data->next].id2.idtype =
567 strtol(argv[9], &end, 10) ? IDMAP_UID : IDMAP_GID;
568
569 w2u = argv[4] ? strtol(argv[4], &end, 10) : 0;
570 u2w = argv[5] ? strtol(argv[5], &end, 10) : 0;
571
572 if (w2u > 0 && u2w == 0)
573 result->mappings.mappings_val[cb_data->next].direction =
574 IDMAP_DIRECTION_W2U;
575 else if (w2u == 0 && u2w > 0)
576 result->mappings.mappings_val[cb_data->next].direction =
577 IDMAP_DIRECTION_U2W;
578 else
579 result->mappings.mappings_val[cb_data->next].direction =
580 IDMAP_DIRECTION_BI;
581
582 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1domain,
583 argv[6]);
584
585 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1name,
586 argv[7]);
587
588 STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id2name,
589 argv[8]);
590
591 if (cb_data->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
592 how = &result->mappings.mappings_val[cb_data->next].info.how;
593 how->map_type = strtoul(argv[11], &end, 10);
594 switch (how->map_type) {
595 case IDMAP_MAP_TYPE_DS_AD:
596 how->idmap_how_u.ad.dn =
597 strdup(argv[12]);
598 how->idmap_how_u.ad.attr =
599 strdup(argv[13]);
600 how->idmap_how_u.ad.value =
601 strdup(argv[14]);
602 break;
603
604 case IDMAP_MAP_TYPE_DS_NLDAP:
605 how->idmap_how_u.nldap.dn =
606 strdup(argv[12]);
607 how->idmap_how_u.nldap.attr =
608 strdup(argv[13]);
609 how->idmap_how_u.nldap.value =
610 strdup(argv[14]);
611 break;
612
613 case IDMAP_MAP_TYPE_RULE_BASED:
614 how->idmap_how_u.rule.windomain =
615 strdup(argv[15]);
616 how->idmap_how_u.rule.winname =
617 strdup(argv[16]);
618 how->idmap_how_u.rule.unixname =
619 strdup(argv[17]);
620 how->idmap_how_u.rule.is_nt4 =
621 strtoul(argv[18], &end, 10);
622 how->idmap_how_u.rule.is_user =
623 strtol(argv[9], &end, 10);
624 how->idmap_how_u.rule.is_wuser =
625 strtol(argv[10], &end, 10);
626 break;
627
628 case IDMAP_MAP_TYPE_EPHEMERAL:
629 break;
630
631 case IDMAP_MAP_TYPE_LOCAL_SID:
632 break;
633
634 case IDMAP_MAP_TYPE_IDMU:
635 how->idmap_how_u.idmu.dn =
636 strdup(argv[12]);
637 how->idmap_how_u.idmu.attr =
638 strdup(argv[13]);
639 how->idmap_how_u.idmu.value =
640 strdup(argv[14]);
641 break;
642
643 default:
644 /* Unknown mapping type */
645 assert(FALSE);
646 }
647
648 }
649
650 result->lastrowid = strtoll(argv[0], &end, 10);
651 cb_data->next++;
652 result->retcode = IDMAP_SUCCESS;
653 return (0);
654 }
655
656
657 /* ARGSUSED */
658 bool_t
idmap_list_mappings_1_svc(int64_t lastrowid,uint64_t limit,int32_t flag,idmap_mappings_res * result,struct svc_req * rqstp)659 idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, int32_t flag,
660 idmap_mappings_res *result, struct svc_req *rqstp)
661 {
662 sqlite *cache = NULL;
663 char lbuf[30], rbuf[30];
664 uint64_t maxlimit;
665 idmap_retcode retcode;
666 char *sql = NULL;
667 time_t curtime;
668
669 (void) memset(result, 0, sizeof (*result));
670
671 /* Current time */
672 errno = 0;
673 if ((curtime = time(NULL)) == (time_t)-1) {
674 idmapdlog(LOG_ERR, "Failed to get current time (%s)",
675 strerror(errno));
676 retcode = IDMAP_ERR_INTERNAL;
677 goto out;
678 }
679
680 RDLOCK_CONFIG();
681 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit;
682 UNLOCK_CONFIG();
683
684 /* Get cache handle */
685 result->retcode = get_cache_handle(&cache);
686 if (result->retcode != IDMAP_SUCCESS)
687 goto out;
688
689 result->retcode = IDMAP_ERR_INTERNAL;
690
691 /* Create LIMIT expression. */
692 if (limit == 0 || (maxlimit > 0 && maxlimit < limit))
693 limit = maxlimit;
694 if (limit > 0)
695 (void) snprintf(lbuf, sizeof (lbuf),
696 "LIMIT %" PRIu64, limit + 1ULL);
697 else
698 lbuf[0] = '\0';
699
700 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid);
701
702 /*
703 * Combine all the above into a giant SELECT statement that
704 * will return the requested mappings
705 */
706
707 sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, "
708 "u2w, windomain, canon_winname, unixname, is_user, is_wuser, "
709 "map_type, map_dn, map_attr, map_value, map_windomain, "
710 "map_winname, map_unixname, map_is_nt4 "
711 "FROM idmap_cache WHERE %s AND "
712 "(pid >= 2147483648 OR (expiration = 0 OR "
713 "expiration ISNULL OR expiration > %d)) "
714 "%s;",
715 rbuf, curtime, lbuf);
716 if (sql == NULL) {
717 result->retcode = IDMAP_ERR_MEMORY;
718 idmapdlog(LOG_ERR, "Out of memory");
719 goto out;
720 }
721
722 /* Execute the SQL statement and update the return buffer */
723 PROCESS_LIST_SVC_SQL(retcode, cache, IDMAP_CACHENAME, sql, limit,
724 flag, list_mappings_cb, result, result->mappings.mappings_len);
725
726 if (retcode == IDMAP_ERR_DB)
727 kill_cache_handle(cache);
728
729 out:
730 if (sql)
731 sqlite_freemem(sql);
732 if (IDMAP_ERROR(result->retcode))
733 xdr_free(xdr_idmap_mappings_res, (caddr_t)result);
734 result->retcode = idmap_stat4prot(result->retcode);
735 return (TRUE);
736 }
737
738
739 /* ARGSUSED */
740 static
741 int
list_namerules_cb(void * parg,int argc,char ** argv,char ** colnames)742 list_namerules_cb(void *parg, int argc, char **argv, char **colnames)
743 {
744 list_cb_data_t *cb_data;
745 idmap_namerules_res *result;
746 idmap_retcode retcode;
747 int w2u_order, u2w_order;
748 char *end;
749 static int validated_column_names = 0;
750
751 if (!validated_column_names) {
752 assert(strcmp(colnames[0], "rowid") == 0);
753 assert(strcmp(colnames[1], "is_user") == 0);
754 assert(strcmp(colnames[2], "is_wuser") == 0);
755 assert(strcmp(colnames[3], "windomain") == 0);
756 assert(strcmp(colnames[4], "winname_display") == 0);
757 assert(strcmp(colnames[5], "is_nt4") == 0);
758 assert(strcmp(colnames[6], "unixname") == 0);
759 assert(strcmp(colnames[7], "w2u_order") == 0);
760 assert(strcmp(colnames[8], "u2w_order") == 0);
761 validated_column_names = 1;
762 }
763
764 cb_data = (list_cb_data_t *)parg;
765 result = (idmap_namerules_res *)cb_data->result;
766
767 _VALIDATE_LIST_CB_DATA(9, &result->rules.rules_val,
768 sizeof (idmap_namerule));
769
770 result->rules.rules_len++;
771
772 result->rules.rules_val[cb_data->next].is_user =
773 strtol(argv[1], &end, 10);
774
775 result->rules.rules_val[cb_data->next].is_wuser =
776 strtol(argv[2], &end, 10);
777
778 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].windomain,
779 argv[3]);
780
781 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].winname,
782 argv[4]);
783
784 result->rules.rules_val[cb_data->next].is_nt4 =
785 strtol(argv[5], &end, 10);
786
787 STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].unixname,
788 argv[6]);
789
790 w2u_order = argv[7] ? strtol(argv[7], &end, 10) : 0;
791 u2w_order = argv[8] ? strtol(argv[8], &end, 10) : 0;
792
793 if (w2u_order > 0 && u2w_order == 0)
794 result->rules.rules_val[cb_data->next].direction =
795 IDMAP_DIRECTION_W2U;
796 else if (w2u_order == 0 && u2w_order > 0)
797 result->rules.rules_val[cb_data->next].direction =
798 IDMAP_DIRECTION_U2W;
799 else
800 result->rules.rules_val[cb_data->next].direction =
801 IDMAP_DIRECTION_BI;
802
803 result->lastrowid = strtoll(argv[0], &end, 10);
804 cb_data->next++;
805 result->retcode = IDMAP_SUCCESS;
806 return (0);
807 }
808
809
810 /* ARGSUSED */
811 bool_t
idmap_list_namerules_1_svc(idmap_namerule rule,uint64_t lastrowid,uint64_t limit,idmap_namerules_res * result,struct svc_req * rqstp)812 idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid,
813 uint64_t limit, idmap_namerules_res *result, struct svc_req *rqstp)
814 {
815
816 sqlite *db = NULL;
817 char lbuf[30], rbuf[30];
818 char *sql = NULL;
819 char *expr = NULL;
820 uint64_t maxlimit;
821 idmap_retcode retcode;
822
823 (void) memset(result, 0, sizeof (*result));
824
825 result->retcode = validate_rule(&rule);
826 if (result->retcode != IDMAP_SUCCESS)
827 goto out;
828
829 RDLOCK_CONFIG();
830 maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit;
831 UNLOCK_CONFIG();
832
833 /* Get db handle */
834 result->retcode = get_db_handle(&db);
835 if (result->retcode != IDMAP_SUCCESS)
836 goto out;
837
838 result->retcode = gen_sql_expr_from_rule(&rule, &expr);
839 if (result->retcode != IDMAP_SUCCESS)
840 goto out;
841
842 /* Create LIMIT expression. */
843 if (limit == 0 || (maxlimit > 0 && maxlimit < limit))
844 limit = maxlimit;
845 if (limit > 0)
846 (void) snprintf(lbuf, sizeof (lbuf),
847 "LIMIT %" PRIu64, limit + 1ULL);
848 else
849 lbuf[0] = '\0';
850
851 (void) snprintf(rbuf, sizeof (rbuf), "rowid > %" PRIu64, lastrowid);
852
853 /*
854 * Combine all the above into a giant SELECT statement that
855 * will return the requested rules
856 */
857 sql = sqlite_mprintf("SELECT rowid, is_user, is_wuser, windomain, "
858 "winname_display, is_nt4, unixname, w2u_order, u2w_order "
859 "FROM namerules WHERE "
860 " %s %s %s;",
861 rbuf, expr, lbuf);
862
863 if (sql == NULL) {
864 result->retcode = IDMAP_ERR_MEMORY;
865 idmapdlog(LOG_ERR, "Out of memory");
866 goto out;
867 }
868
869 /* Execute the SQL statement and update the return buffer */
870 PROCESS_LIST_SVC_SQL(retcode, db, IDMAP_DBNAME, sql, limit,
871 0, list_namerules_cb, result, result->rules.rules_len);
872
873 if (retcode == IDMAP_ERR_DB)
874 kill_db_handle(db);
875
876 out:
877 if (expr)
878 sqlite_freemem(expr);
879 if (sql)
880 sqlite_freemem(sql);
881 if (IDMAP_ERROR(result->retcode))
882 xdr_free(xdr_idmap_namerules_res, (caddr_t)result);
883 result->retcode = idmap_stat4prot(result->retcode);
884 return (TRUE);
885 }
886
887 #define IDMAP_RULES_AUTH "solaris.admin.idmap.rules"
888 static int
verify_rules_auth(struct svc_req * rqstp)889 verify_rules_auth(struct svc_req *rqstp)
890 {
891 ucred_t *uc = NULL;
892 uid_t uid;
893 char buf[1024];
894 struct passwd pwd;
895
896 if (svc_getcallerucred(rqstp->rq_xprt, &uc) != 0) {
897 idmapdlog(LOG_ERR, "svc_getcallerucred failed during "
898 "authorization (%s)", strerror(errno));
899 return (-1);
900 }
901
902 uid = ucred_geteuid(uc);
903 if (uid == (uid_t)-1) {
904 idmapdlog(LOG_ERR, "ucred_geteuid failed during "
905 "authorization (%s)", strerror(errno));
906 ucred_free(uc);
907 return (-1);
908 }
909
910 if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) {
911 idmapdlog(LOG_ERR, "getpwuid_r(%u) failed during "
912 "authorization (%s)", uid, strerror(errno));
913 ucred_free(uc);
914 return (-1);
915 }
916
917 if (chkauthattr(IDMAP_RULES_AUTH, pwd.pw_name) != 1) {
918 idmapdlog(LOG_INFO, "%s is not authorized (%s)",
919 pwd.pw_name, IDMAP_RULES_AUTH);
920 ucred_free(uc);
921 return (-1);
922 }
923
924 ucred_free(uc);
925 return (1);
926 }
927
928 /*
929 * Meaning of the return values is the following: For retcode ==
930 * IDMAP_SUCCESS, everything went OK and error_index is
931 * undefined. Otherwise, error_index >=0 shows the failed batch
932 * element. errro_index == -1 indicates failure at the beginning,
933 * error_index == -2 at the end.
934 */
935
936 /* ARGSUSED */
937 bool_t
idmap_update_1_svc(idmap_update_batch batch,idmap_update_res * res,struct svc_req * rqstp)938 idmap_update_1_svc(idmap_update_batch batch, idmap_update_res *res,
939 struct svc_req *rqstp)
940 {
941 sqlite *db = NULL;
942 idmap_update_op *up;
943 int i;
944 int trans = FALSE;
945
946 res->error_index = -1;
947 (void) memset(&res->error_rule, 0, sizeof (res->error_rule));
948 (void) memset(&res->conflict_rule, 0, sizeof (res->conflict_rule));
949
950 if (verify_rules_auth(rqstp) < 0) {
951 res->retcode = IDMAP_ERR_PERMISSION_DENIED;
952 goto out;
953 }
954
955 if (batch.idmap_update_batch_len == 0 ||
956 batch.idmap_update_batch_val == NULL) {
957 res->retcode = IDMAP_SUCCESS;
958 goto out;
959 }
960
961 res->retcode = validate_rules(&batch);
962 if (res->retcode != IDMAP_SUCCESS)
963 goto out;
964
965 /* Get db handle */
966 res->retcode = get_db_handle(&db);
967 if (res->retcode != IDMAP_SUCCESS)
968 goto out;
969
970 res->retcode = sql_exec_no_cb(db, IDMAP_DBNAME, "BEGIN TRANSACTION;");
971 if (res->retcode != IDMAP_SUCCESS)
972 goto out;
973 trans = TRUE;
974
975 for (i = 0; i < batch.idmap_update_batch_len; i++) {
976 up = &batch.idmap_update_batch_val[i];
977 switch (up->opnum) {
978 case OP_NONE:
979 res->retcode = IDMAP_SUCCESS;
980 break;
981 case OP_ADD_NAMERULE:
982 res->retcode = add_namerule(db,
983 &up->idmap_update_op_u.rule);
984 break;
985 case OP_RM_NAMERULE:
986 res->retcode = rm_namerule(db,
987 &up->idmap_update_op_u.rule);
988 break;
989 case OP_FLUSH_NAMERULES:
990 res->retcode = flush_namerules(db);
991 break;
992 default:
993 res->retcode = IDMAP_ERR_NOTSUPPORTED;
994 break;
995 };
996
997 if (res->retcode != IDMAP_SUCCESS) {
998 res->error_index = i;
999 if (up->opnum == OP_ADD_NAMERULE ||
1000 up->opnum == OP_RM_NAMERULE) {
1001 idmap_stat r2 =
1002 idmap_namerule_cpy(&res->error_rule,
1003 &up->idmap_update_op_u.rule);
1004 if (r2 != IDMAP_SUCCESS)
1005 res->retcode = r2;
1006 }
1007 goto out;
1008 }
1009 }
1010
1011 out:
1012 if (trans) {
1013 if (res->retcode == IDMAP_SUCCESS) {
1014 res->retcode =
1015 sql_exec_no_cb(db, IDMAP_DBNAME,
1016 "COMMIT TRANSACTION;");
1017 if (res->retcode == IDMAP_SUCCESS) {
1018 /*
1019 * We've updated the rules. Expire the cache
1020 * so that existing mappings will be
1021 * reconsidered.
1022 */
1023 res->retcode =
1024 idmap_cache_flush(IDMAP_FLUSH_EXPIRE);
1025 } else {
1026 res->error_index = -2;
1027 }
1028 }
1029 else
1030 (void) sql_exec_no_cb(db, IDMAP_DBNAME,
1031 "ROLLBACK TRANSACTION;");
1032 }
1033
1034 if (res->retcode == IDMAP_ERR_DB)
1035 kill_db_handle(db);
1036
1037 res->retcode = idmap_stat4prot(res->retcode);
1038
1039 return (TRUE);
1040 }
1041
1042 static
1043 int
copy_string(char ** to,char * from)1044 copy_string(char **to, char *from)
1045 {
1046 if (EMPTY_STRING(from)) {
1047 *to = NULL;
1048 } else {
1049 *to = strdup(from);
1050 if (*to == NULL) {
1051 idmapdlog(LOG_ERR, "Out of memory");
1052 return (IDMAP_ERR_MEMORY);
1053 }
1054 }
1055 return (IDMAP_SUCCESS);
1056 }
1057
1058 static
1059 int
copy_id(idmap_id * to,idmap_id * from)1060 copy_id(idmap_id *to, idmap_id *from)
1061 {
1062 (void) memset(to, 0, sizeof (*to));
1063
1064 to->idtype = from->idtype;
1065 if (IS_ID_SID(*from)) {
1066 idmap_retcode retcode;
1067
1068 to->idmap_id_u.sid.rid = from->idmap_id_u.sid.rid;
1069 retcode = copy_string(&to->idmap_id_u.sid.prefix,
1070 from->idmap_id_u.sid.prefix);
1071
1072 return (retcode);
1073 } else {
1074 to->idmap_id_u.uid = from->idmap_id_u.uid;
1075 return (IDMAP_SUCCESS);
1076 }
1077 }
1078
1079 static
1080 int
copy_mapping(idmap_mapping * mapping,idmap_mapping * request)1081 copy_mapping(idmap_mapping *mapping, idmap_mapping *request)
1082 {
1083 idmap_retcode retcode;
1084
1085 (void) memset(mapping, 0, sizeof (*mapping));
1086
1087 mapping->flag = request->flag;
1088 mapping->direction = _IDMAP_F_DONE;
1089
1090 retcode = copy_id(&mapping->id1, &request->id1);
1091 if (retcode != IDMAP_SUCCESS)
1092 goto errout;
1093
1094 retcode = copy_string(&mapping->id1domain, request->id1domain);
1095 if (retcode != IDMAP_SUCCESS)
1096 goto errout;
1097
1098 retcode = copy_string(&mapping->id1name, request->id1name);
1099 if (retcode != IDMAP_SUCCESS)
1100 goto errout;
1101
1102 retcode = copy_id(&mapping->id2, &request->id2);
1103 if (retcode != IDMAP_SUCCESS)
1104 goto errout;
1105
1106 retcode = copy_string(&mapping->id2domain, request->id2domain);
1107 if (retcode != IDMAP_SUCCESS)
1108 goto errout;
1109 retcode = copy_string(&mapping->id2name, request->id2name);
1110 if (retcode != IDMAP_SUCCESS)
1111 goto errout;
1112
1113 return (IDMAP_SUCCESS);
1114
1115 errout:
1116 if (IS_ID_SID(mapping->id1))
1117 free(mapping->id1.idmap_id_u.sid.prefix);
1118 free(mapping->id1domain);
1119 free(mapping->id1name);
1120 if (IS_ID_SID(mapping->id2))
1121 free(mapping->id2.idmap_id_u.sid.prefix);
1122 free(mapping->id2domain);
1123 free(mapping->id2name);
1124
1125 (void) memset(mapping, 0, sizeof (*mapping));
1126 return (retcode);
1127 }
1128
1129
1130 /* ARGSUSED */
1131 bool_t
idmap_get_mapped_id_by_name_1_svc(idmap_mapping request,idmap_mappings_res * result,struct svc_req * rqstp)1132 idmap_get_mapped_id_by_name_1_svc(idmap_mapping request,
1133 idmap_mappings_res *result, struct svc_req *rqstp)
1134 {
1135 idmap_mapping_batch batch_request;
1136 idmap_ids_res batch_result;
1137 idmap_mapping *map;
1138
1139 /* Clear out things we might want to xdr_free on error */
1140 (void) memset(&batch_result, 0, sizeof (batch_result));
1141 (void) memset(result, 0, sizeof (*result));
1142
1143 result->retcode = validate_mapped_id_by_name_req(&request);
1144 if (result->retcode != IDMAP_SUCCESS)
1145 goto out;
1146
1147 /*
1148 * Copy the request. We need to modify it, and
1149 * what we have is a shallow copy. Freeing pointers from
1150 * our copy will lead to problems, since the RPC framework
1151 * has its own copy of those pointers. Besides, we need
1152 * a copy to return.
1153 */
1154 map = calloc(1, sizeof (idmap_mapping));
1155 if (map == NULL) {
1156 idmapdlog(LOG_ERR, "Out of memory");
1157 result->retcode = IDMAP_ERR_MEMORY;
1158 goto out;
1159 }
1160
1161 /*
1162 * Set up to return the filled-in mapping structure.
1163 * Note that we xdr_free result on error, and that'll take
1164 * care of freeing the mapping structure.
1165 */
1166 result->mappings.mappings_val = map;
1167 result->mappings.mappings_len = 1;
1168
1169 result->retcode = copy_mapping(map, &request);
1170 if (result->retcode != IDMAP_SUCCESS)
1171 goto out;
1172
1173 /* Set up for the request to the batch API */
1174 batch_request.idmap_mapping_batch_val = map;
1175 batch_request.idmap_mapping_batch_len = 1;
1176
1177 /* Do the real work. */
1178 (void) idmap_get_mapped_ids_1_svc(batch_request,
1179 &batch_result, rqstp);
1180
1181 /* Copy what we need out of the batch response */
1182
1183 if (batch_result.retcode != IDMAP_SUCCESS) {
1184 result->retcode = batch_result.retcode;
1185 goto out;
1186 }
1187
1188 result->retcode = copy_id(&map->id2, &batch_result.ids.ids_val[0].id);
1189 if (result->retcode != IDMAP_SUCCESS)
1190 goto out;
1191
1192 map->direction = batch_result.ids.ids_val[0].direction;
1193
1194 result->retcode = batch_result.ids.ids_val[0].retcode;
1195
1196 idmap_info_mov(&map->info, &batch_result.ids.ids_val[0].info);
1197
1198 out:
1199 if (IDMAP_FATAL_ERROR(result->retcode)) {
1200 xdr_free(xdr_idmap_mappings_res, (caddr_t)result);
1201 result->mappings.mappings_len = 0;
1202 result->mappings.mappings_val = NULL;
1203 }
1204 result->retcode = idmap_stat4prot(result->retcode);
1205
1206 xdr_free(xdr_idmap_ids_res, (char *)&batch_result);
1207
1208 return (TRUE);
1209 }
1210
1211 /* ARGSUSED */
1212 bool_t
idmap_get_prop_1_svc(idmap_prop_type request,idmap_prop_res * result,struct svc_req * rqstp)1213 idmap_get_prop_1_svc(idmap_prop_type request,
1214 idmap_prop_res *result, struct svc_req *rqstp)
1215 {
1216 idmap_pg_config_t *pgcfg;
1217
1218 /* Init */
1219 (void) memset(result, 0, sizeof (*result));
1220 result->retcode = IDMAP_SUCCESS;
1221 result->value.prop = request;
1222
1223 RDLOCK_CONFIG();
1224
1225 /* Just shortcuts: */
1226 pgcfg = &_idmapdstate.cfg->pgcfg;
1227
1228
1229 switch (request) {
1230 case PROP_LIST_SIZE_LIMIT:
1231 result->value.idmap_prop_val_u.intval = pgcfg->list_size_limit;
1232 result->auto_discovered = FALSE;
1233 break;
1234 case PROP_DEFAULT_DOMAIN:
1235 result->auto_discovered = FALSE;
1236 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1237 pgcfg->default_domain);
1238 break;
1239 case PROP_DOMAIN_NAME:
1240 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1241 pgcfg->domain_name);
1242 result->auto_discovered =
1243 pgcfg->domain_name_auto_disc;
1244 break;
1245 case PROP_MACHINE_SID:
1246 result->auto_discovered = FALSE;
1247 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1248 pgcfg->machine_sid);
1249 break;
1250 case PROP_DOMAIN_CONTROLLER:
1251 if (pgcfg->domain_controller != NULL) {
1252 (void) memcpy(&result->value.idmap_prop_val_u.dsval,
1253 pgcfg->domain_controller,
1254 sizeof (idmap_ad_disc_ds_t));
1255 }
1256 result->auto_discovered = pgcfg->domain_controller_auto_disc;
1257 break;
1258 case PROP_FOREST_NAME:
1259 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1260 pgcfg->forest_name);
1261 result->auto_discovered = pgcfg->forest_name_auto_disc;
1262 break;
1263 case PROP_SITE_NAME:
1264 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1265 pgcfg->site_name);
1266 result->auto_discovered = pgcfg->site_name_auto_disc;
1267 break;
1268 case PROP_GLOBAL_CATALOG:
1269 if (pgcfg->global_catalog != NULL) {
1270 (void) memcpy(&result->value.idmap_prop_val_u.dsval,
1271 pgcfg->global_catalog, sizeof (idmap_ad_disc_ds_t));
1272 }
1273 result->auto_discovered = pgcfg->global_catalog_auto_disc;
1274 break;
1275 case PROP_AD_UNIXUSER_ATTR:
1276 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1277 pgcfg->ad_unixuser_attr);
1278 result->auto_discovered = FALSE;
1279 break;
1280 case PROP_AD_UNIXGROUP_ATTR:
1281 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1282 pgcfg->ad_unixgroup_attr);
1283 result->auto_discovered = FALSE;
1284 break;
1285 case PROP_NLDAP_WINNAME_ATTR:
1286 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1287 pgcfg->nldap_winname_attr);
1288 result->auto_discovered = FALSE;
1289 break;
1290 case PROP_DIRECTORY_BASED_MAPPING:
1291 STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
1292 enum_lookup(pgcfg->directory_based_mapping,
1293 directory_mapping_map));
1294 result->auto_discovered = FALSE;
1295 break;
1296 default:
1297 result->retcode = IDMAP_ERR_PROP_UNKNOWN;
1298 break;
1299 }
1300
1301 out:
1302 UNLOCK_CONFIG();
1303 if (IDMAP_FATAL_ERROR(result->retcode)) {
1304 xdr_free(xdr_idmap_prop_res, (caddr_t)result);
1305 result->value.prop = PROP_UNKNOWN;
1306 }
1307 result->retcode = idmap_stat4prot(result->retcode);
1308 return (TRUE);
1309 }
1310
1311 int
idmap_flush_1_svc(idmap_flush_op op,idmap_retcode * result,struct svc_req * rqstp)1312 idmap_flush_1_svc(
1313 idmap_flush_op op,
1314 idmap_retcode *result,
1315 struct svc_req *rqstp)
1316 {
1317 NOTE(ARGUNUSED(rqstp))
1318 if (verify_rules_auth(rqstp) < 0) {
1319 *result = IDMAP_ERR_PERMISSION_DENIED;
1320 return (TRUE);
1321 }
1322
1323 *result = idmap_cache_flush(op);
1324
1325 return (TRUE);
1326 }
1327
1328 /* ARGSUSED */
1329 int
idmap_prog_1_freeresult(SVCXPRT * transp,xdrproc_t xdr_result,caddr_t result)1330 idmap_prog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result,
1331 caddr_t result)
1332 {
1333 xdr_free(xdr_result, result);
1334 return (TRUE);
1335 }
1336
1337 /*
1338 * This function is called by rpc_svc.c when it encounters an error.
1339 */
1340 NOTE(PRINTFLIKE(1))
1341 void
idmap_rpc_msgout(const char * fmt,...)1342 idmap_rpc_msgout(const char *fmt, ...)
1343 {
1344 va_list va;
1345 char buf[1000];
1346
1347 va_start(va, fmt);
1348 (void) vsnprintf(buf, sizeof (buf), fmt, va);
1349 va_end(va);
1350
1351 idmapdlog(LOG_ERR, "idmap RPC: %s", buf);
1352 }
1353