source: trunk/server/source3/utils/net_rpc_samsync.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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