2 Unix SMB/Netbios implementation.
6 Copyright (C) Tim Potter 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* Synchronise sam database */
27 static NTSTATUS
sam_sync(struct cli_state
*cli
, unsigned char trust_passwd
[16],
28 BOOL do_smbpasswd_output
)
31 SAM_DELTA_HDR
*hdr_deltas
;
32 SAM_DELTA_CTR
*deltas
;
33 uint32 database_id
= 0, num_deltas
;
34 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
38 if (!(mem_ctx
= talloc_init())) {
39 DEBUG(0,("talloc_init failed\n"));
43 if (!cli_nt_session_open (cli
, PIPE_NETLOGON
)) {
44 DEBUG(0, ("Could not initialize netlogon pipe!\n"));
48 /* Request a challenge */
50 if (!NT_STATUS_IS_OK(new_cli_nt_setup_creds(cli
, trust_passwd
))) {
51 DEBUG(0, ("Error initialising session creds\n"));
55 /* Do sam synchronisation */
57 result
= cli_netlogon_sam_sync(cli
, mem_ctx
, database_id
,
58 &num_deltas
, &hdr_deltas
, &deltas
);
60 if (!NT_STATUS_IS_OK(result
)) {
64 /* Produce smbpasswd output - good for migrating from NT! */
66 if (do_smbpasswd_output
) {
69 for (i
= 0; i
< num_deltas
; i
++) {
71 fstring acct_name
, hex_nt_passwd
, hex_lm_passwd
;
72 uchar lm_passwd
[16], nt_passwd
[16];
74 /* Skip non-user accounts */
76 if (hdr_deltas
[i
].type
!= SAM_DELTA_ACCOUNT_INFO
)
79 a
= &deltas
[i
].account_info
;
81 unistr2_to_unix(acct_name
, &a
->uni_acct_name
,
82 sizeof(acct_name
) - 1);
84 /* Decode hashes from password hash */
86 sam_pwd_hash(a
->user_rid
, a
->pass
.buf_lm_pwd
,
88 sam_pwd_hash(a
->user_rid
, a
->pass
.buf_nt_pwd
,
91 /* Encode as strings */
93 smbpasswd_sethexpwd(hex_lm_passwd
, lm_passwd
,
95 smbpasswd_sethexpwd(hex_nt_passwd
, nt_passwd
,
98 /* Display user info */
100 printf("%s:%d:%s:%s:%s:LCT-0\n", acct_name
,
101 a
->user_rid
, hex_lm_passwd
, hex_nt_passwd
,
102 smbpasswd_encode_acb_info(
103 deltas
[i
].account_info
.acb_info
));
112 cli_nt_session_close(cli
);
113 talloc_destroy(mem_ctx
);
118 /* Replicate sam deltas */
120 static NTSTATUS
sam_repl(struct cli_state
*cli
, unsigned char trust_passwde
[16],
123 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
128 /* Print usage information */
130 static void usage(void)
132 printf("Usage: samsync [options]\n");
134 printf("\t-d debuglevel set the debuglevel\n");
135 printf("\t-h Print this help message.\n");
136 printf("\t-s configfile specify an alternative config file\n");
137 printf("\t-S synchronise sam database\n");
138 printf("\t-R replicate sam deltas\n");
139 printf("\t-U username username and password\n");
140 printf("\t-p produce smbpasswd output\n");
144 /* Initialise client credentials for authenticated pipe access */
146 void init_rpcclient_creds(struct ntuser_creds
*creds
, char* username
,
147 char* domain
, char* password
)
151 if (lp_encrypted_passwords()) {
152 pwd_make_lm_nt_16(&creds
->pwd
, password
);
154 pwd_set_cleartext(&creds
->pwd
, password
);
157 fstrcpy(creds
->user_name
, username
);
158 fstrcpy(creds
->domain
, domain
);
161 creds
->pwd
.null_pwd
= True
;
165 /* Connect to primary domain controller */
167 static struct cli_state
*init_connection(struct cli_state
*cli
,
168 char *username
, char *domain
,
171 struct ntuser_creds creds
;
172 extern pstring global_myname
;
173 struct in_addr
*dest_ip
;
174 struct nmb_name calling
, called
;
178 /* Initialise cli_state information */
182 if (!cli_initialise(cli
)) {
186 init_rpcclient_creds(&creds
, username
, domain
, password
);
187 cli_init_creds(cli
, &creds
);
189 /* Look up name of PDC controller */
191 if (!get_dc_list(True
, lp_workgroup(), &dest_ip
, &count
)) {
192 DEBUG(0, ("Cannot find domain controller for domain %s\n",
197 if (!lookup_pdc_name(global_myname
, lp_workgroup(), dest_ip
,
199 DEBUG(0, ("Could not lookup up PDC name for domain %s\n",
204 get_myname((*global_myname
)?NULL
:global_myname
);
205 strupper(global_myname
);
207 make_nmb_name(&called
, dns_to_netbios_name(dest_host
), 0x20);
208 make_nmb_name(&calling
, dns_to_netbios_name(global_myname
), 0);
210 /* Establish a SMB connection */
212 if (!cli_establish_connection(cli
, dest_host
, dest_ip
, &calling
,
213 &called
, "IPC$", "IPC", False
, True
)) {
222 int main(int argc
, char **argv
)
224 BOOL do_sam_sync
= False
, do_sam_repl
= False
;
225 pstring servicesf
= CONFIGFILE
;
226 struct cli_state cli
;
230 BOOL interactive
= False
, do_smbpasswd_output
= False
;
231 uint32 low_serial
= 0;
232 unsigned char trust_passwd
[16];
233 fstring username
, domain
, password
;
240 ZERO_STRUCT(username
);
242 ZERO_STRUCT(password
);
244 /* Parse command line options */
246 while((opt
= getopt(argc
, argv
, "s:d:SR:hiU:W:p")) != EOF
) {
249 pstrcpy(servicesf
, optarg
);
252 DEBUGLEVEL
= atoi(optarg
);
259 low_serial
= atoi(optarg
);
267 fstrcpy(username
,optarg
);
268 if ((lp
=strchr(username
,'%'))) {
270 fstrcpy(password
,lp
+1);
271 memset(strchr(optarg
, '%') + 1, 'X',
277 pstrcpy(domain
, optarg
);
280 do_smbpasswd_output
= True
;
296 /* Initialise samba */
298 slprintf(logfile
, sizeof(logfile
) - 1, "%s/log.%s", LOGFILEBASE
,
300 lp_set_logfile(logfile
);
302 setup_logging("samsync", interactive
);
307 if (!lp_load(servicesf
, True
, False
, False
)) {
308 fprintf(stderr
, "Can't load %s\n", servicesf
);
315 /* Check arguments make sense */
317 if (do_sam_sync
&& do_sam_repl
) {
318 fprintf(stderr
, "cannot specify both -S and -R\n");
323 if (!do_sam_sync
&& !do_sam_repl
) {
324 fprintf(stderr
, "must specify either -S or -R\n");
328 if (do_sam_repl
&& low_serial
== 0) {
329 fprintf(stderr
, "serial number must be positive\n");
333 /* BDC operations require the machine account password */
335 if (!secrets_init()) {
336 DEBUG(0, ("Unable to initialise secrets database\n"));
340 if (!secrets_fetch_trust_account_password(lp_workgroup(),
341 trust_passwd
, NULL
)) {
342 DEBUG(0, ("could not fetch trust account password\n"));
346 /* Perform sync or replication */
348 if (!init_connection(&cli
, username
, domain
, password
))
352 result
= sam_sync(&cli
, trust_passwd
, do_smbpasswd_output
);
355 result
= sam_repl(&cli
, trust_passwd
, low_serial
);
357 if (!NT_STATUS_IS_OK(result
)) {
358 DEBUG(0, ("%s\n", get_nt_error_msg(result
)));