f067071de177834cdb99e754ba64b437e98a8b98
[metze/samba/wip.git] / source3 / utils / net_idmap.c
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
31 #define ALLOC_CHECK(mem) do { \
32         if (!mem) { \
33                 d_fprintf(stderr, _("Out of memory!\n")); \
34                 talloc_free(ctx); \
35                 return -1; \
36         } } while(0)
37
38 /***********************************************************
39  Helper function for net_idmap_dump. Dump one entry.
40  **********************************************************/
41 static int net_idmap_dump_one_entry(struct db_record *rec,
42                                     void *unused)
43 {
44         TDB_DATA key;
45         TDB_DATA value;
46
47         key = dbwrap_record_get_key(rec);
48         value = dbwrap_record_get_value(rec);
49
50         if (strcmp((char *)key.dptr, "USER HWM") == 0) {
51                 printf(_("USER HWM %d\n"), IVAL(value.dptr,0));
52                 return 0;
53         }
54
55         if (strcmp((char *)key.dptr, "GROUP HWM") == 0) {
56                 printf(_("GROUP HWM %d\n"), IVAL(value.dptr,0));
57                 return 0;
58         }
59
60         if (strncmp((char *)key.dptr, "S-", 2) != 0)
61                 return 0;
62
63         printf("%s %s\n", value.dptr, key.dptr);
64         return 0;
65 }
66
67 static const char* net_idmap_dbfile(struct net_context *c)
68 {
69         const char* dbfile = NULL;
70
71         if (c->opt_db != NULL) {
72                 dbfile = talloc_strdup(talloc_tos(), c->opt_db);
73                 if (dbfile == NULL) {
74                         d_fprintf(stderr, _("Out of memory!\n"));
75                 }
76         } else if (strequal(lp_idmap_backend(), "tdb")) {
77                 dbfile = state_path("winbindd_idmap.tdb");
78                 if (dbfile == NULL) {
79                         d_fprintf(stderr, _("Out of memory!\n"));
80                 }
81         } else if (strequal(lp_idmap_backend(), "tdb2")) {
82                 dbfile = lp_parm_talloc_string(talloc_tos(),
83                                                -1, "tdb", "idmap2.tdb", NULL);
84                 if (dbfile == NULL) {
85                         dbfile = talloc_asprintf(talloc_tos(), "%s/idmap2.tdb",
86                                                  lp_private_dir());
87                 }
88                 if (dbfile == NULL) {
89                         d_fprintf(stderr, _("Out of memory!\n"));
90                 }
91         } else {
92                 char* backend = talloc_strdup(talloc_tos(), lp_idmap_backend());
93                 char* args = strchr(backend, ':');
94                 if (args != NULL) {
95                         *args = '\0';
96                 }
97
98                 d_printf(_("Sorry, 'idmap backend = %s' is currently not supported\n"),
99                          backend);
100
101                 talloc_free(backend);
102         }
103
104         return dbfile;
105 }
106
107 /***********************************************************
108  Dump the current idmap
109  **********************************************************/
110 static int net_idmap_dump(struct net_context *c, int argc, const char **argv)
111 {
112         struct db_context *db;
113         TALLOC_CTX *mem_ctx;
114         const char* dbfile;
115         NTSTATUS status;
116         int ret = -1;
117
118         if ( argc > 1  || c->display_usage) {
119                 d_printf("%s\n%s",
120                          _("Usage:"),
121                          _("net idmap dump [[--db=]<inputfile>]\n"
122                            "  Dump current ID mapping.\n"
123                            "    inputfile\tTDB file to read mappings from.\n"));
124                 return c->display_usage?0:-1;
125         }
126
127         mem_ctx = talloc_stackframe();
128
129         dbfile = (argc > 0) ? argv[0] : net_idmap_dbfile(c);
130         if (dbfile == NULL) {
131                 goto done;
132         }
133         d_fprintf(stderr, _("dumping id mapping from %s\n"), dbfile);
134
135         db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDONLY, 0,
136                      DBWRAP_LOCK_ORDER_1);
137         if (db == NULL) {
138                 d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
139                           dbfile, strerror(errno));
140                 goto done;
141         }
142
143         status = dbwrap_traverse_read(db, net_idmap_dump_one_entry, NULL, NULL);
144         if (!NT_STATUS_IS_OK(status)) {
145                 d_fprintf(stderr, _("error traversing the database\n"));
146                 ret = -1;
147                 goto done;
148         }
149
150         ret = 0;
151
152 done:
153         talloc_free(mem_ctx);
154         return ret;
155 }
156
157 /***********************************************************
158  Write entries from stdin to current local idmap
159  **********************************************************/
160
161 static int net_idmap_store_id_mapping(struct db_context *db,
162                                       enum id_type type,
163                                       unsigned long idval,
164                                       const char *sid_string)
165 {
166         NTSTATUS status;
167         char *idstr = NULL;
168
169         switch(type) {
170         case ID_TYPE_UID:
171                 idstr = talloc_asprintf(talloc_tos(), "UID %lu", idval);
172                 break;
173         case ID_TYPE_GID:
174                 idstr = talloc_asprintf(talloc_tos(), "GID %lu", idval);
175                 break;
176         default:
177                 d_fprintf(stderr, "Invalid id mapping type: %d\n", type);
178                 return -1;
179         }
180
181         status = dbwrap_store_bystring(db, idstr,
182                                        string_term_tdb_data(sid_string),
183                                        TDB_REPLACE);
184         if (!NT_STATUS_IS_OK(status)) {
185                 d_fprintf(stderr, "Error storing ID -> SID: "
186                          "%s\n", nt_errstr(status));
187                 talloc_free(idstr);
188                 return -1;
189         }
190         status = dbwrap_store_bystring(db, sid_string,
191                                        string_term_tdb_data(idstr),
192                                        TDB_REPLACE);
193         if (!NT_STATUS_IS_OK(status)) {
194                 d_fprintf(stderr, "Error storing SID -> ID: "
195                          "%s\n", nt_errstr(status));
196                 talloc_free(idstr);
197                 return -1;
198         }
199
200         return 0;
201 }
202
203 static int net_idmap_restore(struct net_context *c, int argc, const char **argv)
204 {
205         TALLOC_CTX *mem_ctx;
206         FILE *input = NULL;
207         struct db_context *db;
208         const char *dbfile = NULL;
209         int ret = 0;
210
211         if (c->display_usage) {
212                 d_printf("%s\n%s",
213                          _("Usage:"),
214                          _("net idmap restore [--db=<TDB>] [<inputfile>]\n"
215                            "  Restore ID mappings from file\n"
216                            "    TDB\tFile to store ID mappings to."
217                            "    inputfile\tFile to load ID mappings from. If not "
218                            "given, load data from stdin.\n"));
219                 return 0;
220         }
221
222         mem_ctx = talloc_stackframe();
223
224         dbfile = net_idmap_dbfile(c);
225
226         if (dbfile == NULL) {
227                 ret = -1;
228                 goto done;
229         }
230
231         d_fprintf(stderr, _("restoring id mapping to %s\n"), dbfile);
232
233         if (argc == 1) {
234                 input = fopen(argv[0], "r");
235                 if (input == NULL) {
236                         d_fprintf(stderr, _("Could not open input file (%s): %s\n"),
237                                   argv[0], strerror(errno));
238                         ret = -1;
239                         goto done;
240                 }
241         } else {
242                 input = stdin;
243         }
244
245         db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644,
246                      DBWRAP_LOCK_ORDER_1);
247         if (db == NULL) {
248                 d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
249                           dbfile, strerror(errno));
250                 ret = -1;
251                 goto done;
252         }
253
254         if (dbwrap_transaction_start(db) != 0) {
255                 d_fprintf(stderr, _("Failed to start transaction.\n"));
256                 ret = -1;
257                 goto done;
258         }
259
260         while (!feof(input)) {
261                 char line[128], sid_string[128];
262                 int len;
263                 unsigned long idval;
264                 NTSTATUS status;
265
266                 if (fgets(line, 127, input) == NULL)
267                         break;
268
269                 len = strlen(line);
270
271                 if ( (len > 0) && (line[len-1] == '\n') )
272                         line[len-1] = '\0';
273
274                 if (sscanf(line, "GID %lu %128s", &idval, sid_string) == 2)
275                 {
276                         ret = net_idmap_store_id_mapping(db, ID_TYPE_GID,
277                                                          idval, sid_string);
278                         if (ret != 0) {
279                                 break;
280                         }
281                 } else if (sscanf(line, "UID %lu %128s", &idval, sid_string) == 2)
282                 {
283                         ret = net_idmap_store_id_mapping(db, ID_TYPE_UID,
284                                                          idval, sid_string);
285                         if (ret != 0) {
286                                 break;
287                         }
288                 } else if (sscanf(line, "USER HWM %lu", &idval) == 1) {
289                         status = dbwrap_store_int32_bystring(
290                                 db, "USER HWM", idval);
291                         if (!NT_STATUS_IS_OK(status)) {
292                                 d_fprintf(stderr,
293                                           _("Could not store USER HWM: %s\n"),
294                                           nt_errstr(status));
295                                 break;
296                         }
297                 } else if (sscanf(line, "GROUP HWM %lu", &idval) == 1) {
298                         status = dbwrap_store_int32_bystring(
299                                 db, "GROUP HWM", idval);
300                         if (!NT_STATUS_IS_OK(status)) {
301                                 d_fprintf(stderr,
302                                           _("Could not store GROUP HWM: %s\n"),
303                                           nt_errstr(status));
304                                 break;
305                         }
306                 } else {
307                         d_fprintf(stderr, _("ignoring invalid line [%s]\n"),
308                                   line);
309                         continue;
310                 }
311         }
312
313         if (ret == 0) {
314                 if(dbwrap_transaction_commit(db) != 0) {
315                         d_fprintf(stderr, _("Failed to commit transaction.\n"));
316                         ret = -1;
317                 }
318         } else {
319                 if (dbwrap_transaction_cancel(db) != 0) {
320                         d_fprintf(stderr, _("Failed to cancel transaction.\n"));
321                 }
322         }
323
324 done:
325         if ((input != NULL) && (input != stdin)) {
326                 fclose(input);
327         }
328
329         talloc_free(mem_ctx);
330         return ret;
331 }
332
333 static
334 NTSTATUS dbwrap_delete_mapping(struct db_context *db, TDB_DATA key1, bool force)
335 {
336         TALLOC_CTX* mem_ctx = talloc_tos();
337         struct db_record *rec1=NULL, *rec2=NULL;
338         TDB_DATA key2;
339         bool is_valid_mapping;
340         NTSTATUS status = NT_STATUS_OK;
341         TDB_DATA value;
342
343         rec1 = dbwrap_fetch_locked(db, mem_ctx, key1);
344         if (rec1 == NULL) {
345                 DEBUG(1, ("failed to fetch: %.*s\n", (int)key1.dsize, key1.dptr));
346                 status = NT_STATUS_NO_MEMORY;
347                 goto done;
348         }
349         key2 = dbwrap_record_get_value(rec1);
350         if (key2.dptr == NULL) {
351                 DEBUG(1, ("could not find %.*s\n", (int)key1.dsize, key1.dptr));
352                 status = NT_STATUS_NOT_FOUND;
353                 goto done;
354         }
355
356         DEBUG(2, ("mapping: %.*s -> %.*s\n",
357                   (int)key1.dsize, key1.dptr, (int)key2.dsize, key2.dptr));
358
359         rec2 = dbwrap_fetch_locked(db, mem_ctx, key2);
360         if (rec2 == NULL) {
361                 DEBUG(1, ("failed to fetch: %.*s\n", (int)key2.dsize, key2.dptr));
362                 status = NT_STATUS_NO_MEMORY;
363                 goto done;
364         }
365
366         value = dbwrap_record_get_value(rec2);
367         is_valid_mapping = tdb_data_equal(key1, value);
368
369         if (!is_valid_mapping) {
370                 DEBUG(1, ("invalid mapping: %.*s -> %.*s -> %.*s\n",
371                           (int)key1.dsize, key1.dptr, (int)key2.dsize, key2.dptr,
372                           (int)value.dsize, value.dptr ));
373                 if ( !force ) {
374                         status = NT_STATUS_FILE_INVALID;
375                         goto done;
376                 }
377         }
378
379         status = dbwrap_record_delete(rec1);
380         if (!NT_STATUS_IS_OK(status)) {
381                 DEBUG(1, ("failed to delete: %.*s\n", (int)key1.dsize, key1.dptr));
382                 goto done;
383         }
384
385         if (is_valid_mapping) {
386                 status = dbwrap_record_delete(rec2);
387                 if (!NT_STATUS_IS_OK(status)) {
388                         DEBUG(1, ("failed to delete: %.*s\n", (int)key2.dsize, key2.dptr));
389                 }
390         }
391 done:
392         TALLOC_FREE(rec1);
393         TALLOC_FREE(rec2);
394         return status;
395 }
396
397 static
398 NTSTATUS delete_mapping_action(struct db_context *db, void* data)
399 {
400         return dbwrap_delete_mapping(db, *(TDB_DATA*)data, false);
401 }
402 static
403 NTSTATUS delete_mapping_action_force(struct db_context *db, void* data)
404 {
405         return dbwrap_delete_mapping(db, *(TDB_DATA*)data, true);
406 }
407
408 /***********************************************************
409  Delete a SID mapping from a winbindd_idmap.tdb
410  **********************************************************/
411 static bool delete_args_ok(int argc, const char **argv)
412 {
413         if (argc != 1)
414                 return false;
415         if (strncmp(argv[0], "S-", 2) == 0)
416                 return true;
417         if (strncmp(argv[0], "GID ", 4) == 0)
418                 return true;
419         if (strncmp(argv[0], "UID ", 4) == 0)
420                 return true;
421         return false;
422 }
423
424 static int net_idmap_delete(struct net_context *c, int argc, const char **argv)
425 {
426         int ret = -1;
427         struct db_context *db;
428         TALLOC_CTX *mem_ctx;
429         TDB_DATA key;
430         NTSTATUS status;
431         const char* dbfile;
432
433         if ( !delete_args_ok(argc,argv) || c->display_usage) {
434                 d_printf("%s\n%s",
435                          _("Usage:"),
436                          _("net idmap delete [-f] [--db=<TDB>] <ID>\n"
437                            "  Delete mapping of ID from TDB.\n"
438                            "    -f\tforce\n"
439                            "    TDB\tidmap database\n"
440                            "    ID\tSID|GID|UID\n"));
441                 return c->display_usage ? 0 : -1;
442         }
443
444         mem_ctx = talloc_stackframe();
445
446         dbfile = net_idmap_dbfile(c);
447         if (dbfile == NULL) {
448                 goto done;
449         }
450         d_fprintf(stderr, _("deleting id mapping from %s\n"), dbfile);
451
452         db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR, 0,
453                      DBWRAP_LOCK_ORDER_1);
454         if (db == NULL) {
455                 d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
456                           dbfile, strerror(errno));
457                 goto done;
458         }
459
460         key = string_term_tdb_data(argv[0]);
461
462         status = dbwrap_trans_do(db, (c->opt_force
463                                       ? delete_mapping_action_force
464                                       : delete_mapping_action),  &key);
465
466         if (!NT_STATUS_IS_OK(status)) {
467                 d_fprintf(stderr, _("could not delete mapping: %s\n"),
468                           nt_errstr(status));
469                 goto done;
470         }
471         ret = 0;
472 done:
473         talloc_free(mem_ctx);
474         return ret;
475 }
476
477 static int net_idmap_set(struct net_context *c, int argc, const char **argv)
478 {
479         d_printf("%s\n", _("Not implemented yet"));
480         return -1;
481 }
482 static bool idmap_store_secret(const char *backend,
483                                const char *domain,
484                                const char *identity,
485                                const char *secret)
486 {
487         char *tmp;
488         int r;
489         bool ret;
490
491         r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
492
493         if (r < 0) return false;
494
495         strupper_m(tmp); /* make sure the key is case insensitive */
496         ret = secrets_store_generic(tmp, identity, secret);
497
498         free(tmp);
499         return ret;
500 }
501
502
503 static int net_idmap_secret(struct net_context *c, int argc, const char **argv)
504 {
505         TALLOC_CTX *ctx;
506         const char *secret;
507         const char *dn;
508         char *domain;
509         char *backend;
510         char *opt = NULL;
511         bool ret;
512
513         if (argc != 2 || c->display_usage) {
514                 d_printf("%s\n%s",
515                          _("Usage:\n"),
516                          _("net idmap secret <DOMAIN> <secret>\n"
517                            "  Set the secret for the specified domain\n"
518                            "    DOMAIN\tDomain to set secret for.\n"
519                            "    secret\tNew secret to set.\n"));
520                 return c->display_usage?0:-1;
521         }
522
523         secret = argv[1];
524
525         ctx = talloc_new(NULL);
526         ALLOC_CHECK(ctx);
527
528         domain = talloc_strdup(ctx, argv[0]);
529         ALLOC_CHECK(domain);
530
531         opt = talloc_asprintf(ctx, "idmap config %s", domain);
532         ALLOC_CHECK(opt);
533
534         backend = talloc_strdup(ctx, lp_parm_const_string(-1, opt, "backend", "tdb"));
535         ALLOC_CHECK(backend);
536
537         if ( ( ! backend) || ( ! strequal(backend, "ldap"))) {
538                 d_fprintf(stderr,
539                           _("The only currently supported backend is LDAP\n"));
540                 talloc_free(ctx);
541                 return -1;
542         }
543
544         dn = lp_parm_const_string(-1, opt, "ldap_user_dn", NULL);
545         if ( ! dn) {
546                 d_fprintf(stderr,
547                           _("Missing ldap_user_dn option for domain %s\n"),
548                           domain);
549                 talloc_free(ctx);
550                 return -1;
551         }
552
553         ret = idmap_store_secret("ldap", domain, dn, secret);
554
555         if ( ! ret) {
556                 d_fprintf(stderr, _("Failed to store secret\n"));
557                 talloc_free(ctx);
558                 return -1;
559         }
560
561         d_printf(_("Secret stored\n"));
562         return 0;
563 }
564
565 static int net_idmap_check(struct net_context *c, int argc, const char **argv)
566 {
567         const char* dbfile;
568         struct check_options opts;
569
570         if ( argc > 1 || c->display_usage) {
571                 d_printf("%s\n%s",
572                          _("Usage:"),
573                          _("net idmap check  [-v] [-r] [-a] [-T] [-f] [-l] [[--db=]<TDB>]\n"
574                            "  Check an idmap database.\n"
575                            "    --verbose,-v\tverbose\n"
576                            "    --repair,-r\trepair\n"
577                            "    --auto,-a\tnoninteractive mode\n"
578                            "    --test,-T\tdry run\n"
579                            "    --fore,-f\tforce\n"
580                            "    --lock,-l\tlock db while doing the check\n"
581                            "    TDB\tidmap database\n"));
582                 return c->display_usage ? 0 : -1;
583         }
584
585         dbfile = (argc > 0) ? argv[0] : net_idmap_dbfile(c);
586         if (dbfile == NULL) {
587                 return -1;
588         }
589         d_fprintf(stderr, _("check database: %s\n"), dbfile);
590
591         opts = (struct check_options) {
592                 .lock = c->opt_lock || c->opt_long_list_entries,
593                 .test = c->opt_testmode,
594                 .automatic = c->opt_auto,
595                 .verbose = c->opt_verbose,
596                 .force = c->opt_force,
597                 .repair = c->opt_repair || c->opt_reboot,
598         };
599
600         return net_idmap_check_db(dbfile, &opts);
601 }
602
603 static int net_idmap_aclmapset(struct net_context *c, int argc, const char **argv)
604 {
605         TALLOC_CTX *mem_ctx;
606         int result = -1;
607         struct dom_sid src_sid, dst_sid;
608         char *src, *dst;
609         struct db_context *db;
610         struct db_record *rec;
611         NTSTATUS status;
612
613         if (argc != 3 || c->display_usage) {
614                 d_fprintf(stderr, "%s net idmap aclmapset <tdb> "
615                           "<src-sid> <dst-sid>\n", _("Usage:"));
616                 return -1;
617         }
618
619         if (!(mem_ctx = talloc_init("net idmap aclmapset"))) {
620                 d_fprintf(stderr, _("talloc_init failed\n"));
621                 return -1;
622         }
623
624         if (!(db = db_open(mem_ctx, argv[0], 0, TDB_DEFAULT,
625                            O_RDWR|O_CREAT, 0600,
626                            DBWRAP_LOCK_ORDER_1))) {
627                 d_fprintf(stderr, _("db_open failed: %s\n"), strerror(errno));
628                 goto fail;
629         }
630
631         if (!string_to_sid(&src_sid, argv[1])) {
632                 d_fprintf(stderr, _("%s is not a valid sid\n"), argv[1]);
633                 goto fail;
634         }
635
636         if (!string_to_sid(&dst_sid, argv[2])) {
637                 d_fprintf(stderr, _("%s is not a valid sid\n"), argv[2]);
638                 goto fail;
639         }
640
641         if (!(src = sid_string_talloc(mem_ctx, &src_sid))
642             || !(dst = sid_string_talloc(mem_ctx, &dst_sid))) {
643                 d_fprintf(stderr, _("talloc_strdup failed\n"));
644                 goto fail;
645         }
646
647         if (!(rec = dbwrap_fetch_locked(
648                       db, mem_ctx, string_term_tdb_data(src)))) {
649                 d_fprintf(stderr, _("could not fetch db record\n"));
650                 goto fail;
651         }
652
653         status = dbwrap_record_store(rec, string_term_tdb_data(dst), 0);
654         TALLOC_FREE(rec);
655
656         if (!NT_STATUS_IS_OK(status)) {
657                 d_fprintf(stderr, _("could not store record: %s\n"),
658                           nt_errstr(status));
659                 goto fail;
660         }
661
662         result = 0;
663 fail:
664         TALLOC_FREE(mem_ctx);
665         return result;
666 }
667
668 /***********************************************************
669  Look at the current idmap
670  **********************************************************/
671 int net_idmap(struct net_context *c, int argc, const char **argv)
672 {
673         struct functable func[] = {
674                 {
675                         "dump",
676                         net_idmap_dump,
677                         NET_TRANSPORT_LOCAL,
678                         N_("Dump the current ID mappings"),
679                         N_("net idmap dump\n"
680                            "  Dump the current ID mappings")
681                 },
682                 {
683                         "restore",
684                         net_idmap_restore,
685                         NET_TRANSPORT_LOCAL,
686                         N_("Restore entries from stdin"),
687                         N_("net idmap restore\n"
688                            "  Restore entries from stdin")
689                 },
690                 {
691                         "setmap",
692                         net_idmap_set,
693                         NET_TRANSPORT_LOCAL,
694                         N_("Not implemented yet"),
695                         N_("net idmap setmap\n"
696                            "  Not implemented yet")
697                 },
698                 {
699                         "delete",
700                         net_idmap_delete,
701                         NET_TRANSPORT_LOCAL,
702                         N_("Delete ID mapping"),
703                         N_("net idmap delete <ID>\n"
704                            "  Delete ID mapping")
705                 },
706                 {
707                         "secret",
708                         net_idmap_secret,
709                         NET_TRANSPORT_LOCAL,
710                         N_("Set secret for specified domain"),
711                         N_("net idmap secret <DOMAIN> <secret>\n"
712                            "  Set secret for specified domain")
713                 },
714                 {
715                         "aclmapset",
716                         net_idmap_aclmapset,
717                         NET_TRANSPORT_LOCAL,
718                         N_("Set acl map"),
719                         N_("net idmap aclmapset\n"
720                            "  Set acl map")
721                 },
722                 {
723                         "check",
724                         net_idmap_check,
725                         NET_TRANSPORT_LOCAL,
726                         N_("Check id mappings"),
727                         N_("net idmap check\n"
728                            "  Check id mappings")
729                 },
730                 {NULL, NULL, 0, NULL, NULL}
731         };
732
733         return net_run_function(c, argc, argv, "net idmap", func);
734 }
735
736