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