net: Remove rpc samdump
[sfrench/samba-autobuild/.git] / source3 / utils / net_rpc_samsync.c
1 /*
2    Unix SMB/CIFS implementation.
3    dump the remote SAM using rpc samsync operations
4
5    Copyright (C) Andrew Tridgell 2002
6    Copyright (C) Tim Potter 2001,2002
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
8    Modified by Volker Lendecke 2002
9    Copyright (C) Jeremy Allison 2005.
10    Copyright (C) Guenther Deschner 2008.
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "utils/net.h"
28 #include "../librpc/gen_ndr/ndr_netlogon.h"
29 #include "../librpc/gen_ndr/ndr_drsuapi.h"
30 #include "libnet/libnet_samsync.h"
31 #include "libnet/libnet_dssync.h"
32 #include "../libcli/security/security.h"
33 #include "passdb/machine_sid.h"
34
35 static void parse_samsync_partial_replication_objects(TALLOC_CTX *mem_ctx,
36                                                       int argc,
37                                                       const char **argv,
38                                                       bool *do_single_object_replication,
39                                                       struct samsync_object **objects,
40                                                       uint32_t *num_objects)
41 {
42         int i;
43
44         if (argc > 0) {
45                 *do_single_object_replication = true;
46         }
47
48         for (i=0; i<argc; i++) {
49
50                 struct samsync_object o;
51
52                 ZERO_STRUCT(o);
53
54                 if (!strncasecmp_m(argv[i], "user_rid=", strlen("user_rid="))) {
55                         o.object_identifier.rid         = get_int_param(argv[i]);
56                         o.object_type                   = NETR_DELTA_USER;
57                         o.database_id                   = SAM_DATABASE_DOMAIN;
58                 }
59                 if (!strncasecmp_m(argv[i], "group_rid=", strlen("group_rid="))) {
60                         o.object_identifier.rid         = get_int_param(argv[i]);
61                         o.object_type                   = NETR_DELTA_GROUP;
62                         o.database_id                   = SAM_DATABASE_DOMAIN;
63                 }
64                 if (!strncasecmp_m(argv[i], "group_member_rid=", strlen("group_member_rid="))) {
65                         o.object_identifier.rid         = get_int_param(argv[i]);
66                         o.object_type                   = NETR_DELTA_GROUP_MEMBER;
67                         o.database_id                   = SAM_DATABASE_DOMAIN;
68                 }
69                 if (!strncasecmp_m(argv[i], "alias_rid=", strlen("alias_rid="))) {
70                         o.object_identifier.rid         = get_int_param(argv[i]);
71                         o.object_type                   = NETR_DELTA_ALIAS;
72                         o.database_id                   = SAM_DATABASE_BUILTIN;
73                 }
74                 if (!strncasecmp_m(argv[i], "alias_member_rid=", strlen("alias_member_rid="))) {
75                         o.object_identifier.rid         = get_int_param(argv[i]);
76                         o.object_type                   = NETR_DELTA_ALIAS_MEMBER;
77                         o.database_id                   = SAM_DATABASE_BUILTIN;
78                 }
79                 if (!strncasecmp_m(argv[i], "account_sid=", strlen("account_sid="))) {
80                         const char *sid_str = get_string_param(argv[i]);
81                         string_to_sid(&o.object_identifier.sid, sid_str);
82                         o.object_type                   = NETR_DELTA_ACCOUNT;
83                         o.database_id                   = SAM_DATABASE_PRIVS;
84                 }
85                 if (!strncasecmp_m(argv[i], "policy_sid=", strlen("policy_sid="))) {
86                         const char *sid_str = get_string_param(argv[i]);
87                         string_to_sid(&o.object_identifier.sid, sid_str);
88                         o.object_type                   = NETR_DELTA_POLICY;
89                         o.database_id                   = SAM_DATABASE_PRIVS;
90                 }
91                 if (!strncasecmp_m(argv[i], "trustdom_sid=", strlen("trustdom_sid="))) {
92                         const char *sid_str = get_string_param(argv[i]);
93                         string_to_sid(&o.object_identifier.sid, sid_str);
94                         o.object_type                   = NETR_DELTA_TRUSTED_DOMAIN;
95                         o.database_id                   = SAM_DATABASE_PRIVS;
96                 }
97                 if (!strncasecmp_m(argv[i], "secret_name=", strlen("secret_name="))) {
98                         o.object_identifier.name        = get_string_param(argv[i]);
99                         o.object_type                   = NETR_DELTA_SECRET;
100                         o.database_id                   = SAM_DATABASE_PRIVS;
101                 }
102
103                 if (o.object_type > 0) {
104                         ADD_TO_ARRAY(mem_ctx, struct samsync_object, o,
105                                      objects, num_objects);
106                 }
107         }
108 }
109
110 /**
111  * Basic usage function for 'net rpc vampire'
112  *
113  * @param c     A net_context structure
114  * @param argc  Standard main() style argc
115  * @param argc  Standard main() style argv.  Initial components are already
116  *              stripped
117  **/
118
119 int rpc_vampire_usage(struct net_context *c, int argc, const char **argv)
120 {
121         d_printf(_("net rpc vampire ([ldif [<ldif-filename>] | [keytab] "
122                    "[<keytab-filename]) [options]\n"
123                    "\t to pull accounts from a remote PDC where we are a BDC\n"
124                    "\t\t no args puts accounts in local passdb from smb.conf\n"
125                    "\t\t ldif - put accounts in ldif format (file defaults to "
126                    "/tmp/tmp.ldif)\n"
127                    "\t\t keytab - put account passwords in krb5 keytab "
128                    "(defaults to system keytab)\n"));
129
130         net_common_flags_usage(c, argc, argv);
131         return -1;
132 }
133
134 static NTSTATUS rpc_vampire_ds_internals(struct net_context *c,
135                                          const struct dom_sid *domain_sid,
136                                          const char *domain_name,
137                                          struct cli_state *cli,
138                                          struct rpc_pipe_client *pipe_hnd,
139                                          TALLOC_CTX *mem_ctx,
140                                          int argc,
141                                          const char **argv)
142 {
143         NTSTATUS status;
144         struct dssync_context *ctx = NULL;
145
146         if (!dom_sid_equal(domain_sid, get_global_sam_sid())) {
147                 d_printf(_("Cannot import users from %s at this time, "
148                            "as the current domain:\n\t%s: %s\nconflicts "
149                            "with the remote domain\n\t%s: %s\n"
150                            "Perhaps you need to set: \n\n\tsecurity=user\n\t"
151                            "workgroup=%s\n\n in your smb.conf?\n"),
152                          domain_name,
153                          get_global_sam_name(),
154                          sid_string_dbg(get_global_sam_sid()),
155                          domain_name,
156                          sid_string_dbg(domain_sid),
157                          domain_name);
158                 return NT_STATUS_UNSUCCESSFUL;
159         }
160
161         status = libnet_dssync_init_context(mem_ctx,
162                                             &ctx);
163         if (!NT_STATUS_IS_OK(status)) {
164                 return status;
165         }
166
167         ctx->cli                = pipe_hnd;
168         ctx->domain_name        = domain_name;
169         ctx->ops                = &libnet_dssync_passdb_ops;
170
171         status = libnet_dssync(mem_ctx, ctx);
172         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
173                 d_fprintf(stderr, "%s\n", ctx->error_message);
174                 goto out;
175         }
176
177         if (ctx->result_message) {
178                 d_fprintf(stdout, "%s\n", ctx->result_message);
179         }
180
181  out:
182         TALLOC_FREE(ctx);
183
184         return status;
185 }
186
187 /* dump sam database via samsync rpc calls */
188 static NTSTATUS rpc_vampire_internals(struct net_context *c,
189                                       const struct dom_sid *domain_sid,
190                                       const char *domain_name,
191                                       struct cli_state *cli,
192                                       struct rpc_pipe_client *pipe_hnd,
193                                       TALLOC_CTX *mem_ctx,
194                                       int argc,
195                                       const char **argv)
196 {
197         NTSTATUS result;
198         struct samsync_context *ctx = NULL;
199
200         if (!dom_sid_equal(domain_sid, get_global_sam_sid())) {
201                 d_printf(_("Cannot import users from %s at this time, "
202                            "as the current domain:\n\t%s: %s\nconflicts "
203                            "with the remote domain\n\t%s: %s\n"
204                            "Perhaps you need to set: \n\n\tsecurity=user\n\t"
205                            "workgroup=%s\n\n in your smb.conf?\n"),
206                          domain_name,
207                          get_global_sam_name(),
208                          sid_string_dbg(get_global_sam_sid()),
209                          domain_name,
210                          sid_string_dbg(domain_sid),
211                          domain_name);
212                 return NT_STATUS_UNSUCCESSFUL;
213         }
214
215         result = libnet_samsync_init_context(mem_ctx,
216                                              domain_sid,
217                                              &ctx);
218         if (!NT_STATUS_IS_OK(result)) {
219                 return result;
220         }
221
222         ctx->mode               = NET_SAMSYNC_MODE_FETCH_PASSDB;
223         ctx->cli                = pipe_hnd;
224         ctx->ops                = &libnet_samsync_passdb_ops;
225         ctx->domain_name        = domain_name;
226
227         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
228         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
229
230         parse_samsync_partial_replication_objects(ctx, argc, argv,
231                                                   &ctx->single_object_replication,
232                                                   &ctx->objects,
233                                                   &ctx->num_objects);
234
235         /* fetch domain */
236         result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
237
238         if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
239                 d_fprintf(stderr, "%s\n", ctx->error_message);
240                 goto fail;
241         }
242
243         if (ctx->result_message) {
244                 d_fprintf(stdout, "%s\n", ctx->result_message);
245         }
246
247         /* fetch builtin */
248         ctx->domain_sid = dom_sid_dup(mem_ctx, &global_sid_Builtin);
249         ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
250         result = libnet_samsync(SAM_DATABASE_BUILTIN, ctx);
251
252         if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
253                 d_fprintf(stderr, "%s\n", ctx->error_message);
254                 goto fail;
255         }
256
257         if (ctx->result_message) {
258                 d_fprintf(stdout, "%s\n", ctx->result_message);
259         }
260
261  fail:
262         TALLOC_FREE(ctx);
263         return result;
264 }
265
266 int rpc_vampire_passdb(struct net_context *c, int argc, const char **argv)
267 {
268         int ret = 0;
269         NTSTATUS status;
270         struct cli_state *cli = NULL;
271         struct net_dc_info dc_info;
272
273         if (c->display_usage) {
274                 d_printf(  "%s\n"
275                            "net rpc vampire passdb\n"
276                            "    %s\n",
277                          _("Usage:"),
278                          _("Dump remote SAM database to passdb"));
279                 return 0;
280         }
281
282         status = net_make_ipc_connection(c, 0, &cli);
283         if (!NT_STATUS_IS_OK(status)) {
284                 return -1;
285         }
286
287         status = net_scan_dc(c, cli, &dc_info);
288         if (!NT_STATUS_IS_OK(status)) {
289                 return -1;
290         }
291
292         if (!dc_info.is_ad) {
293                 printf(_("DC is not running Active Directory\n"));
294                 ret = run_rpc_command(c, cli, &ndr_table_netlogon,
295                                       0,
296                                       rpc_vampire_internals, argc, argv);
297                 return ret;
298         }
299
300         if (!c->opt_force) {
301                 d_printf(  "%s\n"
302                            "net rpc vampire passdb\n"
303                            "    %s\n",
304                          _("Usage:"),
305                          _("Should not be used against Active Directory, maybe use --force"));
306                 return -1;
307         }
308
309         ret = run_rpc_command(c, cli, &ndr_table_drsuapi,
310                               NET_FLAGS_SEAL | NET_FLAGS_TCP,
311                               rpc_vampire_ds_internals, argc, argv);
312         if (ret != 0 && dc_info.is_mixed_mode) {
313                 printf(_("Fallback to NT4 vampire on Mixed-Mode AD "
314                          "Domain\n"));
315                 ret = run_rpc_command(c, cli, &ndr_table_netlogon,
316                                       0,
317                                       rpc_vampire_internals, argc, argv);
318         }
319
320         return ret;
321 }
322
323 static NTSTATUS rpc_vampire_ldif_internals(struct net_context *c,
324                                            const struct dom_sid *domain_sid,
325                                            const char *domain_name,
326                                            struct cli_state *cli,
327                                            struct rpc_pipe_client *pipe_hnd,
328                                            TALLOC_CTX *mem_ctx,
329                                            int argc,
330                                            const char **argv)
331 {
332         NTSTATUS status;
333         struct samsync_context *ctx = NULL;
334
335         status = libnet_samsync_init_context(mem_ctx,
336                                              domain_sid,
337                                              &ctx);
338         if (!NT_STATUS_IS_OK(status)) {
339                 return status;
340         }
341
342         if (argc >= 1) {
343                 ctx->output_filename = argv[0];
344         }
345         if (argc >= 2) {
346                 parse_samsync_partial_replication_objects(ctx, argc-1, argv+1,
347                                                           &ctx->single_object_replication,
348                                                           &ctx->objects,
349                                                           &ctx->num_objects);
350         }
351
352         ctx->mode               = NET_SAMSYNC_MODE_FETCH_LDIF;
353         ctx->cli                = pipe_hnd;
354         ctx->ops                = &libnet_samsync_ldif_ops;
355         ctx->domain_name        = domain_name;
356
357         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
358         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
359
360         /* fetch domain */
361         status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
362
363         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
364                 d_fprintf(stderr, "%s\n", ctx->error_message);
365                 goto fail;
366         }
367
368         if (ctx->result_message) {
369                 d_fprintf(stdout, "%s\n", ctx->result_message);
370         }
371
372         /* fetch builtin */
373         ctx->domain_sid = dom_sid_dup(mem_ctx, &global_sid_Builtin);
374         ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
375         status = libnet_samsync(SAM_DATABASE_BUILTIN, ctx);
376
377         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
378                 d_fprintf(stderr, "%s\n", ctx->error_message);
379                 goto fail;
380         }
381
382         if (ctx->result_message) {
383                 d_fprintf(stdout, "%s\n", ctx->result_message);
384         }
385
386  fail:
387         TALLOC_FREE(ctx);
388         return status;
389 }
390
391 int rpc_vampire_ldif(struct net_context *c, int argc, const char **argv)
392 {
393         if (c->display_usage) {
394                 d_printf(  "%s\n"
395                            "net rpc vampire ldif\n"
396                            "    %s\n",
397                          _("Usage:"),
398                          _("Dump remote SAM database to LDIF file or "
399                            "stdout"));
400                 return 0;
401         }
402
403         return run_rpc_command(c, NULL, &ndr_table_netlogon, 0,
404                                rpc_vampire_ldif_internals, argc, argv);
405 }
406
407
408 static NTSTATUS rpc_vampire_keytab_internals(struct net_context *c,
409                                              const struct dom_sid *domain_sid,
410                                              const char *domain_name,
411                                              struct cli_state *cli,
412                                              struct rpc_pipe_client *pipe_hnd,
413                                              TALLOC_CTX *mem_ctx,
414                                              int argc,
415                                              const char **argv)
416 {
417         NTSTATUS status;
418         struct samsync_context *ctx = NULL;
419
420         status = libnet_samsync_init_context(mem_ctx,
421                                              domain_sid,
422                                              &ctx);
423         if (!NT_STATUS_IS_OK(status)) {
424                 return status;
425         }
426
427         if (argc < 1) {
428                 /* the caller should ensure that a filename is provided */
429                 return NT_STATUS_INVALID_PARAMETER;
430         } else {
431                 ctx->output_filename = argv[0];
432         }
433         if (argc >= 2) {
434                 parse_samsync_partial_replication_objects(ctx, argc-1, argv+1,
435                                                           &ctx->single_object_replication,
436                                                           &ctx->objects,
437                                                           &ctx->num_objects);
438         }
439
440         ctx->mode               = NET_SAMSYNC_MODE_FETCH_KEYTAB;
441         ctx->cli                = pipe_hnd;
442         ctx->ops                = &libnet_samsync_keytab_ops;
443         ctx->domain_name        = domain_name;
444         ctx->username           = c->opt_user_name;
445         ctx->password           = c->opt_password;
446
447         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
448         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
449
450         /* fetch domain */
451         status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
452
453         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
454                 d_fprintf(stderr, "%s\n", ctx->error_message);
455                 goto out;
456         }
457
458         if (ctx->result_message) {
459                 d_fprintf(stdout, "%s\n", ctx->result_message);
460         }
461
462  out:
463         TALLOC_FREE(ctx);
464
465         return status;
466 }
467
468 static NTSTATUS rpc_vampire_keytab_ds_internals(struct net_context *c,
469                                                 const struct dom_sid *domain_sid,
470                                                 const char *domain_name,
471                                                 struct cli_state *cli,
472                                                 struct rpc_pipe_client *pipe_hnd,
473                                                 TALLOC_CTX *mem_ctx,
474                                                 int argc,
475                                                 const char **argv)
476 {
477         NTSTATUS status;
478         struct dssync_context *ctx = NULL;
479
480         status = libnet_dssync_init_context(mem_ctx,
481                                             &ctx);
482         if (!NT_STATUS_IS_OK(status)) {
483                 return status;
484         }
485
486         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
487         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
488
489         if (argc < 1) {
490                 /* the caller should ensure that a filename is provided */
491                 return NT_STATUS_INVALID_PARAMETER;
492         } else {
493                 ctx->output_filename = argv[0];
494         }
495
496         if (argc >= 2) {
497                 ctx->object_dns = &argv[1];
498                 ctx->object_count = argc - 1;
499                 ctx->single_object_replication = c->opt_single_obj_repl ? true
500                                                                         : false;
501         }
502
503         ctx->cli                = pipe_hnd;
504         ctx->domain_name        = domain_name;
505         ctx->ops                = &libnet_dssync_keytab_ops;
506
507         status = libnet_dssync(mem_ctx, ctx);
508         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
509                 d_fprintf(stderr, "%s\n", ctx->error_message);
510                 goto out;
511         }
512
513         if (ctx->result_message) {
514                 d_fprintf(stdout, "%s\n", ctx->result_message);
515         }
516
517  out:
518         TALLOC_FREE(ctx);
519
520         return status;
521 }
522
523 /**
524  * Basic function for 'net rpc vampire keytab'
525  *
526  * @param c     A net_context structure
527  * @param argc  Standard main() style argc
528  * @param argc  Standard main() style argv.  Initial components are already
529  *              stripped
530  **/
531
532 int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv)
533 {
534         int ret = 0;
535         NTSTATUS status;
536         struct cli_state *cli = NULL;
537         struct net_dc_info dc_info;
538
539         if (c->display_usage || (argc < 1)) {
540                 d_printf("%s\n%s",
541                          _("Usage:"),
542                          _("net rpc vampire keytab <keytabfile>\n"
543                            "    Dump remote SAM database to Kerberos keytab "
544                            "file\n"));
545                 return 0;
546         }
547
548         status = net_make_ipc_connection(c, 0, &cli);
549         if (!NT_STATUS_IS_OK(status)) {
550                 return -1;
551         }
552
553         status = net_scan_dc(c, cli, &dc_info);
554         if (!NT_STATUS_IS_OK(status)) {
555                 return -1;
556         }
557
558         if (!dc_info.is_ad) {
559                 printf(_("DC is not running Active Directory\n"));
560                 ret = run_rpc_command(c, cli, &ndr_table_netlogon,
561                                       0,
562                                       rpc_vampire_keytab_internals, argc, argv);
563         } else {
564                 ret = run_rpc_command(c, cli, &ndr_table_drsuapi,
565                                       NET_FLAGS_SEAL | NET_FLAGS_TCP,
566                                       rpc_vampire_keytab_ds_internals, argc, argv);
567                 if (ret != 0 && dc_info.is_mixed_mode) {
568                         printf(_("Fallback to NT4 vampire on Mixed-Mode AD "
569                                  "Domain\n"));
570                         ret = run_rpc_command(c, cli, &ndr_table_netlogon,
571                                               0,
572                                               rpc_vampire_keytab_internals, argc, argv);
573                 } else {
574 #ifndef HAVE_ADS
575                         printf(_("Vampire requested against AD DC but ADS"
576                                 " support not built in: HAVE_ADS is not defined\n"));
577 #endif
578                 }
579         }
580
581         return ret;
582 }