sync'ing up for 3.0alpha20 release
[Samba/gbeck.git] / source3 / rpcclient / samsync.c
blob7124f9416ad4ff1fdf08b080f3d39b419411fd9d
1 /*
2 Unix SMB/CIFS implementation.
3 SAM synchronisation and replication
5 Copyright (C) Tim Potter 2001,2002
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 DOM_SID domain_sid;
26 static void decode_domain_info(SAM_DOMAIN_INFO *a)
28 fstring temp;
29 printf("Domain Information\n");
30 printf("------------------\n");
32 unistr2_to_ascii(temp, &a->uni_dom_name, sizeof(temp)-1);
33 printf("\tDomain :%s\n", temp);
34 printf("\tMin password len :%d\n", a->min_pwd_len);
35 printf("\tpassword history len:%d\n", a->pwd_history_len);
36 printf("\tcreation time :%s\n", http_timestring(nt_time_to_unix(&a->creation_time)));
39 static void decode_sam_group_info(SAM_GROUP_INFO *a)
41 fstring temp;
42 printf("\nDomain Group Information\n");
43 printf("------------------------\n");
45 unistr2_to_ascii(temp, &a->uni_grp_name, sizeof(temp)-1);
46 printf("\tGroup name :%s\n", temp);
47 unistr2_to_ascii(temp, &a->uni_grp_desc, sizeof(temp)-1);
48 printf("\tGroup description :%s\n", temp);
49 printf("\trid :%d\n", a->gid.g_rid);
50 printf("\tattribute :%d\n", a->gid.attr);
53 static void decode_sam_account_info(SAM_ACCOUNT_INFO *a)
55 fstring temp;
56 printf("\nUser Information\n");
57 printf("----------------\n");
59 unistr2_to_ascii(temp, &a->uni_acct_name, sizeof(temp)-1);
60 printf("\tUser name :%s\n", temp);
61 printf("\tuser's rid :%d\n", a->user_rid);
62 printf("\tuser's primary gid :%d\n", a->group_rid);
63 unistr2_to_ascii(temp, &a->uni_full_name, sizeof(temp)-1);
64 printf("\tfull name :%s\n", temp);
65 unistr2_to_ascii(temp, &a->uni_home_dir, sizeof(temp)-1);
66 printf("\thome directory :%s\n", temp);
67 unistr2_to_ascii(temp, &a->uni_dir_drive, sizeof(temp)-1);
68 printf("\tdrive :%s\n", temp);
69 unistr2_to_ascii(temp, &a->uni_logon_script, sizeof(temp)-1);
70 printf("\tlogon script :%s\n", temp);
71 unistr2_to_ascii(temp, &a->uni_acct_desc, sizeof(temp)-1);
72 printf("\tdescription :%s\n", temp);
73 unistr2_to_ascii(temp, &a->uni_workstations, sizeof(temp)-1);
74 printf("\tworkstations :%s\n", temp);
77 static void decode_sam_grp_mem_info(SAM_GROUP_MEM_INFO *a)
79 int i;
80 printf("\nGroup members information\n");
81 printf("-------------------------\n");
82 printf("\tnum members :%d\n", a->num_members);
84 for (i=0; i<a->num_members; i++) {
85 printf("\trid, attr:%d, %d\n", a->rids[i], a->attribs[i]);
89 static void decode_sam_alias_info(SAM_ALIAS_INFO *a)
91 fstring temp;
92 printf("\nAlias Information\n");
93 printf("-----------------\n");
95 unistr2_to_ascii(temp, &a->uni_als_name, sizeof(temp)-1);
96 printf("\tname :%s\n", temp);
97 unistr2_to_ascii(temp, &a->uni_als_desc, sizeof(temp)-1);
98 printf("\tdescription :%s\n", temp);
99 printf("\trid :%d\n", a->als_rid);
102 static void decode_sam_als_mem_info(SAM_ALIAS_MEM_INFO *a)
104 int i;
105 fstring temp;
106 printf("\nAlias members Information\n");
107 printf("-------------------------\n");
108 printf("\tnum members :%d\n", a->num_members);
109 printf("\tnum sids :%d\n", a->num_sids);
110 for (i=0; i<a->num_sids; i++) {
111 printf("\tsid :%s\n", sid_to_string(temp, &a->sids[i].sid));
117 static void decode_sam_dom_info(SAM_DELTA_DOM *a)
119 fstring temp;
120 printf("\nDomain information\n");
121 printf("------------------\n");
123 unistr2_to_ascii(temp, &a->domain_name, sizeof(temp)-1);
124 printf("\tdomain name :%s\n", temp);
125 printf("\tsid :%s\n", sid_to_string(temp, &a->domain_sid.sid));
128 static void decode_sam_unk0e_info(SAM_DELTA_UNK0E *a)
130 fstring temp;
131 printf("\nTrust information\n");
132 printf("-----------------\n");
134 unistr2_to_ascii(temp, &a->domain, sizeof(temp)-1);
135 printf("\tdomain name :%s\n", temp);
136 printf("\tsid :%s\n", sid_to_string(temp, &a->sid.sid));
137 display_sec_desc(a->sec_desc);
140 static void decode_sam_privs_info(SAM_DELTA_PRIVS *a)
142 int i;
143 fstring temp;
144 printf("\nSID and privileges information\n");
145 printf("------------------------------\n");
146 printf("\tsid :%s\n", sid_to_string(temp, &a->sid.sid));
147 display_sec_desc(a->sec_desc);
148 printf("\tprivileges count :%d\n", a->privlist_count);
149 for (i=0; i<a->privlist_count; i++) {
150 unistr2_to_ascii(temp, &a->uni_privslist[i], sizeof(temp)-1);
151 printf("\tprivilege name :%s\n", temp);
152 printf("\tattribute :%d\n", a->attributes[i]);
156 static void decode_sam_unk12_info(SAM_DELTA_UNK12 *a)
158 fstring temp;
159 printf("\nTrusted information\n");
160 printf("-------------------\n");
162 unistr2_to_ascii(temp, &a->secret, sizeof(temp)-1);
163 printf("\tsecret name :%s\n", temp);
164 display_sec_desc(a->sec_desc);
166 printf("\ttime 1 :%s\n", http_timestring(nt_time_to_unix(&a->time1)));
167 printf("\ttime 2 :%s\n", http_timestring(nt_time_to_unix(&a->time2)));
169 display_sec_desc(a->sec_desc2);
172 static void decode_sam_stamp(SAM_DELTA_STAMP *a)
174 printf("\nStamp information\n");
175 printf("-----------------\n");
176 printf("\tsequence number :%d\n", a->seqnum);
179 static void decode_sam_deltas(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas, SAM_DELTA_CTR *deltas)
181 int i;
182 for (i = 0; i < num_deltas; i++) {
183 switch (hdr_deltas[i].type) {
184 case SAM_DELTA_DOMAIN_INFO: {
185 SAM_DOMAIN_INFO *a;
186 a = &deltas[i].domain_info;
187 decode_domain_info(a);
188 break;
190 case SAM_DELTA_GROUP_INFO: {
191 SAM_GROUP_INFO *a;
192 a = &deltas[i].group_info;
193 decode_sam_group_info(a);
194 break;
196 case SAM_DELTA_ACCOUNT_INFO: {
197 SAM_ACCOUNT_INFO *a;
198 a = &deltas[i].account_info;
199 decode_sam_account_info(a);
200 break;
202 case SAM_DELTA_GROUP_MEM: {
203 SAM_GROUP_MEM_INFO *a;
204 a = &deltas[i].grp_mem_info;
205 decode_sam_grp_mem_info(a);
206 break;
208 case SAM_DELTA_ALIAS_INFO: {
209 SAM_ALIAS_INFO *a;
210 a = &deltas[i].alias_info;
211 decode_sam_alias_info(a);
212 break;
214 case SAM_DELTA_ALIAS_MEM: {
215 SAM_ALIAS_MEM_INFO *a;
216 a = &deltas[i].als_mem_info;
217 decode_sam_als_mem_info(a);
218 break;
220 case SAM_DELTA_POLICY_INFO: {
221 SAM_DELTA_POLICY *a;
222 a = &deltas[i].dom_info;
223 decode_sam_dom_info(a);
224 break;
226 case SAM_DELTA_UNK0E_INFO: {
227 SAM_DELTA_UNK0E *a;
228 a = &deltas[i].unk0e_info;
229 decode_sam_unk0e_info(a);
230 break;
232 case SAM_DELTA_PRIVS_INFO: {
233 SAM_DELTA_PRIVS *a;
234 a = &deltas[i].privs_info;
235 decode_sam_privs_info(a);
236 break;
238 case SAM_DELTA_UNK12_INFO: {
239 SAM_DELTA_UNK12 *a;
240 a = &deltas[i].unk12_info;
241 decode_sam_unk12_info(a);
242 break;
244 case SAM_DELTA_SAM_STAMP: {
245 SAM_DELTA_STAMP *a;
246 a = &deltas[i].stamp;
247 decode_sam_stamp(a);
248 break;
250 default:
251 DEBUG(0,("unknown delta type: %d\n", hdr_deltas[i].type));
252 break;
257 /* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */
259 static void sam_account_from_delta(SAM_ACCOUNT *account,
260 SAM_ACCOUNT_INFO *delta)
262 DOM_SID sid;
263 fstring s;
265 /* Username, fullname, home dir, dir drive, logon script, acct
266 desc, workstations, profile. */
268 unistr2_to_ascii(s, &delta->uni_acct_name, sizeof(s) - 1);
269 pdb_set_nt_username(account, s);
271 /* Unix username is the same - for sainity */
272 pdb_set_username(account, s);
274 unistr2_to_ascii(s, &delta->uni_full_name, sizeof(s) - 1);
275 pdb_set_fullname(account, s);
277 unistr2_to_ascii(s, &delta->uni_home_dir, sizeof(s) - 1);
278 pdb_set_homedir(account, s, True);
280 unistr2_to_ascii(s, &delta->uni_dir_drive, sizeof(s) - 1);
281 pdb_set_dir_drive(account, s, True);
283 unistr2_to_ascii(s, &delta->uni_logon_script, sizeof(s) - 1);
284 pdb_set_logon_script(account, s, True);
286 unistr2_to_ascii(s, &delta->uni_acct_desc, sizeof(s) - 1);
287 pdb_set_acct_desc(account, s);
289 unistr2_to_ascii(s, &delta->uni_workstations, sizeof(s) - 1);
290 pdb_set_workstations(account, s);
292 unistr2_to_ascii(s, &delta->uni_profile, sizeof(s) - 1);
293 pdb_set_profile_path(account, s, True);
295 /* User and group sid */
297 sid_copy(&sid, &domain_sid);
298 sid_append_rid(&sid, delta->user_rid);
299 pdb_set_user_sid(account, &sid);
301 sid_copy(&sid, &domain_sid);
302 sid_append_rid(&sid, delta->group_rid);
303 pdb_set_group_sid(account, &sid);
305 /* Logon and password information */
307 pdb_set_logon_time(account, nt_time_to_unix(&delta->logon_time), True);
308 pdb_set_logoff_time(account, nt_time_to_unix(&delta->logoff_time),
309 True);
311 pdb_set_logon_divs(account, delta->logon_divs);
313 /* TODO: logon hours */
314 /* TODO: bad password count */
315 /* TODO: logon count */
317 pdb_set_pass_last_set_time(
318 account, nt_time_to_unix(&delta->pwd_last_set_time));
320 /* TODO: account expiry time */
322 pdb_set_acct_ctrl(account, delta->acb_info);
325 static void apply_account_info(SAM_ACCOUNT_INFO *sam_acct_delta)
327 SAM_ACCOUNT *sam_acct;
328 BOOL result;
330 if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_acct))) {
331 return;
334 sam_account_from_delta(sam_acct, sam_acct_delta);
335 result = pdb_add_sam_account(sam_acct);
338 /* Apply an array of deltas to the SAM database */
340 static void apply_deltas(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas,
341 SAM_DELTA_CTR *deltas)
343 uint32 i;
345 for (i = 0; i < num_deltas; i++) {
346 switch(hdr_deltas[i].type) {
347 case SAM_DELTA_ACCOUNT_INFO:
348 apply_account_info(&deltas[i].account_info);
349 break;
354 /* Synchronise sam database */
356 static NTSTATUS sam_sync(struct cli_state *cli, unsigned char trust_passwd[16],
357 BOOL do_smbpasswd_output, BOOL verbose)
359 TALLOC_CTX *mem_ctx;
360 SAM_DELTA_HDR *hdr_deltas_0, *hdr_deltas_2;
361 SAM_DELTA_CTR *deltas_0, *deltas_2;
362 uint32 num_deltas_0, num_deltas_2;
363 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
364 struct pdb_context *in;
365 uint32 neg_flags = 0x000001ff;
367 DOM_CRED ret_creds;
369 /* Initialise */
371 if (!NT_STATUS_IS_OK(make_pdb_context_list(&in, lp_passdb_backend()))){
372 DEBUG(0, ("Can't initialize passdb backend.\n"));
373 return result;
376 if (!(mem_ctx = talloc_init())) {
377 DEBUG(0,("talloc_init failed\n"));
378 return result;
381 if (!cli_nt_session_open (cli, PIPE_NETLOGON)) {
382 DEBUG(0, ("Could not initialize netlogon pipe!\n"));
383 goto done;
386 /* Request a challenge */
388 if (!NT_STATUS_IS_OK(cli_nt_setup_creds(cli, SEC_CHAN_BDC, trust_passwd, &neg_flags, 2))) {
389 DEBUG(0, ("Error initialising session creds\n"));
390 goto done;
393 /* on first call the returnAuthenticator is empty */
394 memset(&ret_creds, 0, sizeof(ret_creds));
396 /* Do sam synchronisation on the SAM database*/
398 result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, 0, 0,
399 &num_deltas_0, &hdr_deltas_0,
400 &deltas_0);
402 if (!NT_STATUS_IS_OK(result))
403 goto done;
406 /* Update sam */
408 apply_deltas(num_deltas_0, hdr_deltas_0, deltas_0);
412 * we can't yet do several sam_sync in a raw, it's a credential problem
413 * we must chain the credentials
416 #if 1
417 /* Do sam synchronisation on the LSA database */
419 result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, 2, 0, &num_deltas_2, &hdr_deltas_2, &deltas_2);
421 if (!NT_STATUS_IS_OK(result))
422 goto done;
424 /* verbose mode */
425 if (verbose)
426 decode_sam_deltas(num_deltas_2, hdr_deltas_2, deltas_2);
427 #endif
429 /* Produce smbpasswd output - good for migrating from NT! */
431 if (do_smbpasswd_output) {
432 int i;
434 for (i = 0; i < num_deltas_0; i++) {
435 SAM_ACCOUNT_INFO *a;
436 fstring acct_name, hex_nt_passwd, hex_lm_passwd;
437 uchar lm_passwd[16], nt_passwd[16];
439 /* Skip non-user accounts */
441 if (hdr_deltas_0[i].type != SAM_DELTA_ACCOUNT_INFO)
442 continue;
444 a = &deltas_0[i].account_info;
446 unistr2_to_ascii(acct_name, &a->uni_acct_name,
447 sizeof(acct_name) - 1);
449 /* Decode hashes from password hash */
451 sam_pwd_hash(a->user_rid, a->pass.buf_lm_pwd,
452 lm_passwd, 0);
453 sam_pwd_hash(a->user_rid, a->pass.buf_nt_pwd,
454 nt_passwd, 0);
456 /* Encode as strings */
458 smbpasswd_sethexpwd(hex_lm_passwd, lm_passwd,
459 a->acb_info);
460 smbpasswd_sethexpwd(hex_nt_passwd, nt_passwd,
461 a->acb_info);
463 /* Display user info */
465 printf("%s:%d:%s:%s:%s:LCT-0\n", acct_name,
466 a->user_rid, hex_lm_passwd, hex_nt_passwd,
467 smbpasswd_encode_acb_info(a->acb_info));
470 goto done;
473 done:
474 cli_nt_session_close(cli);
475 talloc_destroy(mem_ctx);
477 return result;
480 /* Replicate sam deltas */
482 static NTSTATUS sam_repl(struct cli_state *cli, unsigned char trust_passwde[16],
483 uint32 low_serial)
485 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
487 return result;
490 /* Connect to primary domain controller */
492 static struct cli_state *init_connection(struct cli_state **cli,
493 char *username, char *domain,
494 char *password)
496 extern pstring global_myname;
497 struct in_addr *dest_ip;
498 int count;
499 fstring dest_host;
501 /* Initialise myname */
503 if (!global_myname[0]) {
504 char *p;
506 fstrcpy(global_myname, myhostname());
507 p = strchr(global_myname, '.');
508 if (p)
509 *p = 0;
512 /* Look up name of PDC controller */
514 if (!get_dc_list(True, lp_workgroup(), &dest_ip, &count)) {
515 DEBUG(0, ("Cannot find domain controller for domain %s\n",
516 lp_workgroup()));
517 return NULL;
520 if (!lookup_dc_name(global_myname, lp_workgroup(), dest_ip,
521 dest_host)) {
522 DEBUG(0, ("Could not lookup up PDC name for domain %s\n",
523 lp_workgroup()));
524 return NULL;
527 if (NT_STATUS_IS_OK(cli_full_connection(cli, global_myname, dest_host,
528 dest_ip, 0,
529 "IPC$", "IPC",
530 username, domain,
531 password, 0))) {
532 return *cli;
535 return NULL;
538 /* Main function */
540 static fstring popt_username, popt_domain, popt_password;
541 static BOOL popt_got_pass;
543 static void user_callback(poptContext con,
544 enum poptCallbackReason reason,
545 const struct poptOption *opt,
546 const char *arg, const void *data)
548 const char *p, *ch;
550 if (!arg)
551 return;
553 switch(opt->val) {
555 /* Check for [DOMAIN\\]username[%password]*/
557 case 'U':
559 p = arg;
561 if ((ch = strchr(p, '\\'))) {
562 fstrcpy(popt_domain, p);
563 popt_domain[ch - p] = 0;
566 fstrcpy(popt_username, p);
568 if ((ch = strchr(p, '%'))) {
569 popt_username[ch - p] = 0;
570 fstrcpy(popt_password, ch + 1);
571 popt_got_pass = True;
574 break;
576 case 'W':
577 fstrcpy(popt_domain, arg);
578 break;
582 /* Return domain, username and password passed in from cmd line */
584 void popt_common_get_auth_info(char **domain, char **username, char **password,
585 BOOL *got_pass)
587 *domain = popt_domain;
588 *username = popt_username;
589 *password = popt_password;
590 *got_pass = popt_got_pass;
593 struct poptOption popt_common_auth_info[] = {
594 { NULL, 0, POPT_ARG_CALLBACK, user_callback },
595 { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set username",
596 "[DOMAIN\\]username[%password]" },
597 { "domain", 'W', POPT_ARG_STRING, NULL, 'W', "Set domain name",
598 "DOMAIN"},
599 { 0 }
602 static BOOL popt_interactive;
604 BOOL popt_common_is_interactive(void)
606 return popt_interactive;
609 struct poptOption popt_common_interactive[] = {
610 { "interactive", 'i', POPT_ARG_NONE, &popt_interactive, 'i',
611 "Log to stdout" },
612 { 0 }
615 int main(int argc, char **argv)
617 BOOL do_sam_sync = False, do_sam_repl = False;
618 struct cli_state *cli;
619 NTSTATUS result;
620 pstring logfile;
621 BOOL do_smbpasswd_output = False;
622 BOOL verbose = True, got_pass = False;
623 uint32 serial = 0;
624 unsigned char trust_passwd[16];
625 char *username, *domain, *password;
626 poptContext pc;
627 char c;
629 struct poptOption popt_samsync_opts[] = {
630 { "synchronise", 'S', POPT_ARG_NONE, &do_sam_sync, 'S',
631 "Perform full SAM synchronisation" },
632 { "replicate", 'R', POPT_ARG_NONE, &do_sam_repl, 'R',
633 "Replicate SAM changes" },
634 { "serial", 0, POPT_ARG_INT, &serial, 0, "SAM serial number" },
635 { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
636 { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_auth_info },
637 { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_interactive },
638 POPT_AUTOHELP
639 { 0 }
642 /* Read command line options */
644 pc = poptGetContext("samsync", argc, (const char **)argv,
645 popt_samsync_opts, 0);
647 if (argc == 1) {
648 poptPrintUsage(pc, stdout, 0);
649 return 1;
652 while ((c = poptGetNextOpt(pc)) != -1) {
654 /* Argument processing error */
656 if (c < -1) {
657 fprintf(stderr, "samsync: %s: %s\n",
658 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
659 poptStrerror(c));
660 return 1;
663 /* Handle arguments */
665 switch (c) {
666 case 'h':
667 poptPrintHelp(pc, stdout, 0);
668 return 1;
669 case 'u':
670 poptPrintUsage(pc, stdout, 0);
671 return 1;
675 /* Bail out if any extra args were passed */
677 if (poptPeekArg(pc)) {
678 fprintf(stderr, "samsync: invalid argument %s\n",
679 poptPeekArg(pc));
680 poptPrintUsage(pc, stdout, 0);
681 return 1;
684 poptFreeContext(pc);
686 /* Setup logging */
688 dbf = x_stdout;
690 if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
691 d_fprintf(stderr, "samsync: error opening config file %s. "
692 "Error was %s\n", dyn_CONFIGFILE, strerror(errno));
693 return 1;
696 slprintf(logfile, sizeof(logfile) - 1, "%s/log.%s", dyn_LOGFILEBASE,
697 "samsync");
699 lp_set_logfile(logfile);
701 setup_logging("samsync", popt_common_is_interactive());
703 if (!popt_common_is_interactive())
704 reopen_logs();
706 load_interfaces();
708 /* Check arguments make sense */
710 if (do_sam_sync && do_sam_repl) {
711 DEBUG(0, ("cannot specify both -S and -R\n"));
712 return 1;
716 if (!do_sam_sync && !do_sam_repl) {
717 DEBUG(0, ("samsync: you must either --synchronise or "
718 "--replicate the SAM database\n"));
719 return 1;
722 if (do_sam_repl && serial == 0) {
723 DEBUG(0, ("samsync: must specify serial number\n"));
724 return 1;
727 if (do_sam_sync && serial != 0) {
728 DEBUG(0, ("samsync: you can't specify a serial number when "
729 "synchonising the SAM database\n"));
730 return 1;
733 /* BDC operations require the machine account password */
735 if (!secrets_init()) {
736 DEBUG(0, ("samsync: unable to initialise secrets database\n"));
737 return 1;
740 if (!secrets_fetch_trust_account_password(lp_workgroup(),
741 trust_passwd, NULL)) {
742 DEBUG(0, ("samsync: could not fetch trust account password\n"));
743 return 1;
746 /* I wish the domain sid wasn't stored in secrets.tdb */
748 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
749 DEBUG(0, ("samsync: could not retrieve domain sid\n"));
750 return 1;
753 /* Perform sync or replication */
755 popt_common_get_auth_info(&domain, &username, &password, &got_pass);
757 if (!init_connection(&cli, username, domain, password))
758 return 1;
760 if (do_sam_sync)
761 result = sam_sync(cli, trust_passwd, do_smbpasswd_output,
762 verbose);
764 if (do_sam_repl)
765 result = sam_repl(cli, trust_passwd, serial);
767 if (!NT_STATUS_IS_OK(result)) {
768 DEBUG(0, ("%s\n", nt_errstr(result)));
769 return 1;
772 return 0;