WHATSNEW: Update changes.
[Samba.git] / source3 / utils / net_rpc_samsync.c
blob8b5a90838ed883309b7585f951c476fffa280521
1 /*
2 Unix SMB/CIFS implementation.
3 dump the remote SAM using rpc samsync operations
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.
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.
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.
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/>.
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"
33 static void parse_samsync_partial_replication_objects(TALLOC_CTX *mem_ctx,
34 int argc,
35 const char **argv,
36 bool *do_single_object_replication,
37 struct samsync_object **objects,
38 uint32_t *num_objects)
40 int i;
42 if (argc > 0) {
43 *do_single_object_replication = true;
46 for (i=0; i<argc; i++) {
48 struct samsync_object o;
50 ZERO_STRUCT(o);
52 if (!StrnCaseCmp(argv[i], "user_rid=", strlen("user_rid="))) {
53 o.object_identifier.rid = get_int_param(argv[i]);
54 o.object_type = NETR_DELTA_USER;
55 o.database_id = SAM_DATABASE_DOMAIN;
57 if (!StrnCaseCmp(argv[i], "group_rid=", strlen("group_rid="))) {
58 o.object_identifier.rid = get_int_param(argv[i]);
59 o.object_type = NETR_DELTA_GROUP;
60 o.database_id = SAM_DATABASE_DOMAIN;
62 if (!StrnCaseCmp(argv[i], "group_member_rid=", strlen("group_member_rid="))) {
63 o.object_identifier.rid = get_int_param(argv[i]);
64 o.object_type = NETR_DELTA_GROUP_MEMBER;
65 o.database_id = SAM_DATABASE_DOMAIN;
67 if (!StrnCaseCmp(argv[i], "alias_rid=", strlen("alias_rid="))) {
68 o.object_identifier.rid = get_int_param(argv[i]);
69 o.object_type = NETR_DELTA_ALIAS;
70 o.database_id = SAM_DATABASE_BUILTIN;
72 if (!StrnCaseCmp(argv[i], "alias_member_rid=", strlen("alias_member_rid="))) {
73 o.object_identifier.rid = get_int_param(argv[i]);
74 o.object_type = NETR_DELTA_ALIAS_MEMBER;
75 o.database_id = SAM_DATABASE_BUILTIN;
77 if (!StrnCaseCmp(argv[i], "account_sid=", strlen("account_sid="))) {
78 const char *sid_str = get_string_param(argv[i]);
79 string_to_sid(&o.object_identifier.sid, sid_str);
80 o.object_type = NETR_DELTA_ACCOUNT;
81 o.database_id = SAM_DATABASE_PRIVS;
83 if (!StrnCaseCmp(argv[i], "policy_sid=", strlen("policy_sid="))) {
84 const char *sid_str = get_string_param(argv[i]);
85 string_to_sid(&o.object_identifier.sid, sid_str);
86 o.object_type = NETR_DELTA_POLICY;
87 o.database_id = SAM_DATABASE_PRIVS;
89 if (!StrnCaseCmp(argv[i], "trustdom_sid=", strlen("trustdom_sid="))) {
90 const char *sid_str = get_string_param(argv[i]);
91 string_to_sid(&o.object_identifier.sid, sid_str);
92 o.object_type = NETR_DELTA_TRUSTED_DOMAIN;
93 o.database_id = SAM_DATABASE_PRIVS;
95 if (!StrnCaseCmp(argv[i], "secret_name=", strlen("secret_name="))) {
96 o.object_identifier.name = get_string_param(argv[i]);
97 o.object_type = NETR_DELTA_SECRET;
98 o.database_id = SAM_DATABASE_PRIVS;
101 if (o.object_type > 0) {
102 ADD_TO_ARRAY(mem_ctx, struct samsync_object, o,
103 objects, num_objects);
108 /* dump sam database via samsync rpc calls */
109 NTSTATUS rpc_samdump_internals(struct net_context *c,
110 const struct dom_sid *domain_sid,
111 const char *domain_name,
112 struct cli_state *cli,
113 struct rpc_pipe_client *pipe_hnd,
114 TALLOC_CTX *mem_ctx,
115 int argc,
116 const char **argv)
118 struct samsync_context *ctx = NULL;
119 NTSTATUS status;
121 status = libnet_samsync_init_context(mem_ctx,
122 domain_sid,
123 &ctx);
124 if (!NT_STATUS_IS_OK(status)) {
125 return status;
128 ctx->mode = NET_SAMSYNC_MODE_DUMP;
129 ctx->cli = pipe_hnd;
130 ctx->ops = &libnet_samsync_display_ops;
131 ctx->domain_name = domain_name;
133 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
134 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
136 parse_samsync_partial_replication_objects(ctx, argc, argv,
137 &ctx->single_object_replication,
138 &ctx->objects,
139 &ctx->num_objects);
141 libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
143 libnet_samsync(SAM_DATABASE_BUILTIN, ctx);
145 libnet_samsync(SAM_DATABASE_PRIVS, ctx);
147 TALLOC_FREE(ctx);
149 return NT_STATUS_OK;
153 * Basic usage function for 'net rpc vampire'
155 * @param c A net_context structure
156 * @param argc Standard main() style argc
157 * @param argc Standard main() style argv. Initial components are already
158 * stripped
161 int rpc_vampire_usage(struct net_context *c, int argc, const char **argv)
163 d_printf(_("net rpc vampire ([ldif [<ldif-filename>] | [keytab] "
164 "[<keytab-filename]) [options]\n"
165 "\t to pull accounts from a remote PDC where we are a BDC\n"
166 "\t\t no args puts accounts in local passdb from smb.conf\n"
167 "\t\t ldif - put accounts in ldif format (file defaults to "
168 "/tmp/tmp.ldif)\n"
169 "\t\t keytab - put account passwords in krb5 keytab "
170 "(defaults to system keytab)\n"));
172 net_common_flags_usage(c, argc, argv);
173 return -1;
177 /* dump sam database via samsync rpc calls */
178 NTSTATUS rpc_vampire_internals(struct net_context *c,
179 const struct dom_sid *domain_sid,
180 const char *domain_name,
181 struct cli_state *cli,
182 struct rpc_pipe_client *pipe_hnd,
183 TALLOC_CTX *mem_ctx,
184 int argc,
185 const char **argv)
187 NTSTATUS result;
188 struct samsync_context *ctx = NULL;
190 if (!sid_equal(domain_sid, get_global_sam_sid())) {
191 d_printf(_("Cannot import users from %s at this time, "
192 "as the current domain:\n\t%s: %s\nconflicts "
193 "with the remote domain\n\t%s: %s\n"
194 "Perhaps you need to set: \n\n\tsecurity=user\n\t"
195 "workgroup=%s\n\n in your smb.conf?\n"),
196 domain_name,
197 get_global_sam_name(),
198 sid_string_dbg(get_global_sam_sid()),
199 domain_name,
200 sid_string_dbg(domain_sid),
201 domain_name);
202 return NT_STATUS_UNSUCCESSFUL;
205 result = libnet_samsync_init_context(mem_ctx,
206 domain_sid,
207 &ctx);
208 if (!NT_STATUS_IS_OK(result)) {
209 return result;
212 ctx->mode = NET_SAMSYNC_MODE_FETCH_PASSDB;
213 ctx->cli = pipe_hnd;
214 ctx->ops = &libnet_samsync_passdb_ops;
215 ctx->domain_name = domain_name;
217 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
218 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
220 parse_samsync_partial_replication_objects(ctx, argc, argv,
221 &ctx->single_object_replication,
222 &ctx->objects,
223 &ctx->num_objects);
225 /* fetch domain */
226 result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
228 if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
229 d_fprintf(stderr, "%s\n", ctx->error_message);
230 goto fail;
233 if (ctx->result_message) {
234 d_fprintf(stdout, "%s\n", ctx->result_message);
237 /* fetch builtin */
238 ctx->domain_sid = sid_dup_talloc(mem_ctx, &global_sid_Builtin);
239 ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
240 result = libnet_samsync(SAM_DATABASE_BUILTIN, ctx);
242 if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
243 d_fprintf(stderr, "%s\n", ctx->error_message);
244 goto fail;
247 if (ctx->result_message) {
248 d_fprintf(stdout, "%s\n", ctx->result_message);
251 fail:
252 TALLOC_FREE(ctx);
253 return result;
256 int rpc_vampire_passdb(struct net_context *c, int argc, const char **argv)
258 if (c->display_usage) {
259 d_printf( "%s\n"
260 "net rpc vampire passdb\n"
261 " %s\n",
262 _("Usage:"),
263 _("Dump remote SAM database to passdb"));
264 return 0;
267 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id, 0,
268 rpc_vampire_internals, argc, argv);
271 NTSTATUS rpc_vampire_ldif_internals(struct net_context *c,
272 const struct dom_sid *domain_sid,
273 const char *domain_name,
274 struct cli_state *cli,
275 struct rpc_pipe_client *pipe_hnd,
276 TALLOC_CTX *mem_ctx,
277 int argc,
278 const char **argv)
280 NTSTATUS status;
281 struct samsync_context *ctx = NULL;
283 status = libnet_samsync_init_context(mem_ctx,
284 domain_sid,
285 &ctx);
286 if (!NT_STATUS_IS_OK(status)) {
287 return status;
290 if (argc >= 1) {
291 ctx->output_filename = argv[0];
293 if (argc >= 2) {
294 parse_samsync_partial_replication_objects(ctx, argc-1, argv+1,
295 &ctx->single_object_replication,
296 &ctx->objects,
297 &ctx->num_objects);
300 ctx->mode = NET_SAMSYNC_MODE_FETCH_LDIF;
301 ctx->cli = pipe_hnd;
302 ctx->ops = &libnet_samsync_ldif_ops;
303 ctx->domain_name = domain_name;
305 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
306 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
308 /* fetch domain */
309 status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
311 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
312 d_fprintf(stderr, "%s\n", ctx->error_message);
313 goto fail;
316 if (ctx->result_message) {
317 d_fprintf(stdout, "%s\n", ctx->result_message);
320 /* fetch builtin */
321 ctx->domain_sid = sid_dup_talloc(mem_ctx, &global_sid_Builtin);
322 ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
323 status = libnet_samsync(SAM_DATABASE_BUILTIN, ctx);
325 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
326 d_fprintf(stderr, "%s\n", ctx->error_message);
327 goto fail;
330 if (ctx->result_message) {
331 d_fprintf(stdout, "%s\n", ctx->result_message);
334 fail:
335 TALLOC_FREE(ctx);
336 return status;
339 int rpc_vampire_ldif(struct net_context *c, int argc, const char **argv)
341 if (c->display_usage) {
342 d_printf( "%s\n"
343 "net rpc vampire ldif\n"
344 " %s\n",
345 _("Usage:"),
346 _("Dump remote SAM database to LDIF file or "
347 "stdout"));
348 return 0;
351 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id, 0,
352 rpc_vampire_ldif_internals, argc, argv);
356 NTSTATUS rpc_vampire_keytab_internals(struct net_context *c,
357 const struct dom_sid *domain_sid,
358 const char *domain_name,
359 struct cli_state *cli,
360 struct rpc_pipe_client *pipe_hnd,
361 TALLOC_CTX *mem_ctx,
362 int argc,
363 const char **argv)
365 NTSTATUS status;
366 struct samsync_context *ctx = NULL;
368 status = libnet_samsync_init_context(mem_ctx,
369 domain_sid,
370 &ctx);
371 if (!NT_STATUS_IS_OK(status)) {
372 return status;
375 if (argc < 1) {
376 /* the caller should ensure that a filename is provided */
377 return NT_STATUS_INVALID_PARAMETER;
378 } else {
379 ctx->output_filename = argv[0];
381 if (argc >= 2) {
382 parse_samsync_partial_replication_objects(ctx, argc-1, argv+1,
383 &ctx->single_object_replication,
384 &ctx->objects,
385 &ctx->num_objects);
388 ctx->mode = NET_SAMSYNC_MODE_FETCH_KEYTAB;
389 ctx->cli = pipe_hnd;
390 ctx->ops = &libnet_samsync_keytab_ops;
391 ctx->domain_name = domain_name;
392 ctx->username = c->opt_user_name;
393 ctx->password = c->opt_password;
395 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
396 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
398 /* fetch domain */
399 status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
401 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
402 d_fprintf(stderr, "%s\n", ctx->error_message);
403 goto out;
406 if (ctx->result_message) {
407 d_fprintf(stdout, "%s\n", ctx->result_message);
410 out:
411 TALLOC_FREE(ctx);
413 return status;
416 static NTSTATUS rpc_vampire_keytab_ds_internals(struct net_context *c,
417 const struct dom_sid *domain_sid,
418 const char *domain_name,
419 struct cli_state *cli,
420 struct rpc_pipe_client *pipe_hnd,
421 TALLOC_CTX *mem_ctx,
422 int argc,
423 const char **argv)
425 NTSTATUS status;
426 struct dssync_context *ctx = NULL;
428 status = libnet_dssync_init_context(mem_ctx,
429 &ctx);
430 if (!NT_STATUS_IS_OK(status)) {
431 return status;
434 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
435 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
437 if (argc < 1) {
438 /* the caller should ensure that a filename is provided */
439 return NT_STATUS_INVALID_PARAMETER;
440 } else {
441 ctx->output_filename = argv[0];
444 if (argc >= 2) {
445 ctx->object_dns = &argv[1];
446 ctx->object_count = argc - 1;
447 ctx->single_object_replication = c->opt_single_obj_repl ? true
448 : false;
451 ctx->cli = pipe_hnd;
452 ctx->domain_name = domain_name;
453 ctx->ops = &libnet_dssync_keytab_ops;
455 status = libnet_dssync(mem_ctx, ctx);
456 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
457 d_fprintf(stderr, "%s\n", ctx->error_message);
458 goto out;
461 if (ctx->result_message) {
462 d_fprintf(stdout, "%s\n", ctx->result_message);
465 out:
466 TALLOC_FREE(ctx);
468 return status;
472 * Basic function for 'net rpc vampire keytab'
474 * @param c A net_context structure
475 * @param argc Standard main() style argc
476 * @param argc Standard main() style argv. Initial components are already
477 * stripped
480 int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv)
482 int ret = 0;
483 NTSTATUS status;
484 struct cli_state *cli = NULL;
485 struct net_dc_info dc_info;
487 if (c->display_usage || (argc < 1)) {
488 d_printf("%s\n%s",
489 _("Usage:"),
490 _("net rpc vampire keytab <keytabfile>\n"
491 " Dump remote SAM database to Kerberos keytab "
492 "file\n"));
493 return 0;
496 status = net_make_ipc_connection(c, 0, &cli);
497 if (!NT_STATUS_IS_OK(status)) {
498 return -1;
501 status = net_scan_dc(c, cli, &dc_info);
502 if (!NT_STATUS_IS_OK(status)) {
503 return -1;
506 if (!dc_info.is_ad) {
507 printf(_("DC is not running Active Directory\n"));
508 ret = run_rpc_command(c, cli, &ndr_table_netlogon.syntax_id,
510 rpc_vampire_keytab_internals, argc, argv);
511 return -1;
512 } else {
513 ret = run_rpc_command(c, cli, &ndr_table_drsuapi.syntax_id,
514 NET_FLAGS_SEAL | NET_FLAGS_TCP,
515 rpc_vampire_keytab_ds_internals, argc, argv);
516 if (ret != 0 && dc_info.is_mixed_mode) {
517 printf(_("Fallback to NT4 vampire on Mixed-Mode AD "
518 "Domain\n"));
519 ret = run_rpc_command(c, cli, &ndr_table_netlogon.syntax_id,
521 rpc_vampire_keytab_internals, argc, argv);
525 return ret;