1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2003 Andrew Bartlett (abartlet@samba.org)
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "includes.h"
21 #include "system/filesys.h"
22 #include "utils/net.h"
23 #include "secrets.h"
24 #include "idmap.h"
25 #include "dbwrap/dbwrap.h"
26 #include "dbwrap/dbwrap_open.h"
27 #include "../libcli/security/security.h"
28 #include "net_idmap_check.h"
29 #include "util_tdb.h"
30 #include "idmap_autorid_tdb.h"
31 
32 #define ALLOC_CHECK(mem) do { \
33 	if (!mem) { \
34 		d_fprintf(stderr, _("Out of memory!\n")); \
35 		talloc_free(ctx); \
36 		return -1; \
37 	} } while(0)
38 
39 enum idmap_dump_backend {
40 	TDB,
41 	AUTORID
42 };
43 
44 struct net_idmap_ctx {
45 	enum idmap_dump_backend backend;
46 };
47 
net_idmap_dump_one_autorid_entry(struct db_record * rec,void * unused)48 static int net_idmap_dump_one_autorid_entry(struct db_record *rec,
49 					    void *unused)
50 {
51 	TDB_DATA key;
52 	TDB_DATA value;
53 
54 	key = dbwrap_record_get_key(rec);
55 	value = dbwrap_record_get_value(rec);
56 
57 	if (strncmp((char *)key.dptr, "CONFIG", 6) == 0) {
58 		char *config = talloc_array(talloc_tos(), char, value.dsize+1);
59 		memcpy(config, value.dptr, value.dsize);
60 		config[value.dsize] = '\0';
61 		printf("CONFIG: %s\n", config);
62 		talloc_free(config);
63 		return 0;
64 	}
65 
66 	if (strncmp((char *)key.dptr, "NEXT RANGE", 10) == 0) {
67 		printf("RANGE HWM: %"PRIu32"\n", IVAL(value.dptr, 0));
68 		return 0;
69 	}
70 
71 	if (strncmp((char *)key.dptr, "NEXT ALLOC UID", 14) == 0) {
72 		printf("UID HWM: %"PRIu32"\n", IVAL(value.dptr, 0));
73 		return 0;
74 	}
75 
76 	if (strncmp((char *)key.dptr, "NEXT ALLOC GID", 14) == 0) {
77 		printf("GID HWM: %"PRIu32"\n", IVAL(value.dptr, 0));
78 		return 0;
79 	}
80 
81 	if (strncmp((char *)key.dptr, "UID", 3) == 0 ||
82 	    strncmp((char *)key.dptr, "GID", 3) == 0)
83 	{
84 		/* mapped entry from allocation pool */
85 		printf("%s %s\n", value.dptr, key.dptr);
86 		return 0;
87 	}
88 
89 	if ((strncmp((char *)key.dptr, "S-1-5-", 6) == 0 ||
90 	     strncmp((char *)key.dptr, "ALLOC", 5) == 0) &&
91 	    value.dsize == sizeof(uint32_t))
92 	{
93 		/* this is a domain range assignment */
94 		uint32_t range = IVAL(value.dptr, 0);
95 		printf("RANGE %"PRIu32": %s\n", range, key.dptr);
96 		return 0;
97 	}
98 
99 	return 0;
100 }
101 
102 /***********************************************************
103  Helper function for net_idmap_dump. Dump one entry.
104  **********************************************************/
net_idmap_dump_one_tdb_entry(struct db_record * rec,void * unused)105 static int net_idmap_dump_one_tdb_entry(struct db_record *rec,
106 					void *unused)
107 {
108 	TDB_DATA key;
109 	TDB_DATA value;
110 
111 	key = dbwrap_record_get_key(rec);
112 	value = dbwrap_record_get_value(rec);
113 
114 	if (strcmp((char *)key.dptr, "USER HWM") == 0) {
115 		printf(_("USER HWM %d\n"), IVAL(value.dptr,0));
116 		return 0;
117 	}
118 
119 	if (strcmp((char *)key.dptr, "GROUP HWM") == 0) {
120 		printf(_("GROUP HWM %d\n"), IVAL(value.dptr,0));
121 		return 0;
122 	}
123 
124 	if (strncmp((char *)key.dptr, "S-", 2) != 0) {
125 		return 0;
126 	}
127 
128 	printf("%s %s\n", value.dptr, key.dptr);
129 	return 0;
130 }
131 
132 /* returns db path for idmap backend alloced on talloc_tos */
net_idmap_dbfile(struct net_context * c,struct net_idmap_ctx * ctx)133 static char *net_idmap_dbfile(struct net_context *c,
134 			      struct net_idmap_ctx *ctx)
135 {
136 	char *dbfile = NULL;
137 	const char *backend = NULL;
138 
139 	backend = lp_idmap_default_backend();
140 	if (!backend) {
141 		d_printf(_("Internal error: 'idmap config * : backend' is not set!\n"));
142 		return NULL;
143 	}
144 
145 	if (c->opt_db != NULL) {
146 		dbfile = talloc_strdup(talloc_tos(), c->opt_db);
147 		if (dbfile == NULL) {
148 			d_fprintf(stderr, _("Out of memory!\n"));
149 		}
150 	} else if (strequal(backend, "tdb")) {
151 		dbfile = state_path(talloc_tos(), "winbindd_idmap.tdb");
152 		if (dbfile == NULL) {
153 			d_fprintf(stderr, _("Out of memory!\n"));
154 		}
155 		ctx->backend = TDB;
156 	} else if (strequal(backend, "tdb2")) {
157 		dbfile = talloc_asprintf(talloc_tos(), "%s/idmap2.tdb",
158 					 lp_private_dir());
159 		if (dbfile == NULL) {
160 			d_fprintf(stderr, _("Out of memory!\n"));
161 		}
162 		ctx->backend = TDB;
163 	} else if (strequal(backend, "autorid")) {
164 		dbfile = state_path(talloc_tos(), "autorid.tdb");
165 		if (dbfile == NULL) {
166 			d_fprintf(stderr, _("Out of memory!\n"));
167 		}
168 		ctx->backend = AUTORID;
169 	} else {
170 		char *_backend = talloc_strdup(talloc_tos(), backend);
171 		char* args = strchr(_backend, ':');
172 		if (args != NULL) {
173 			*args = '\0';
174 		}
175 
176 		d_printf(_("Sorry, 'idmap backend = %s' is currently not supported\n"),
177 			   _backend);
178 
179 		talloc_free(_backend);
180 	}
181 
182 	return dbfile;
183 }
184 
net_idmap_opendb_autorid(TALLOC_CTX * mem_ctx,struct net_context * c,bool readonly,struct db_context ** db)185 static bool net_idmap_opendb_autorid(TALLOC_CTX *mem_ctx,
186 				     struct net_context *c,
187 				     bool readonly,
188 				     struct db_context **db)
189 {
190 	bool ret = false;
191 	char *dbfile = NULL;
192 	struct net_idmap_ctx ctx = { .backend = AUTORID };
193 
194 	if (c == NULL) {
195 		goto done;
196 	}
197 
198 	dbfile = net_idmap_dbfile(c, &ctx);
199 	if (dbfile == NULL) {
200 		goto done;
201 	}
202 
203 	if (ctx.backend != AUTORID) {
204 		d_fprintf(stderr, _("Unsupported backend\n"));
205 		goto done;
206 	}
207 
208 	if (readonly) {
209 		*db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDONLY, 0,
210 			     DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
211 		if (*db == NULL) {
212 			d_fprintf(stderr,
213 				  _("Could not open autorid db (%s): %s\n"),
214 				 dbfile, strerror(errno));
215 			goto done;
216 		}
217 	} else {
218 		NTSTATUS status;
219 		status = idmap_autorid_db_init(dbfile, mem_ctx, db);
220 		if (!NT_STATUS_IS_OK(status)) {
221 			d_fprintf(stderr,
222 				_("Error calling idmap_autorid_db_init: %s\n"),
223 				nt_errstr(status));
224 			goto done;
225 		}
226 	}
227 
228 	ret = true;
229 
230 done:
231 	talloc_free(dbfile);
232 	return ret;
233 }
234 
235 
236 /***********************************************************
237  Dump the current idmap
238  **********************************************************/
net_idmap_dump(struct net_context * c,int argc,const char ** argv)239 static int net_idmap_dump(struct net_context *c, int argc, const char **argv)
240 {
241 	struct db_context *db;
242 	TALLOC_CTX *mem_ctx;
243 	const char* dbfile;
244 	NTSTATUS status;
245 	int ret = -1;
246 	struct net_idmap_ctx ctx = { .backend = TDB };
247 
248 	if ( argc > 1  || c->display_usage) {
249 		d_printf("%s\n%s",
250 			 _("Usage:"),
251 			 _("net idmap dump [[--db=]<inputfile>]\n"
252 			   "  Dump current ID mapping.\n"
253 			   "    inputfile\tTDB file to read mappings from.\n"));
254 		return c->display_usage?0:-1;
255 	}
256 
257 	mem_ctx = talloc_stackframe();
258 
259 	dbfile = (argc > 0) ? argv[0] : net_idmap_dbfile(c, &ctx);
260 	if (dbfile == NULL) {
261 		goto done;
262 	}
263 	d_fprintf(stderr, _("dumping id mapping from %s\n"), dbfile);
264 
265 	db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDONLY, 0,
266 		     DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
267 	if (db == NULL) {
268 		d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
269 			  dbfile, strerror(errno));
270 		goto done;
271 	}
272 
273 	if (ctx.backend == AUTORID) {
274 		status = dbwrap_traverse_read(db,
275 					      net_idmap_dump_one_autorid_entry,
276 					      NULL, NULL);
277 	} else {
278 		status = dbwrap_traverse_read(db,
279 					      net_idmap_dump_one_tdb_entry,
280 					      NULL, NULL);
281 	}
282 	if (!NT_STATUS_IS_OK(status)) {
283 		d_fprintf(stderr, _("error traversing the database\n"));
284 		ret = -1;
285 		goto done;
286 	}
287 
288 	ret = 0;
289 
290 done:
291 	talloc_free(mem_ctx);
292 	return ret;
293 }
294 
295 /***********************************************************
296  Write entries from stdin to current local idmap
297  **********************************************************/
298 
net_idmap_store_id_mapping(struct db_context * db,enum id_type type,unsigned long idval,const char * sid_string)299 static int net_idmap_store_id_mapping(struct db_context *db,
300 				      enum id_type type,
301 				      unsigned long idval,
302 				      const char *sid_string)
303 {
304 	NTSTATUS status;
305 	char *idstr = NULL;
306 
307 	switch(type) {
308 	case ID_TYPE_UID:
309 		idstr = talloc_asprintf(talloc_tos(), "UID %lu", idval);
310 		break;
311 	case ID_TYPE_GID:
312 		idstr = talloc_asprintf(talloc_tos(), "GID %lu", idval);
313 		break;
314 	default:
315 		d_fprintf(stderr, "Invalid id mapping type: %d\n", type);
316 		return -1;
317 	}
318 
319 	status = dbwrap_store_bystring(db, idstr,
320 				       string_term_tdb_data(sid_string),
321 				       TDB_REPLACE);
322 	if (!NT_STATUS_IS_OK(status)) {
323 		d_fprintf(stderr, "Error storing ID -> SID: "
324 			 "%s\n", nt_errstr(status));
325 		talloc_free(idstr);
326 		return -1;
327 	}
328 	status = dbwrap_store_bystring(db, sid_string,
329 				       string_term_tdb_data(idstr),
330 				       TDB_REPLACE);
331 	if (!NT_STATUS_IS_OK(status)) {
332 		d_fprintf(stderr, "Error storing SID -> ID: "
333 			 "%s\n", nt_errstr(status));
334 		talloc_free(idstr);
335 		return -1;
336 	}
337 
338 	return 0;
339 }
340 
net_idmap_restore(struct net_context * c,int argc,const char ** argv)341 static int net_idmap_restore(struct net_context *c, int argc, const char **argv)
342 {
343 	TALLOC_CTX *mem_ctx;
344 	FILE *input = NULL;
345 	struct db_context *db;
346 	const char *dbfile = NULL;
347 	int ret = 0;
348 	struct net_idmap_ctx ctx = { .backend = TDB };
349 
350 	if (c->display_usage) {
351 		d_printf("%s\n%s",
352 			 _("Usage:"),
353 			 _("net idmap restore [--db=<TDB>] [<inputfile>]\n"
354 			   "  Restore ID mappings from file\n"
355 			   "    TDB\tFile to store ID mappings to."
356 			   "    inputfile\tFile to load ID mappings from. If not "
357 			   "given, load data from stdin.\n"));
358 		return 0;
359 	}
360 
361 	mem_ctx = talloc_stackframe();
362 
363 	dbfile = net_idmap_dbfile(c, &ctx);
364 
365 	if (dbfile == NULL) {
366 		ret = -1;
367 		goto done;
368 	}
369 
370 	if (ctx.backend != TDB) {
371 		d_fprintf(stderr, _("Sorry, restoring of non-TDB databases is "
372 				    "currently not supported\n"));
373 		ret = -1;
374 		goto done;
375 	}
376 
377 	d_fprintf(stderr, _("restoring id mapping to %s\n"), dbfile);
378 
379 	if (argc == 1) {
380 		input = fopen(argv[0], "r");
381 		if (input == NULL) {
382 			d_fprintf(stderr, _("Could not open input file (%s): %s\n"),
383 				  argv[0], strerror(errno));
384 			ret = -1;
385 			goto done;
386 		}
387 	} else {
388 		input = stdin;
389 	}
390 
391 	db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644,
392 		     DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
393 	if (db == NULL) {
394 		d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
395 			  dbfile, strerror(errno));
396 		ret = -1;
397 		goto done;
398 	}
399 
400 	if (dbwrap_transaction_start(db) != 0) {
401 		d_fprintf(stderr, _("Failed to start transaction.\n"));
402 		ret = -1;
403 		goto done;
404 	}
405 
406 	while (!feof(input)) {
407 		char line[128], sid_string[128];
408 		int len;
409 		unsigned long idval;
410 		NTSTATUS status;
411 
412 		if (fgets(line, 127, input) == NULL)
413 			break;
414 
415 		len = strlen(line);
416 
417 		if ( (len > 0) && (line[len-1] == '\n') )
418 			line[len-1] = '\0';
419 
420 		if (sscanf(line, "GID %lu %127s", &idval, sid_string) == 2)
421 		{
422 			ret = net_idmap_store_id_mapping(db, ID_TYPE_GID,
423 							 idval, sid_string);
424 			if (ret != 0) {
425 				break;
426 			}
427 		} else if (sscanf(line, "UID %lu %127s", &idval, sid_string) == 2)
428 		{
429 			ret = net_idmap_store_id_mapping(db, ID_TYPE_UID,
430 							 idval, sid_string);
431 			if (ret != 0) {
432 				break;
433 			}
434 		} else if (sscanf(line, "USER HWM %lu", &idval) == 1) {
435 			status = dbwrap_store_int32_bystring(
436 				db, "USER HWM", idval);
437 			if (!NT_STATUS_IS_OK(status)) {
438 				d_fprintf(stderr,
439 					  _("Could not store USER HWM: %s\n"),
440 					  nt_errstr(status));
441 				break;
442 			}
443 		} else if (sscanf(line, "GROUP HWM %lu", &idval) == 1) {
444 			status = dbwrap_store_int32_bystring(
445 				db, "GROUP HWM", idval);
446 			if (!NT_STATUS_IS_OK(status)) {
447 				d_fprintf(stderr,
448 					  _("Could not store GROUP HWM: %s\n"),
449 					  nt_errstr(status));
450 				break;
451 			}
452 		} else {
453 			d_fprintf(stderr, _("ignoring invalid line [%s]\n"),
454 				  line);
455 			continue;
456 		}
457 	}
458 
459 	if (ret == 0) {
460 		if(dbwrap_transaction_commit(db) != 0) {
461 			d_fprintf(stderr, _("Failed to commit transaction.\n"));
462 			ret = -1;
463 		}
464 	} else {
465 		if (dbwrap_transaction_cancel(db) != 0) {
466 			d_fprintf(stderr, _("Failed to cancel transaction.\n"));
467 		}
468 	}
469 
470 done:
471 	if ((input != NULL) && (input != stdin)) {
472 		fclose(input);
473 	}
474 
475 	talloc_free(mem_ctx);
476 	return ret;
477 }
478 
479 static
dbwrap_delete_mapping(struct db_context * db,TDB_DATA key1,bool force)480 NTSTATUS dbwrap_delete_mapping(struct db_context *db, TDB_DATA key1, bool force)
481 {
482 	TALLOC_CTX *mem_ctx = talloc_stackframe();
483 	bool is_valid_mapping;
484 	NTSTATUS status = NT_STATUS_OK;
485 	TDB_DATA val1, val2;
486 
487 	ZERO_STRUCT(val1);
488 	ZERO_STRUCT(val2);
489 
490 	status = dbwrap_fetch(db, mem_ctx, key1, &val1);
491 	if (!NT_STATUS_IS_OK(status)) {
492 		DEBUG(1, ("failed to fetch: %.*s\n", (int)key1.dsize, key1.dptr));
493 		goto done;
494 	}
495 
496 	if (val1.dptr == NULL) {
497 		DEBUG(1, ("invalid mapping: %.*s -> empty value\n",
498 			  (int)key1.dsize, key1.dptr));
499 		status = NT_STATUS_FILE_INVALID;
500 		goto done;
501 	}
502 
503 	DEBUG(2, ("mapping: %.*s -> %.*s\n",
504 		  (int)key1.dsize, key1.dptr, (int)val1.dsize, val1.dptr));
505 
506 	status = dbwrap_fetch(db, mem_ctx, val1, &val2);
507 	if (!NT_STATUS_IS_OK(status)) {
508 		DEBUG(1, ("failed to fetch: %.*s\n", (int)val1.dsize, val1.dptr));
509 		goto done;
510 	}
511 
512 	is_valid_mapping = tdb_data_equal(key1, val2);
513 
514 	if (!is_valid_mapping) {
515 		DEBUG(1, ("invalid mapping: %.*s -> %.*s -> %.*s\n",
516 			  (int)key1.dsize, key1.dptr,
517 			  (int)val1.dsize, val1.dptr,
518 			  (int)val2.dsize, val2.dptr));
519 		if ( !force ) {
520 			status = NT_STATUS_FILE_INVALID;
521 			goto done;
522 		}
523 	}
524 
525 	status = dbwrap_delete(db, key1);
526 	if (!NT_STATUS_IS_OK(status)) {
527 		DEBUG(1, ("failed to delete: %.*s\n", (int)key1.dsize, key1.dptr));
528 		goto done;
529 	}
530 
531 	if (!is_valid_mapping) {
532 		goto done;
533 	}
534 
535 	status = dbwrap_delete(db, val1);
536 	if (!NT_STATUS_IS_OK(status)) {
537 		DEBUG(1, ("failed to delete: %.*s\n", (int)val1.dsize, val1.dptr));
538 	}
539 
540 done:
541 	talloc_free(mem_ctx);
542 	return status;
543 }
544 
545 static
delete_mapping_action(struct db_context * db,void * data)546 NTSTATUS delete_mapping_action(struct db_context *db, void* data)
547 {
548 	return dbwrap_delete_mapping(db, *(TDB_DATA*)data, false);
549 }
550 static
delete_mapping_action_force(struct db_context * db,void * data)551 NTSTATUS delete_mapping_action_force(struct db_context *db, void* data)
552 {
553 	return dbwrap_delete_mapping(db, *(TDB_DATA*)data, true);
554 }
555 
556 /***********************************************************
557  Delete a SID mapping from a winbindd_idmap.tdb
558  **********************************************************/
delete_args_ok(int argc,const char ** argv)559 static bool delete_args_ok(int argc, const char **argv)
560 {
561 	if (argc != 1)
562 		return false;
563 	if (strncmp(argv[0], "S-", 2) == 0)
564 		return true;
565 	if (strncmp(argv[0], "GID ", 4) == 0)
566 		return true;
567 	if (strncmp(argv[0], "UID ", 4) == 0)
568 		return true;
569 	return false;
570 }
571 
net_idmap_delete_mapping(struct net_context * c,int argc,const char ** argv)572 static int net_idmap_delete_mapping(struct net_context *c, int argc,
573 				    const char **argv)
574 {
575 	int ret = -1;
576 	struct db_context *db;
577 	TALLOC_CTX *mem_ctx;
578 	TDB_DATA key;
579 	NTSTATUS status;
580 	const char* dbfile;
581 	struct net_idmap_ctx ctx = { .backend = TDB };
582 
583 	if ( !delete_args_ok(argc,argv) || c->display_usage) {
584 		d_printf("%s\n%s",
585 			 _("Usage:"),
586 			 _("net idmap delete mapping [-f] [--db=<TDB>] <ID>\n"
587 			   "  Delete mapping of ID from TDB.\n"
588 			   "    -f\tforce\n"
589 			   "    TDB\tidmap database\n"
590 			   "    ID\tSID|GID|UID\n"));
591 		return c->display_usage ? 0 : -1;
592 	}
593 
594 	mem_ctx = talloc_stackframe();
595 
596 	dbfile = net_idmap_dbfile(c, &ctx);
597 	if (dbfile == NULL) {
598 		goto done;
599 	}
600 	d_fprintf(stderr, _("deleting id mapping from %s\n"), dbfile);
601 
602 	db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR, 0,
603 		     DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
604 	if (db == NULL) {
605 		d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
606 			  dbfile, strerror(errno));
607 		goto done;
608 	}
609 
610 	key = string_term_tdb_data(argv[0]);
611 
612 	status = dbwrap_trans_do(db, (c->opt_force
613 				      ? delete_mapping_action_force
614 				      : delete_mapping_action),  &key);
615 
616 	if (!NT_STATUS_IS_OK(status)) {
617 		d_fprintf(stderr, _("could not delete mapping: %s\n"),
618 			  nt_errstr(status));
619 		goto done;
620 	}
621 	ret = 0;
622 done:
623 	talloc_free(mem_ctx);
624 	return ret;
625 }
626 
parse_uint32(const char * str,uint32_t * result)627 static bool parse_uint32(const char *str, uint32_t *result)
628 {
629 	unsigned long val;
630 	int error = 0;
631 
632 	val = smb_strtoul(str, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
633 	if (error != 0) {
634 		return false;
635 	}
636 
637 	*result = val;		/* Potential crop */
638 	return true;
639 }
640 
net_idmap_autorid_delete_range_usage(void)641 static void net_idmap_autorid_delete_range_usage(void)
642 {
643 	d_printf("%s\n%s",
644 		 _("Usage:"),
645 		 _("net idmap delete range [-f] [--db=<TDB>] <RANGE>|(<SID>[ <INDEX>])\n"
646 		   "  Delete a domain range mapping from the database.\n"
647 		   "    -f\tforce\n"
648 		   "    TDB\tidmap database\n"
649 		   "    RANGE\tthe range number to delete\n"
650 		   "    SID\t\tSID of the domain\n"
651 		   "    INDEX\trange index number do delete for the domain\n"));
652 }
653 
net_idmap_autorid_delete_range(struct net_context * c,int argc,const char ** argv)654 static int net_idmap_autorid_delete_range(struct net_context *c, int argc,
655 					  const char **argv)
656 {
657 	int ret = -1;
658 	struct db_context *db = NULL;
659 	NTSTATUS status;
660 	uint32_t rangenum;
661 	uint32_t range_index;
662 	const char *domsid;
663 	TALLOC_CTX *mem_ctx = NULL;
664 	bool ok;
665 	bool force = (c->opt_force != 0);
666 
667 	if (c->display_usage) {
668 		net_idmap_autorid_delete_range_usage();
669 		return 0;
670 	}
671 
672 	if (argc < 1 || argc > 2) {
673 		net_idmap_autorid_delete_range_usage();
674 		return -1;
675 	}
676 
677 	mem_ctx = talloc_stackframe();
678 	if (!net_idmap_opendb_autorid(mem_ctx, c, false, &db)) {
679 		goto done;
680 	}
681 
682 	ok = parse_uint32(argv[0], &rangenum);
683 	if (ok) {
684 		d_printf("%s: %"PRIu32"\n", _("Deleting range number"),
685 			 rangenum);
686 
687 		status = idmap_autorid_delete_range_by_num(db, rangenum,
688 							   force);
689 		if (!NT_STATUS_IS_OK(status)) {
690 			d_fprintf(stderr, "%s: %s\n",
691 				  _("Failed to delete domain range mapping"),
692 				  nt_errstr(status));
693 		} else {
694 			ret = 0;
695 		}
696 
697 		goto done;
698 	}
699 
700 	domsid = argv[0];
701 	range_index = 0;
702 
703 	if (argc == 2) {
704 		ok = parse_uint32(argv[1], &range_index);
705 		if (!ok) {
706 			d_printf("%s: %s\n",
707 				 _("Invalid index specification"), argv[1]);
708 			net_idmap_autorid_delete_range_usage();
709 			goto done;
710 		}
711 	}
712 
713 	status = idmap_autorid_delete_range_by_sid(db, domsid, range_index,
714 						   force);
715 	if (!NT_STATUS_IS_OK(status)) {
716 		d_fprintf(stderr, "%s: %s\n",
717 			  _("Failed to delete domain range mapping"),
718 			  nt_errstr(status));
719 		goto done;
720 	}
721 
722 	ret = 0;
723 
724 done:
725 	talloc_free(mem_ctx);
726 	return ret;
727 }
728 
net_idmap_autorid_delete_ranges_usage(void)729 static void net_idmap_autorid_delete_ranges_usage(void)
730 {
731 	d_printf("%s\n%s",
732 		 _("Usage:"),
733 		 _("net idmap delete ranges [-f] [--db=<TDB>] <SID>\n"
734 		   "  Delete all domain range mappings for a given domain.\n"
735 		   "    -f\tforce\n"
736 		   "    TDB\tidmap database\n"
737 		   "    SID\t\tSID of the domain\n"));
738 }
739 
net_idmap_autorid_delete_ranges(struct net_context * c,int argc,const char ** argv)740 static int net_idmap_autorid_delete_ranges(struct net_context *c, int argc,
741 					   const char **argv)
742 {
743 	int ret = -1;
744 	struct db_context *db = NULL;
745 	NTSTATUS status;
746 	const char *domsid;
747 	TALLOC_CTX *mem_ctx = NULL;
748 	bool force = (c->opt_force != 0);
749 	int count = 0;
750 
751 	if (c->display_usage) {
752 		net_idmap_autorid_delete_ranges_usage();
753 		return 0;
754 	}
755 
756 	if (argc != 1) {
757 		net_idmap_autorid_delete_ranges_usage();
758 		return -1;
759 	}
760 
761 	domsid = argv[0];
762 
763 	mem_ctx = talloc_stackframe();
764 	if (!net_idmap_opendb_autorid(mem_ctx, c, false, &db)) {
765 		goto done;
766 	}
767 
768 	status = idmap_autorid_delete_domain_ranges(db, domsid, force, &count);
769 	if (!NT_STATUS_IS_OK(status)) {
770 		d_fprintf(stderr, "%s %s: %s\n",
771 			  _("Failed to delete domain range mappings for "
772 			    "domain"),
773 			  domsid,
774 			  nt_errstr(status));
775 		goto done;
776 	}
777 
778 	d_printf(_("deleted %d domain mappings\n"), count);
779 
780 	ret = 0;
781 
782 done:
783 	talloc_free(mem_ctx);
784 	return ret;
785 }
786 
net_idmap_delete(struct net_context * c,int argc,const char ** argv)787 static int net_idmap_delete(struct net_context *c, int argc, const char **argv)
788 {
789 	struct functable func[] = {
790 		{
791 			"mapping",
792 			net_idmap_delete_mapping,
793 			NET_TRANSPORT_LOCAL,
794 			N_("Delete ID mapping"),
795 			N_("net idmap delete mapping <ID>\n"
796 			   "  Delete ID mapping")
797 		},
798 		{
799 			"range",
800 			net_idmap_autorid_delete_range,
801 			NET_TRANSPORT_LOCAL,
802 			N_("Delete a domain range mapping"),
803 			N_("net idmap delete range <RANGE>|(<SID>[ <INDEX>])\n"
804 			   "  Delete a domain range mapping")
805 		},
806 		{
807 			"ranges",
808 			net_idmap_autorid_delete_ranges,
809 			NET_TRANSPORT_LOCAL,
810 			N_("Delete all domain range mappings for a given "
811 			   "domain"),
812 			N_("net idmap delete ranges <SID>\n"
813 			   "  Delete a domain range mapping")
814 		},
815 		{NULL, NULL, 0, NULL, NULL}
816 	};
817 
818 	return net_run_function(c, argc, argv, "net idmap delete", func);
819 }
820 
821 
net_idmap_set_mapping(struct net_context * c,int argc,const char ** argv)822 static int net_idmap_set_mapping(struct net_context *c,
823 				 int argc, const char **argv)
824 {
825 	d_printf("%s\n", _("Not implemented yet"));
826 	return -1;
827 }
828 
net_idmap_autorid_set_range_usage(void)829 static void net_idmap_autorid_set_range_usage(void)
830 {
831 	d_printf("%s\n%s",
832 		 _("Usage:"),
833 		 _("net idmap set range"
834 		   " <range> <SID> [<index>] [--db=<inputfile>]\n"
835 		   "  Store a domain-range mapping for a given domain.\n"
836 		   "    range\tRange number to be set for the domain\n"
837 		   "    SID\t\tSID of the domain\n"
838 		   "    index\trange-index number to be set for the domain\n"
839 		   "    inputfile\tTDB file to add mapping to.\n"));
840 }
841 
net_idmap_autorid_set_range(struct net_context * c,int argc,const char ** argv)842 static int net_idmap_autorid_set_range(struct net_context *c,
843 				       int argc, const char **argv)
844 {
845 	int ret = -1;
846 	TALLOC_CTX *mem_ctx;
847 	struct db_context *db = NULL;
848 	const char *domsid;
849 	uint32_t rangenum;
850 	uint32_t range_index = 0;
851 	NTSTATUS status;
852 	bool ok;
853 
854 	if (c->display_usage) {
855 		net_idmap_autorid_set_range_usage();
856 		return 0;
857 	}
858 
859 	if (argc < 2  || argc > 3) {
860 		net_idmap_autorid_set_range_usage();
861 		return -1;
862 	}
863 
864 	ok = parse_uint32(argv[0], &rangenum);
865 	if (!ok) {
866 		d_printf("%s: %s\n", _("Invalid range specification"),
867 			 argv[0]);
868 		net_idmap_autorid_set_range_usage();
869 		return -1;
870 	}
871 
872 	domsid = argv[1];
873 
874 	if (argc == 3) {
875 		ok = parse_uint32(argv[2], &range_index);
876 		if (!ok) {
877 			d_printf("%s: %s\n",
878 				 _("Invalid index specification"), argv[2]);
879 			net_idmap_autorid_set_range_usage();
880 			return -1;
881 		}
882 	}
883 
884 	mem_ctx = talloc_stackframe();
885 	if (!net_idmap_opendb_autorid(mem_ctx, c, false, &db)) {
886 		goto done;
887 	}
888 
889 	status = idmap_autorid_setrange(db, domsid, range_index, rangenum);
890 	if (!NT_STATUS_IS_OK(status)) {
891 		d_fprintf(stderr, "%s: %s\n",
892 			  _("Failed to save domain mapping"),
893 			  nt_errstr(status));
894 		goto done;
895 	}
896 
897 	ret = 0;
898 
899 done:
900 	TALLOC_FREE(mem_ctx);
901 	return ret;
902 }
903 
idmap_store_secret(const char * backend,const char * domain,const char * identity,const char * secret)904 static bool idmap_store_secret(const char *backend,
905 			       const char *domain,
906 			       const char *identity,
907 			       const char *secret)
908 {
909 	char *tmp;
910 	int r;
911 	bool ret;
912 
913 	r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
914 
915 	if (r < 0) return false;
916 
917 	/* make sure the key is case insensitive */
918 	if (!strupper_m(tmp)) {
919 		free(tmp);
920 		return false;
921 	}
922 	ret = secrets_store_generic(tmp, identity, secret);
923 
924 	free(tmp);
925 	return ret;
926 }
927 
928 
net_idmap_secret(struct net_context * c,int argc,const char ** argv)929 static int net_idmap_secret(struct net_context *c, int argc, const char **argv)
930 {
931 	TALLOC_CTX *ctx;
932 	const char *secret;
933 	const char *dn;
934 	char *domain;
935 	char *backend;
936 	char *opt = NULL;
937 	bool ret;
938 
939 	if (argc != 2 || c->display_usage) {
940 		d_printf("%s\n%s",
941 			 _("Usage:\n"),
942 			 _("net idmap set secret <DOMAIN> <secret>\n"
943 			   "  Set the secret for the specified domain\n"
944 			   "    DOMAIN\tDomain to set secret for.\n"
945 			   "    secret\tNew secret to set.\n"));
946 		return c->display_usage?0:-1;
947 	}
948 
949 	secret = argv[1];
950 
951 	ctx = talloc_new(NULL);
952 	ALLOC_CHECK(ctx);
953 
954 	domain = talloc_strdup(ctx, argv[0]);
955 	ALLOC_CHECK(domain);
956 
957 	opt = talloc_asprintf(ctx, "idmap config %s", domain);
958 	ALLOC_CHECK(opt);
959 
960 	backend = talloc_strdup(ctx, lp_parm_const_string(-1, opt, "backend", "tdb"));
961 	ALLOC_CHECK(backend);
962 
963 	if ((!backend) || (!strequal(backend, "ldap") &&
964 			   !strequal(backend, "rfc2307"))) {
965 		d_fprintf(stderr,
966 			  _("The only currently supported backend are LDAP "
967 			    "and rfc2307\n"));
968 		talloc_free(ctx);
969 		return -1;
970 	}
971 
972 	dn = lp_parm_const_string(-1, opt, "ldap_user_dn", NULL);
973 	if ( ! dn) {
974 		d_fprintf(stderr,
975 			  _("Missing ldap_user_dn option for domain %s\n"),
976 			  domain);
977 		talloc_free(ctx);
978 		return -1;
979 	}
980 
981 	ret = idmap_store_secret("ldap", domain, dn, secret);
982 
983 	if ( ! ret) {
984 		d_fprintf(stderr, _("Failed to store secret\n"));
985 		talloc_free(ctx);
986 		return -1;
987 	}
988 
989 	d_printf(_("Secret stored\n"));
990 	return 0;
991 }
992 
net_idmap_autorid_set_config(struct net_context * c,int argc,const char ** argv)993 static int net_idmap_autorid_set_config(struct net_context *c,
994 					int argc, const char **argv)
995 {
996 	int ret = -1;
997 	NTSTATUS status;
998 	TALLOC_CTX *mem_ctx;
999 	struct db_context *db = NULL;
1000 
1001 	if (argc != 1 || c->display_usage) {
1002 		d_printf("%s\n%s",
1003 			 _("Usage:"),
1004 			 _("net idmap set config <config>"
1005 			   " [--db=<inputfile>]\n"
1006 			   " Update CONFIG entry in autorid.\n"
1007 			   "	config\tConfig string to be stored\n"
1008 			   "	inputfile\tTDB file to update config.\n"));
1009 		return c->display_usage ? 0 : -1;
1010 	}
1011 
1012 	mem_ctx = talloc_stackframe();
1013 
1014 	if (!net_idmap_opendb_autorid(mem_ctx, c, false, &db)) {
1015 		goto done;
1016 	}
1017 
1018 	status = idmap_autorid_saveconfigstr(db, argv[0]);
1019 	if (!NT_STATUS_IS_OK(status)) {
1020 		printf("Error storing the config in the database: %s\n",
1021 		       nt_errstr(status));
1022 		goto done;
1023 	}
1024 
1025 	ret = 0;
1026 
1027 done:
1028 	TALLOC_FREE(mem_ctx);
1029 	return ret;
1030 }
1031 
net_idmap_set(struct net_context * c,int argc,const char ** argv)1032 static int net_idmap_set(struct net_context *c, int argc, const char **argv)
1033 {
1034 	struct functable func[] = {
1035 		{
1036 			"mapping",
1037 			net_idmap_set_mapping,
1038 			NET_TRANSPORT_LOCAL,
1039 			N_("Not implemented yet"),
1040 			N_("net idmap set mapping\n"
1041 			   "  Not implemented yet")
1042 		},
1043 		{
1044 			"range",
1045 			net_idmap_autorid_set_range,
1046 			NET_TRANSPORT_LOCAL,
1047 			N_("Store a domain-range mapping"),
1048 			N_("net idmap set range\n"
1049 			   "  Store a domain-range mapping")
1050 		},
1051 		{
1052 			"config",
1053 			net_idmap_autorid_set_config,
1054 			NET_TRANSPORT_LOCAL,
1055 			N_("Save the global configuration in the autorid database"),
1056 			N_("net idmap set config \n"
1057 			   "  Save the global configuration in the autorid database ")
1058 		},
1059 		{
1060 			"secret",
1061 			net_idmap_secret,
1062 			NET_TRANSPORT_LOCAL,
1063 			N_("Set secret for specified domain"),
1064 			N_("net idmap set secret <DOMAIN> <secret>\n"
1065 			   "  Set secret for specified domain")
1066 		},
1067 		{NULL, NULL, 0, NULL, NULL}
1068 	};
1069 
1070 	return net_run_function(c, argc, argv, "net idmap set", func);
1071 }
1072 
net_idmap_autorid_get_range_usage(void)1073 static void net_idmap_autorid_get_range_usage(void)
1074 {
1075 	d_printf("%s\n%s",
1076 		 _("Usage:"),
1077 		 _("net idmap get range <SID> [<index>] [--db=<inputfile>]\n"
1078 		   "  Get the range for a given domain and index.\n"
1079 		   "    SID\t\tSID of the domain\n"
1080 		   "    index\trange-index number to be retrieved\n"
1081 		   "    inputfile\tTDB file to add mapping to.\n"));
1082 }
1083 
1084 
net_idmap_autorid_get_range(struct net_context * c,int argc,const char ** argv)1085 static int net_idmap_autorid_get_range(struct net_context *c, int argc,
1086 				       const char **argv)
1087 {
1088 	int ret = -1;
1089 	TALLOC_CTX *mem_ctx;
1090 	struct db_context *db = NULL;
1091 	const char *domsid;
1092 	uint32_t rangenum;
1093 	uint32_t range_index = 0;
1094 	uint32_t low_id;
1095 	NTSTATUS status;
1096 	char *keystr;
1097 	bool ok;
1098 
1099 	if (c->display_usage) {
1100 		net_idmap_autorid_get_range_usage();
1101 		return 0;
1102 	}
1103 
1104 	if (argc < 1  || argc > 2) {
1105 		net_idmap_autorid_get_range_usage();
1106 		return -1;
1107 	}
1108 
1109 	domsid = argv[0];
1110 
1111 	if (argc == 2) {
1112 		ok = parse_uint32(argv[1], &range_index);
1113 		if (!ok) {
1114 			d_printf("%s: %s\n",
1115 				 _("Invalid index specification"), argv[1]);
1116 			net_idmap_autorid_get_range_usage();
1117 			return -1;
1118 		}
1119 	}
1120 
1121 	mem_ctx = talloc_stackframe();
1122 	if (!net_idmap_opendb_autorid(mem_ctx, c, true, &db)) {
1123 		goto done;
1124 	}
1125 
1126 	status = idmap_autorid_getrange(db, domsid, range_index, &rangenum,
1127 					&low_id);
1128 	if (!NT_STATUS_IS_OK(status)) {
1129 		d_fprintf(stderr, "%s: %s\n",
1130 			  _("Failed to load domain range"), nt_errstr(status));
1131 		goto done;
1132 	}
1133 
1134 	if (range_index == 0) {
1135 		keystr = talloc_strdup(mem_ctx, domsid);
1136 	} else {
1137 		keystr = talloc_asprintf(mem_ctx, "%s#%"PRIu32, domsid,
1138 					 range_index);
1139 	}
1140 
1141 	printf("RANGE %"PRIu32": %s (low id: %"PRIu32")\n",
1142 	       rangenum, keystr, low_id);
1143 
1144 	ret = 0;
1145 
1146 done:
1147 	TALLOC_FREE(mem_ctx);
1148 	return ret;
1149 }
1150 
net_idmap_autorid_print_range(struct db_context * db,const char * domsid,uint32_t range_index,uint32_t rangenum,void * private_data)1151 static NTSTATUS net_idmap_autorid_print_range(struct db_context *db,
1152 					      const char *domsid,
1153 					      uint32_t range_index,
1154 					      uint32_t rangenum,
1155 					      void *private_data)
1156 {
1157 	if (range_index == 0) {
1158 		printf("RANGE %"PRIu32": %s\n", rangenum, domsid);
1159 	} else {
1160 		printf("RANGE %"PRIu32": %s#%"PRIu32"\n", rangenum, domsid,
1161 		       range_index);
1162 	}
1163 
1164 	return NT_STATUS_OK;
1165 }
1166 
net_idmap_autorid_get_ranges_usage(void)1167 static void net_idmap_autorid_get_ranges_usage(void)
1168 {
1169 	d_printf("%s\n%s",
1170 		 _("Usage:"),
1171 		 _("net idmap get ranges [<SID>] [--db=<inputfile>]\n"
1172 		   "  Get all ranges for a given domain.\n"
1173 		   "    SID\t\tSID of the domain - list all ranges if omitted\n"
1174 		   "    inputfile\tTDB file to add mapping to.\n"));
1175 }
1176 
net_idmap_autorid_get_ranges(struct net_context * c,int argc,const char ** argv)1177 static int net_idmap_autorid_get_ranges(struct net_context *c, int argc,
1178 					const char **argv)
1179 {
1180 	int ret = -1;
1181 	TALLOC_CTX *mem_ctx;
1182 	struct db_context *db = NULL;
1183 	const char *domsid;
1184 	NTSTATUS status;
1185 
1186 	if (c->display_usage) {
1187 		net_idmap_autorid_get_ranges_usage();
1188 		return 0;
1189 	}
1190 
1191 	if (argc == 0) {
1192 		domsid = NULL;
1193 	} else if (argc == 1) {
1194 		domsid = argv[0];
1195 	} else {
1196 		net_idmap_autorid_get_ranges_usage();
1197 		return -1;
1198 	}
1199 
1200 	mem_ctx = talloc_stackframe();
1201 	if (!net_idmap_opendb_autorid(mem_ctx, c, true, &db)) {
1202 		goto done;
1203 	}
1204 
1205 	status = idmap_autorid_iterate_domain_ranges_read(db,
1206 						domsid,
1207 						net_idmap_autorid_print_range,
1208 						NULL, /* private_data */
1209 						NULL  /* count */);
1210 	if (!NT_STATUS_IS_OK(status)) {
1211 		d_fprintf(stderr, "%s: %s\n",
1212 			  _("Error getting domain ranges"), nt_errstr(status));
1213 		goto done;
1214 	}
1215 
1216 	ret = 0;
1217 
1218 done:
1219 	talloc_free(mem_ctx);
1220 	return ret;
1221 }
1222 
net_idmap_autorid_get_config(struct net_context * c,int argc,const char ** argv)1223 static int net_idmap_autorid_get_config(struct net_context *c, int argc,
1224 					const char **argv)
1225 {
1226 	int ret = -1;
1227 	char *config;
1228 	TALLOC_CTX *mem_ctx;
1229 	NTSTATUS status;
1230 	struct db_context *db = NULL;
1231 
1232 	if (argc > 0 || c->display_usage) {
1233 		d_printf("%s\n%s",
1234 			 _("Usage:"),
1235 			 _("net idmap get config"
1236 			   " [--db=<inputfile>]\n"
1237 			   " Get CONFIG entry from autorid database\n"
1238 			   "	inputfile\tTDB file to read config from.\n"));
1239 		return c->display_usage ? 0 : -1;
1240 	}
1241 
1242 	mem_ctx = talloc_stackframe();
1243 
1244 	if (!net_idmap_opendb_autorid(mem_ctx, c, true, &db)) {
1245 		goto done;
1246 	}
1247 
1248 	status = idmap_autorid_getconfigstr(db, mem_ctx, &config);
1249 	if (!NT_STATUS_IS_OK(status)) {
1250 		d_fprintf(stderr, "%s: %s\n",
1251 			  _("Error: unable to read config entry"),
1252 			  nt_errstr(status));
1253 		goto done;
1254 	}
1255 
1256 	printf("CONFIG: %s\n", config);
1257 	ret = 0;
1258 
1259 done:
1260 	TALLOC_FREE(mem_ctx);
1261 	return ret;
1262 }
1263 
1264 
net_idmap_get(struct net_context * c,int argc,const char ** argv)1265 static int net_idmap_get(struct net_context *c, int argc, const char **argv)
1266 {
1267 	struct functable func[] = {
1268 		{
1269 			"range",
1270 			net_idmap_autorid_get_range,
1271 			NET_TRANSPORT_LOCAL,
1272 			N_("Get the range for a domain and range-index"),
1273 			N_("net idmap get range\n"
1274 			   "  Get the range for a domain and range-index")
1275 		},
1276 		{
1277 			"ranges",
1278 			net_idmap_autorid_get_ranges,
1279 			NET_TRANSPORT_LOCAL,
1280 			N_("Get all ranges for a domain"),
1281 			N_("net idmap get ranges <SID>\n"
1282 			   "  Get all ranges for a domain")
1283 		},
1284 		{
1285 			"config",
1286 			net_idmap_autorid_get_config,
1287 			NET_TRANSPORT_LOCAL,
1288 			N_("Get the global configuration from the autorid database"),
1289 			N_("net idmap get config \n"
1290 			   "  Get the global configuration from the autorid database ")
1291 		},
1292 		{NULL, NULL, 0, NULL, NULL}
1293 	};
1294 
1295 	return net_run_function(c, argc, argv, "net idmap get", func);
1296 }
1297 
net_idmap_check(struct net_context * c,int argc,const char ** argv)1298 static int net_idmap_check(struct net_context *c, int argc, const char **argv)
1299 {
1300 	char *dbfile;
1301 	struct check_options opts;
1302 	struct net_idmap_ctx ctx = { .backend = TDB };
1303 	int ret;
1304 
1305 	if ( argc > 1 || c->display_usage) {
1306 		d_printf("%s\n%s",
1307 			 _("Usage:"),
1308 			 _("net idmap check  [-v] [-r] [-a] [-T] [-f] [-l] [[--db=]<TDB>]\n"
1309 			   "  Check an idmap database.\n"
1310 			   "    --verbose,-v\tverbose\n"
1311 			   "    --repair,-r\trepair\n"
1312 			   "    --auto,-a\tnoninteractive mode\n"
1313 			   "    --test,-T\tdry run\n"
1314 			   "    --force,-f\tforce\n"
1315 			   "    --lock,-l\tlock db while doing the check\n"
1316 			   "    TDB\tidmap database\n"));
1317 		return c->display_usage ? 0 : -1;
1318 	}
1319 
1320 	if (argc > 0) {
1321 		dbfile = talloc_strdup(talloc_tos(), argv[0]);
1322 	} else {
1323 		dbfile = net_idmap_dbfile(c, &ctx);
1324 	}
1325 	if (dbfile == NULL) {
1326 		return -1;
1327 	}
1328 
1329 	if (ctx.backend != TDB) {
1330 		d_fprintf(stderr, _("Sorry, checking of non-TDB databases is "
1331 				    "currently not supported\n"));
1332 		talloc_free(dbfile);
1333 		return -1;
1334 	}
1335 
1336 	d_fprintf(stderr, _("check database: %s\n"), dbfile);
1337 
1338 	opts = (struct check_options) {
1339 		.lock = c->opt_lock || c->opt_long_list_entries,
1340 		.test = c->opt_testmode,
1341 		.automatic = c->opt_auto,
1342 		.verbose = c->opt_verbose,
1343 		.force = c->opt_force,
1344 		.repair = c->opt_repair || c->opt_reboot,
1345 	};
1346 
1347 	ret = net_idmap_check_db(dbfile, &opts);
1348 	talloc_free(dbfile);
1349 	return ret;
1350 }
1351 
1352 /***********************************************************
1353  Look at the current idmap
1354  **********************************************************/
net_idmap(struct net_context * c,int argc,const char ** argv)1355 int net_idmap(struct net_context *c, int argc, const char **argv)
1356 {
1357 	struct functable func[] = {
1358 		{
1359 			"dump",
1360 			net_idmap_dump,
1361 			NET_TRANSPORT_LOCAL,
1362 			N_("Dump the current ID mapping database"),
1363 			N_("net idmap dump\n"
1364 			   "  Dump the current ID mappings")
1365 		},
1366 		{
1367 			"restore",
1368 			net_idmap_restore,
1369 			NET_TRANSPORT_LOCAL,
1370 			N_("Restore entries from a file or stdin"),
1371 			N_("net idmap restore\n"
1372 			   "  Restore entries from stdin")
1373 		},
1374 		{
1375 			"get",
1376 			net_idmap_get,
1377 			NET_TRANSPORT_LOCAL,
1378 			N_("Read data from the ID mapping database"),
1379 			N_("net idmap get\n"
1380 			   "  Read data from the ID mapping database")
1381 		},
1382 		{
1383 			"set",
1384 			net_idmap_set,
1385 			NET_TRANSPORT_LOCAL,
1386 			N_("Write data to the ID mapping database"),
1387 			N_("net idmap set\n"
1388 			   "  Write data to the ID mapping database")
1389 		},
1390 		{
1391 			"delete",
1392 			net_idmap_delete,
1393 			NET_TRANSPORT_LOCAL,
1394 			N_("Delete entries from the ID mapping database"),
1395 			N_("net idmap delete\n"
1396 			   "  Delete entries from the ID mapping database")
1397 		},
1398 		{
1399 			"check",
1400 			net_idmap_check,
1401 			NET_TRANSPORT_LOCAL,
1402 			N_("Check id mappings"),
1403 			N_("net idmap check\n"
1404 			   "  Check id mappings")
1405 		},
1406 		{NULL, NULL, 0, NULL, NULL}
1407 	};
1408 
1409 	return net_run_function(c, argc, argv, "net idmap", func);
1410 }
1411 
1412 
1413