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