d145693a223b9b90428b52d2e3226d1af487ac28
[amitay/samba.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 #define FOO(x) (x)
21 #include "includes.h"
22 #include "utils/net.h"
23 #include "secrets.h"
24
25 #define ALLOC_CHECK(mem) do { \
26         if (!mem) { \
27                 d_fprintf(stderr, _("Out of memory!\n")); \
28                 talloc_free(ctx); \
29                 return -1; \
30         } } while(0)
31
32 /***********************************************************
33  Helper function for net_idmap_dump. Dump one entry.
34  **********************************************************/
35 static int net_idmap_dump_one_entry(struct db_record *rec,
36                                     void *unused)
37 {
38         if (strcmp((char *)rec->key.dptr, "USER HWM") == 0) {
39                 printf(_("USER HWM %d\n"), IVAL(rec->value.dptr,0));
40                 return 0;
41         }
42
43         if (strcmp((char *)rec->key.dptr, "GROUP HWM") == 0) {
44                 printf(_("GROUP HWM %d\n"), IVAL(rec->value.dptr,0));
45                 return 0;
46         }
47
48         if (strncmp((char *)rec->key.dptr, "S-", 2) != 0)
49                 return 0;
50
51         printf("%s %s\n", rec->value.dptr, rec->key.dptr);
52         return 0;
53 }
54
55 /***********************************************************
56  Dump the current idmap
57  **********************************************************/
58 static int net_idmap_dump(struct net_context *c, int argc, const char **argv)
59 {
60         struct db_context *db;
61         TALLOC_CTX *mem_ctx;
62
63         if ( argc != 1  || c->display_usage) {
64                 d_printf("%s\n%s",
65                          _("Usage:"),
66                          _("net idmap dump <inputfile>\n"
67                            "  Dump current ID mapping.\n"
68                            "    inputfile\tTDB file to read mappings from.\n"));
69                 return c->display_usage?0:-1;
70         }
71
72         mem_ctx = talloc_stackframe();
73
74         db = db_open(mem_ctx, argv[0], 0, TDB_DEFAULT, O_RDONLY, 0);
75         if (db == NULL) {
76                 d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"),
77                           argv[0], strerror(errno));
78                 talloc_free(mem_ctx);
79                 return -1;
80         }
81
82         db->traverse_read(db, net_idmap_dump_one_entry, NULL);
83
84         talloc_free(mem_ctx);
85
86         return 0;
87 }
88
89 /***********************************************************
90  Write entries from stdin to current local idmap
91  **********************************************************/
92
93 static int net_idmap_restore(struct net_context *c, int argc, const char **argv)
94 {
95         TALLOC_CTX *ctx;
96         FILE *input;
97
98         if (c->display_usage) {
99                 d_printf("%s\n%s",
100                          _("Usage:"),
101                          _("net idmap restore [inputfile]\n"
102                            "  Restore ID mappings from file\n"
103                            "    inputfile\tFile to load ID mappings from. If "
104                            "not given, load data from stdin.\n"));
105                 return 0;
106         }
107
108         if (! winbind_ping()) {
109                 d_fprintf(stderr,
110                           _("To use net idmap Winbindd must be running.\n"));
111                 return -1;
112         }
113
114         ctx = talloc_new(NULL);
115         ALLOC_CHECK(ctx);
116
117         if (argc == 1) {
118                 input = fopen(argv[0], "r");
119         } else {
120                 input = stdin;
121         }
122
123         while (!feof(input)) {
124                 char line[128], sid_string[128];
125                 int len;
126                 struct wbcDomainSid sid;
127                 enum id_type type = ID_TYPE_NOT_SPECIFIED;
128                 unsigned long idval;
129                 wbcErr wbc_status;
130
131                 if (fgets(line, 127, input) == NULL)
132                         break;
133
134                 len = strlen(line);
135
136                 if ( (len > 0) && (line[len-1] == '\n') )
137                         line[len-1] = '\0';
138
139                 if (sscanf(line, "GID %lu %128s", &idval, sid_string) == 2) {
140                         type = ID_TYPE_GID;
141                 } else if (sscanf(line, "UID %lu %128s", &idval, sid_string) == 2) {
142                         type = ID_TYPE_UID;
143                 } else if (sscanf(line, "USER HWM %lu", &idval) == 1) {
144                         /* set uid hwm */
145                         wbc_status = wbcSetUidHwm(idval);
146                         if (!WBC_ERROR_IS_OK(wbc_status)) {
147                                 d_fprintf(stderr,
148                                           _("Could not set USER HWM: %s\n"),
149                                           wbcErrorString(wbc_status));
150                         }
151                         continue;
152                 } else if (sscanf(line, "GROUP HWM %lu", &idval) == 1) {
153                         /* set gid hwm */
154                         wbc_status = wbcSetGidHwm(idval);
155                         if (!WBC_ERROR_IS_OK(wbc_status)) {
156                                 d_fprintf(stderr,
157                                           _("Could not set GROUP HWM: %s\n"),
158                                           wbcErrorString(wbc_status));
159                         }
160                         continue;
161                 } else {
162                         d_fprintf(stderr, _("ignoring invalid line [%s]\n"),
163                                   line);
164                         continue;
165                 }
166
167                 wbc_status = wbcStringToSid(sid_string, &sid);
168                 if (!WBC_ERROR_IS_OK(wbc_status)) {
169                         d_fprintf(stderr, _("ignoring invalid sid [%s]: %s\n"),
170                                   sid_string, wbcErrorString(wbc_status));
171                         continue;
172                 }
173
174                 if (type == ID_TYPE_UID) {
175                         wbc_status = wbcSetUidMapping(idval, &sid);
176                 } else {
177                         wbc_status = wbcSetGidMapping(idval, &sid);
178                 }
179                 if (!WBC_ERROR_IS_OK(wbc_status)) {
180                         d_fprintf(stderr,
181                                   _("Could not set mapping of %s %lu to sid %s: %s\n"),
182                                  (type == ID_TYPE_GID) ? "GID" : "UID",
183                                  idval, sid_string,
184                                  wbcErrorString(wbc_status));
185                         continue;
186                 }
187         }
188
189         if (input != stdin) {
190                 fclose(input);
191         }
192
193         talloc_free(ctx);
194         return 0;
195 }
196
197 /***********************************************************
198  Delete a SID mapping from a winbindd_idmap.tdb
199  **********************************************************/
200 static int net_idmap_delete(struct net_context *c, int argc, const char **argv)
201 {
202         d_printf("%s\n", _("Not implemented yet"));
203         return -1;
204 }
205
206 static int net_idmap_set(struct net_context *c, int argc, const char **argv)
207 {
208         d_printf("%s\n", _("Not implemented yet"));
209         return -1;
210 }
211 bool idmap_store_secret(const char *backend, bool alloc,
212                         const char *domain, const char *identity,
213                         const char *secret)
214 {
215         char *tmp;
216         int r;
217         bool ret;
218
219         if (alloc) {
220                 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
221         } else {
222                 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
223         }
224
225         if (r < 0) return false;
226
227         strupper_m(tmp); /* make sure the key is case insensitive */
228         ret = secrets_store_generic(tmp, identity, secret);
229
230         free(tmp);
231         return ret;
232 }
233
234
235 static int net_idmap_secret(struct net_context *c, int argc, const char **argv)
236 {
237         TALLOC_CTX *ctx;
238         const char *secret;
239         const char *dn;
240         char *domain;
241         char *backend;
242         char *opt = NULL;
243         bool ret;
244
245         if (argc != 2 || c->display_usage) {
246                 d_printf("%s\n%s",
247                          _("Usage:"),
248                          _("net idmap secret {<DOMAIN>|alloc} <secret>\n"
249                            "  Set the secret for the specified domain "
250                            "(or alloc module)\n"
251                            "    DOMAIN\tDomain to set secret for.\n"
252                            "    alloc\tSet secret for the alloc module\n"
253                            "    secret\tNew secret to set.\n"));
254                 return c->display_usage?0:-1;
255         }
256
257         secret = argv[1];
258
259         ctx = talloc_new(NULL);
260         ALLOC_CHECK(ctx);
261
262         if (strcmp(argv[0], "alloc") == 0) {
263                 domain = NULL;
264                 backend = lp_idmap_alloc_backend();
265         } else {
266                 domain = talloc_strdup(ctx, argv[0]);
267                 ALLOC_CHECK(domain);
268
269                 opt = talloc_asprintf(ctx, "idmap config %s", domain);
270                 ALLOC_CHECK(opt);
271
272                 backend = talloc_strdup(ctx, lp_parm_const_string(-1, opt, "backend", "tdb"));
273                 ALLOC_CHECK(backend);
274         }
275
276         if ( ( ! backend) || ( ! strequal(backend, "ldap"))) {
277                 d_fprintf(stderr,
278                           _("The only currently supported backend is LDAP\n"));
279                 talloc_free(ctx);
280                 return -1;
281         }
282
283         if (domain) {
284
285                 dn = lp_parm_const_string(-1, opt, "ldap_user_dn", NULL);
286                 if ( ! dn) {
287                         d_fprintf(stderr,
288                                   _("Missing ldap_user_dn option for domain "
289                                     "%s\n"), domain);
290                         talloc_free(ctx);
291                         return -1;
292                 }
293
294                 ret = idmap_store_secret("ldap", false, domain, dn, secret);
295         } else {
296                 dn = lp_parm_const_string(-1, "idmap alloc config", "ldap_user_dn", NULL);
297                 if ( ! dn) {
298                         d_fprintf(stderr,
299                                   _("Missing ldap_user_dn option for alloc "
300                                     "backend\n"));
301                         talloc_free(ctx);
302                         return -1;
303                 }
304
305                 ret = idmap_store_secret("ldap", true, NULL, dn, secret);
306         }
307
308         if ( ! ret) {
309                 d_fprintf(stderr, _("Failed to store secret\n"));
310                 talloc_free(ctx);
311                 return -1;
312         }
313
314         d_printf(_("Secret stored\n"));
315         return 0;
316 }
317
318 int net_help_idmap(struct net_context *c, int argc, const char **argv)
319 {
320         d_printf(_("net idmap dump <inputfile>\n"
321                    "    Dump current id mapping\n"));
322
323         d_printf(_("net idmap restore\n"
324                    "    Restore entries from stdin\n"));
325
326         /* Deliberately *not* document net idmap delete */
327
328         d_printf(_("net idmap secret <DOMAIN>|alloc <secret>\n"
329                    "    Set the secret for the specified DOMAIN (or the alloc "
330                    "module)\n"));
331
332         return -1;
333 }
334
335 static int net_idmap_aclmapset(struct net_context *c, int argc, const char **argv)
336 {
337         TALLOC_CTX *mem_ctx;
338         int result = -1;
339         struct dom_sid src_sid, dst_sid;
340         char *src, *dst;
341         struct db_context *db;
342         struct db_record *rec;
343         NTSTATUS status;
344
345         if (argc != 3 || c->display_usage) {
346                 d_fprintf(stderr, "%s net idmap aclmapset <tdb> "
347                           "<src-sid> <dst-sid>\n", _("Usage:"));
348                 return -1;
349         }
350
351         if (!(mem_ctx = talloc_init("net idmap aclmapset"))) {
352                 d_fprintf(stderr, _("talloc_init failed\n"));
353                 return -1;
354         }
355
356         if (!(db = db_open(mem_ctx, argv[0], 0, TDB_DEFAULT,
357                            O_RDWR|O_CREAT, 0600))) {
358                 d_fprintf(stderr, _("db_open failed: %s\n"), strerror(errno));
359                 goto fail;
360         }
361
362         if (!string_to_sid(&src_sid, argv[1])) {
363                 d_fprintf(stderr, _("%s is not a valid sid\n"), argv[1]);
364                 goto fail;
365         }
366
367         if (!string_to_sid(&dst_sid, argv[2])) {
368                 d_fprintf(stderr, _("%s is not a valid sid\n"), argv[2]);
369                 goto fail;
370         }
371
372         if (!(src = sid_string_talloc(mem_ctx, &src_sid))
373             || !(dst = sid_string_talloc(mem_ctx, &dst_sid))) {
374                 d_fprintf(stderr, _("talloc_strdup failed\n"));
375                 goto fail;
376         }
377
378         if (!(rec = db->fetch_locked(
379                       db, mem_ctx, string_term_tdb_data(src)))) {
380                 d_fprintf(stderr, _("could not fetch db record\n"));
381                 goto fail;
382         }
383
384         status = rec->store(rec, string_term_tdb_data(dst), 0);
385         TALLOC_FREE(rec);
386
387         if (!NT_STATUS_IS_OK(status)) {
388                 d_fprintf(stderr, _("could not store record: %s\n"),
389                           nt_errstr(status));
390                 goto fail;
391         }
392
393         result = 0;
394 fail:
395         TALLOC_FREE(mem_ctx);
396         return result;
397 }
398
399 /***********************************************************
400  Look at the current idmap
401  **********************************************************/
402 int net_idmap(struct net_context *c, int argc, const char **argv)
403 {
404         struct functable func[] = {
405                 {
406                         "dump",
407                         net_idmap_dump,
408                         NET_TRANSPORT_LOCAL,
409                         N_("Dump the current ID mappings"),
410                         N_("net idmap dump\n"
411                            "  Dump the current ID mappings")
412                 },
413                 {
414                         "restore",
415                         net_idmap_restore,
416                         NET_TRANSPORT_LOCAL,
417                         N_("Restore entries from stdin"),
418                         N_("net idmap restore\n"
419                            "  Restore entries from stdin")
420                 },
421                 {
422                         "setmap",
423                         net_idmap_set,
424                         NET_TRANSPORT_LOCAL,
425                         N_("Not implemented yet"),
426                         N_("net idmap setmap\n"
427                            "  Not implemented yet")
428                 },
429                 {
430                         "delete",
431                         net_idmap_delete,
432                         NET_TRANSPORT_LOCAL,
433                         N_("Not implemented yet"),
434                         N_("net idmap delete\n"
435                            "  Not implemented yet")
436                 },
437                 {
438                         "secret",
439                         net_idmap_secret,
440                         NET_TRANSPORT_LOCAL,
441                         N_("Set secret for specified domain"),
442                         N_("net idmap secret {<DOMAIN>|alloc} <secret>\n"
443                            "  Set secret for specified domain or alloc module")
444                 },
445                 {
446                         "aclmapset",
447                         net_idmap_aclmapset,
448                         NET_TRANSPORT_LOCAL,
449                         N_("Set acl map"),
450                         N_("net idmap aclmapset\n"
451                            "  Set acl map")
452                 },
453                 {NULL, NULL, 0, NULL, NULL}
454         };
455
456         return net_run_function(c, argc, argv, "net idmap", func);
457 }
458
459