s3-libnet: better separate headers.
[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 #include "libnet/libnet_samsync.h"
31 #include "libnet/libnet_dssync.h"
32
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)
39 {
40         int i;
41
42         if (argc > 0) {
43                 *do_single_object_replication = true;
44         }
45
46         for (i=0; i<argc; i++) {
47
48                 struct samsync_object o;
49
50                 ZERO_STRUCT(o);
51
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;
56                 }
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;
61                 }
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;
66                 }
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;
71                 }
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;
76                 }
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;
82                 }
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;
88                 }
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;
94                 }
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;
99                 }
100
101                 if (o.object_type > 0) {
102                         ADD_TO_ARRAY(mem_ctx, struct samsync_object, o,
103                                      objects, num_objects);
104                 }
105         }
106 }
107
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)
117 {
118         struct samsync_context *ctx = NULL;
119         NTSTATUS status;
120
121         status = libnet_samsync_init_context(mem_ctx,
122                                              domain_sid,
123                                              &ctx);
124         if (!NT_STATUS_IS_OK(status)) {
125                 return status;
126         }
127
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;
132
133         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
134         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
135
136         parse_samsync_partial_replication_objects(ctx, argc, argv,
137                                                   &ctx->single_object_replication,
138                                                   &ctx->objects,
139                                                   &ctx->num_objects);
140
141         libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
142
143         libnet_samsync(SAM_DATABASE_BUILTIN, ctx);
144
145         libnet_samsync(SAM_DATABASE_PRIVS, ctx);
146
147         TALLOC_FREE(ctx);
148
149         return NT_STATUS_OK;
150 }
151
152 /**
153  * Basic usage function for 'net rpc vampire'
154  *
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
159  **/
160
161 int rpc_vampire_usage(struct net_context *c, int argc, const char **argv)
162 {
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"));
171
172         net_common_flags_usage(c, argc, argv);
173         return -1;
174 }
175
176
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)
186 {
187         NTSTATUS result;
188         struct samsync_context *ctx = NULL;
189
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;
203         }
204
205         result = libnet_samsync_init_context(mem_ctx,
206                                              domain_sid,
207                                              &ctx);
208         if (!NT_STATUS_IS_OK(result)) {
209                 return result;
210         }
211
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;
216
217         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
218         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
219
220         parse_samsync_partial_replication_objects(ctx, argc, argv,
221                                                   &ctx->single_object_replication,
222                                                   &ctx->objects,
223                                                   &ctx->num_objects);
224
225         /* fetch domain */
226         result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
227
228         if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
229                 d_fprintf(stderr, "%s\n", ctx->error_message);
230                 goto fail;
231         }
232
233         if (ctx->result_message) {
234                 d_fprintf(stdout, "%s\n", ctx->result_message);
235         }
236
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);
241
242         if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
243                 d_fprintf(stderr, "%s\n", ctx->error_message);
244                 goto fail;
245         }
246
247         if (ctx->result_message) {
248                 d_fprintf(stdout, "%s\n", ctx->result_message);
249         }
250
251  fail:
252         TALLOC_FREE(ctx);
253         return result;
254 }
255
256 int rpc_vampire_passdb(struct net_context *c, int argc, const char **argv)
257 {
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;
265         }
266
267         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id, 0,
268                                rpc_vampire_internals, argc, argv);
269 }
270
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)
279 {
280         NTSTATUS status;
281         struct samsync_context *ctx = NULL;
282
283         status = libnet_samsync_init_context(mem_ctx,
284                                              domain_sid,
285                                              &ctx);
286         if (!NT_STATUS_IS_OK(status)) {
287                 return status;
288         }
289
290         if (argc >= 1) {
291                 ctx->output_filename = argv[0];
292         }
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);
298         }
299
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;
304
305         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
306         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
307
308         /* fetch domain */
309         status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
310
311         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
312                 d_fprintf(stderr, "%s\n", ctx->error_message);
313                 goto fail;
314         }
315
316         if (ctx->result_message) {
317                 d_fprintf(stdout, "%s\n", ctx->result_message);
318         }
319
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);
324
325         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
326                 d_fprintf(stderr, "%s\n", ctx->error_message);
327                 goto fail;
328         }
329
330         if (ctx->result_message) {
331                 d_fprintf(stdout, "%s\n", ctx->result_message);
332         }
333
334  fail:
335         TALLOC_FREE(ctx);
336         return status;
337 }
338
339 int rpc_vampire_ldif(struct net_context *c, int argc, const char **argv)
340 {
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;
349         }
350
351         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id, 0,
352                                rpc_vampire_ldif_internals, argc, argv);
353 }
354
355
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)
364 {
365         NTSTATUS status;
366         struct samsync_context *ctx = NULL;
367
368         status = libnet_samsync_init_context(mem_ctx,
369                                              domain_sid,
370                                              &ctx);
371         if (!NT_STATUS_IS_OK(status)) {
372                 return status;
373         }
374
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];
380         }
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);
386         }
387
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;
394
395         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
396         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
397
398         /* fetch domain */
399         status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
400
401         if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
402                 d_fprintf(stderr, "%s\n", ctx->error_message);
403                 goto out;
404         }
405
406         if (ctx->result_message) {
407                 d_fprintf(stdout, "%s\n", ctx->result_message);
408         }
409
410  out:
411         TALLOC_FREE(ctx);
412
413         return status;
414 }
415
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)
424 {
425         NTSTATUS status;
426         struct dssync_context *ctx = NULL;
427
428         status = libnet_dssync_init_context(mem_ctx,
429                                             &ctx);
430         if (!NT_STATUS_IS_OK(status)) {
431                 return status;
432         }
433
434         ctx->force_full_replication = c->opt_force_full_repl ? true : false;
435         ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;
436
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];
442         }
443
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;
449         }
450
451         ctx->cli                = pipe_hnd;
452         ctx->domain_name        = domain_name;
453         ctx->ops                = &libnet_dssync_keytab_ops;
454
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;
459         }
460
461         if (ctx->result_message) {
462                 d_fprintf(stdout, "%s\n", ctx->result_message);
463         }
464
465  out:
466         TALLOC_FREE(ctx);
467
468         return status;
469 }
470
471 /**
472  * Basic function for 'net rpc vampire keytab'
473  *
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
478  **/
479
480 int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv)
481 {
482         int ret = 0;
483         NTSTATUS status;
484         struct cli_state *cli = NULL;
485         struct net_dc_info dc_info;
486
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;
494         }
495
496         status = net_make_ipc_connection(c, 0, &cli);
497         if (!NT_STATUS_IS_OK(status)) {
498                 return -1;
499         }
500
501         status = net_scan_dc(c, cli, &dc_info);
502         if (!NT_STATUS_IS_OK(status)) {
503                 return -1;
504         }
505
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,
509                                       0,
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,
520                                               0,
521                                               rpc_vampire_keytab_internals, argc, argv);
522                 }
523         }
524
525         return ret;
526 }