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/>.
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"
35 static void parse_samsync_partial_replication_objects(TALLOC_CTX *mem_ctx,
38 bool *do_single_object_replication,
39 struct samsync_object **objects,
40 uint32_t *num_objects)
45 *do_single_object_replication = true;
48 for (i=0; i<argc; i++) {
50 struct samsync_object o;
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;
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;
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;
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;
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;
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;
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;
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;
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;
103 if (o.object_type > 0) {
104 ADD_TO_ARRAY(mem_ctx, struct samsync_object, o,
105 objects, num_objects);
111 * Basic usage function for 'net rpc vampire'
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
119 int rpc_vampire_usage(struct net_context *c, int argc, const char **argv)
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 "
127 "\t\t keytab - put account passwords in krb5 keytab "
128 "(defaults to system keytab)\n"));
130 net_common_flags_usage(c, argc, argv);
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,
144 struct dssync_context *ctx = NULL;
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"),
153 get_global_sam_name(),
154 sid_string_dbg(get_global_sam_sid()),
156 sid_string_dbg(domain_sid),
158 return NT_STATUS_UNSUCCESSFUL;
161 status = libnet_dssync_init_context(mem_ctx,
163 if (!NT_STATUS_IS_OK(status)) {
168 ctx->domain_name = domain_name;
169 ctx->ops = &libnet_dssync_passdb_ops;
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);
177 if (ctx->result_message) {
178 d_fprintf(stdout, "%s\n", ctx->result_message);
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,
198 struct samsync_context *ctx = NULL;
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"),
207 get_global_sam_name(),
208 sid_string_dbg(get_global_sam_sid()),
210 sid_string_dbg(domain_sid),
212 return NT_STATUS_UNSUCCESSFUL;
215 result = libnet_samsync_init_context(mem_ctx,
218 if (!NT_STATUS_IS_OK(result)) {
222 ctx->mode = NET_SAMSYNC_MODE_FETCH_PASSDB;
224 ctx->ops = &libnet_samsync_passdb_ops;
225 ctx->domain_name = domain_name;
227 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
228 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
230 parse_samsync_partial_replication_objects(ctx, argc, argv,
231 &ctx->single_object_replication,
236 result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
238 if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
239 d_fprintf(stderr, "%s\n", ctx->error_message);
243 if (ctx->result_message) {
244 d_fprintf(stdout, "%s\n", ctx->result_message);
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);
252 if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
253 d_fprintf(stderr, "%s\n", ctx->error_message);
257 if (ctx->result_message) {
258 d_fprintf(stdout, "%s\n", ctx->result_message);
266 int rpc_vampire_passdb(struct net_context *c, int argc, const char **argv)
270 struct cli_state *cli = NULL;
271 struct net_dc_info dc_info;
273 if (c->display_usage) {
275 "net rpc vampire passdb\n"
278 _("Dump remote SAM database to passdb"));
282 status = net_make_ipc_connection(c, 0, &cli);
283 if (!NT_STATUS_IS_OK(status)) {
287 status = net_scan_dc(c, cli, &dc_info);
288 if (!NT_STATUS_IS_OK(status)) {
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,
296 rpc_vampire_internals, argc, argv);
302 "net rpc vampire passdb\n"
305 _("Should not be used against Active Directory, maybe use --force"));
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 "
315 ret = run_rpc_command(c, cli, &ndr_table_netlogon,
317 rpc_vampire_internals, argc, argv);
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,
333 struct samsync_context *ctx = NULL;
335 status = libnet_samsync_init_context(mem_ctx,
338 if (!NT_STATUS_IS_OK(status)) {
343 ctx->output_filename = argv[0];
346 parse_samsync_partial_replication_objects(ctx, argc-1, argv+1,
347 &ctx->single_object_replication,
352 ctx->mode = NET_SAMSYNC_MODE_FETCH_LDIF;
354 ctx->ops = &libnet_samsync_ldif_ops;
355 ctx->domain_name = domain_name;
357 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
358 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
361 status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
363 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
364 d_fprintf(stderr, "%s\n", ctx->error_message);
368 if (ctx->result_message) {
369 d_fprintf(stdout, "%s\n", ctx->result_message);
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);
377 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
378 d_fprintf(stderr, "%s\n", ctx->error_message);
382 if (ctx->result_message) {
383 d_fprintf(stdout, "%s\n", ctx->result_message);
391 int rpc_vampire_ldif(struct net_context *c, int argc, const char **argv)
393 if (c->display_usage) {
395 "net rpc vampire ldif\n"
398 _("Dump remote SAM database to LDIF file or "
403 return run_rpc_command(c, NULL, &ndr_table_netlogon, 0,
404 rpc_vampire_ldif_internals, argc, argv);
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,
418 struct samsync_context *ctx = NULL;
420 status = libnet_samsync_init_context(mem_ctx,
423 if (!NT_STATUS_IS_OK(status)) {
428 /* the caller should ensure that a filename is provided */
429 return NT_STATUS_INVALID_PARAMETER;
431 ctx->output_filename = argv[0];
434 parse_samsync_partial_replication_objects(ctx, argc-1, argv+1,
435 &ctx->single_object_replication,
440 ctx->mode = NET_SAMSYNC_MODE_FETCH_KEYTAB;
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;
447 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
448 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
451 status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
453 if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
454 d_fprintf(stderr, "%s\n", ctx->error_message);
458 if (ctx->result_message) {
459 d_fprintf(stdout, "%s\n", ctx->result_message);
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,
478 struct dssync_context *ctx = NULL;
480 status = libnet_dssync_init_context(mem_ctx,
482 if (!NT_STATUS_IS_OK(status)) {
486 ctx->force_full_replication = c->opt_force_full_repl ? true : false;
487 ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
490 /* the caller should ensure that a filename is provided */
491 return NT_STATUS_INVALID_PARAMETER;
493 ctx->output_filename = argv[0];
497 ctx->object_dns = &argv[1];
498 ctx->object_count = argc - 1;
499 ctx->single_object_replication = c->opt_single_obj_repl ? true
504 ctx->domain_name = domain_name;
505 ctx->ops = &libnet_dssync_keytab_ops;
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);
513 if (ctx->result_message) {
514 d_fprintf(stdout, "%s\n", ctx->result_message);
524 * Basic function for 'net rpc vampire keytab'
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
532 int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv)
536 struct cli_state *cli = NULL;
537 struct net_dc_info dc_info;
539 if (c->display_usage || (argc < 1)) {
542 _("net rpc vampire keytab <keytabfile>\n"
543 " Dump remote SAM database to Kerberos keytab "
548 status = net_make_ipc_connection(c, 0, &cli);
549 if (!NT_STATUS_IS_OK(status)) {
553 status = net_scan_dc(c, cli, &dc_info);
554 if (!NT_STATUS_IS_OK(status)) {
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,
562 rpc_vampire_keytab_internals, argc, argv);
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 "
570 ret = run_rpc_command(c, cli, &ndr_table_netlogon,
572 rpc_vampire_keytab_internals, argc, argv);
575 printf(_("Vampire requested against AD DC but ADS"
576 " support not built in: HAVE_ADS is not defined\n"));