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