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   Modified by Volker Lendecke 2002
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "includes.h"
25#include "utils/net.h"
26
27extern DOM_SID global_sid_Builtin;
28
29static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g)
30{
31	int i;
32	d_printf("Group mem %u: ", rid);
33	for (i=0;i<g->num_members;i++) {
34		d_printf("%u ", g->rids[i]);
35	}
36	d_printf("\n");
37}
38
39
40static const char *display_time(NTTIME *nttime)
41{
42	static fstring string;
43
44	float high;
45	float low;
46	int sec;
47	int days, hours, mins, secs;
48	int offset = 1;
49
50	if (nttime->high==0 && nttime->low==0)
51		return "Now";
52
53	if (nttime->high==0x80000000 && nttime->low==0)
54		return "Never";
55
56	high = 65536;
57	high = high/10000;
58	high = high*65536;
59	high = high/1000;
60	high = high * (~nttime->high);
61
62	low = ~nttime->low;
63	low = low/(1000*1000*10);
64
65	sec=high+low;
66	sec+=offset;
67
68	days=sec/(60*60*24);
69	hours=(sec - (days*60*60*24)) / (60*60);
70	mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
71	secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
72
73	fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
74	return (string);
75}
76
77
78static void display_alias_info(uint32 rid, SAM_ALIAS_INFO *a)
79{
80	d_printf("Alias '%s' ", unistr2_static(&a->uni_als_name));
81	d_printf("desc='%s' rid=%u\n", unistr2_static(&a->uni_als_desc), a->als_rid);
82}
83
84static void display_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *a)
85{
86	int i;
87	d_printf("Alias rid %u: ", rid);
88	for (i=0;i<a->num_members;i++) {
89		d_printf("%s ", sid_string_static(&a->sids[i].sid));
90	}
91	d_printf("\n");
92}
93
94static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a)
95{
96	fstring hex_nt_passwd, hex_lm_passwd;
97	uchar lm_passwd[16], nt_passwd[16];
98	static uchar zero_buf[16];
99
100	/* Decode hashes from password hash (if they are not NULL) */
101
102	if (memcmp(a->pass.buf_lm_pwd, zero_buf, 16) != 0) {
103		sam_pwd_hash(a->user_rid, a->pass.buf_lm_pwd, lm_passwd, 0);
104		pdb_sethexpwd(hex_lm_passwd, lm_passwd, a->acb_info);
105	} else {
106		pdb_sethexpwd(hex_lm_passwd, NULL, 0);
107	}
108
109	if (memcmp(a->pass.buf_nt_pwd, zero_buf, 16) != 0) {
110		sam_pwd_hash(a->user_rid, a->pass.buf_nt_pwd, nt_passwd, 0);
111		pdb_sethexpwd(hex_nt_passwd, nt_passwd, a->acb_info);
112	} else {
113		pdb_sethexpwd(hex_nt_passwd, NULL, 0);
114	}
115
116	printf("%s:%d:%s:%s:%s:LCT-0\n", unistr2_static(&a->uni_acct_name),
117	       a->user_rid, hex_lm_passwd, hex_nt_passwd,
118	       pdb_encode_acct_ctrl(a->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN));
119}
120
121static void display_domain_info(SAM_DOMAIN_INFO *a)
122{
123	time_t u_logout;
124
125	u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff);
126
127	d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name));
128
129	d_printf("Minimal Password Length: %d\n", a->min_pwd_len);
130	d_printf("Password History Length: %d\n", a->pwd_history_len);
131
132	d_printf("Force Logoff: %d\n", (int)u_logout);
133
134	d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age));
135	d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age));
136
137	d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration));
138	d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count));
139
140	d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout);
141	d_printf("User must logon to change password: %d\n", a->logon_chgpass);
142}
143
144static void display_group_info(uint32 rid, SAM_GROUP_INFO *a)
145{
146	d_printf("Group '%s' ", unistr2_static(&a->uni_grp_name));
147	d_printf("desc='%s', rid=%u\n", unistr2_static(&a->uni_grp_desc), rid);
148}
149
150static void display_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta)
151{
152	switch (hdr_delta->type) {
153	case SAM_DELTA_ACCOUNT_INFO:
154		display_account_info(hdr_delta->target_rid, &delta->account_info);
155		break;
156	case SAM_DELTA_GROUP_MEM:
157		display_group_mem_info(hdr_delta->target_rid, &delta->grp_mem_info);
158		break;
159	case SAM_DELTA_ALIAS_INFO:
160		display_alias_info(hdr_delta->target_rid, &delta->alias_info);
161		break;
162	case SAM_DELTA_ALIAS_MEM:
163		display_alias_mem(hdr_delta->target_rid, &delta->als_mem_info);
164		break;
165	case SAM_DELTA_DOMAIN_INFO:
166		display_domain_info(&delta->domain_info);
167		break;
168	case SAM_DELTA_GROUP_INFO:
169		display_group_info(hdr_delta->target_rid, &delta->group_info);
170		break;
171		/* The following types are recognised but not handled */
172	case SAM_DELTA_RENAME_GROUP:
173		d_printf("SAM_DELTA_RENAME_GROUP not handled\n");
174		break;
175	case SAM_DELTA_RENAME_USER:
176		d_printf("SAM_DELTA_RENAME_USER not handled\n");
177		break;
178	case SAM_DELTA_RENAME_ALIAS:
179		d_printf("SAM_DELTA_RENAME_ALIAS not handled\n");
180		break;
181	case SAM_DELTA_POLICY_INFO:
182		d_printf("SAM_DELTA_POLICY_INFO not handled\n");
183		break;
184	case SAM_DELTA_TRUST_DOMS:
185		d_printf("SAM_DELTA_TRUST_DOMS not handled\n");
186		break;
187	case SAM_DELTA_PRIVS_INFO:
188		d_printf("SAM_DELTA_PRIVS_INFO not handled\n");
189		break;
190	case SAM_DELTA_SECRET_INFO:
191		d_printf("SAM_DELTA_SECRET_INFO not handled\n");
192		break;
193	case SAM_DELTA_DELETE_GROUP:
194		d_printf("SAM_DELTA_DELETE_GROUP not handled\n");
195		break;
196	case SAM_DELTA_DELETE_USER:
197		d_printf("SAM_DELTA_DELETE_USER not handled\n");
198		break;
199	case SAM_DELTA_MODIFIED_COUNT:
200		d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n");
201		break;
202	default:
203		d_printf("Unknown delta record type %d\n", hdr_delta->type);
204		break;
205	}
206}
207
208
209static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds)
210{
211	unsigned sync_context = 0;
212        NTSTATUS result;
213	int i;
214        TALLOC_CTX *mem_ctx;
215        SAM_DELTA_HDR *hdr_deltas;
216        SAM_DELTA_CTR *deltas;
217        uint32 num_deltas;
218
219	if (!(mem_ctx = talloc_init("dump_database"))) {
220		return;
221	}
222
223	switch( db_type ) {
224	case SAM_DATABASE_DOMAIN:
225		d_printf("Dumping DOMAIN database\n");
226		break;
227	case SAM_DATABASE_BUILTIN:
228		d_printf("Dumping BUILTIN database\n");
229		break;
230	case SAM_DATABASE_PRIVS:
231		d_printf("Dumping PRIVS databases\n");
232		break;
233	default:
234		d_printf("Dumping unknown database type %u\n", db_type );
235		break;
236	}
237
238	do {
239		result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, db_type,
240					       sync_context,
241					       &num_deltas, &hdr_deltas, &deltas);
242		if (NT_STATUS_IS_ERR(result))
243			break;
244
245		clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), ret_creds);
246                for (i = 0; i < num_deltas; i++) {
247			display_sam_entry(&hdr_deltas[i], &deltas[i]);
248                }
249		sync_context += 1;
250	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
251
252	talloc_destroy(mem_ctx);
253}
254
255/* dump sam database via samsync rpc calls */
256NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid,
257			       const char *domain_name,
258			       struct cli_state *cli, TALLOC_CTX *mem_ctx,
259			       int argc, const char **argv)
260{
261	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
262	uchar trust_password[16];
263	DOM_CRED ret_creds;
264	uint32 sec_channel;
265
266	ZERO_STRUCT(ret_creds);
267
268	fstrcpy(cli->domain, domain_name);
269
270	if (!secrets_fetch_trust_account_password(domain_name,
271						  trust_password,
272						  NULL, &sec_channel)) {
273		DEBUG(0,("Could not fetch trust account password\n"));
274		goto fail;
275	}
276
277	if (!NT_STATUS_IS_OK(nt_status = cli_nt_establish_netlogon(cli, sec_channel,
278								   trust_password))) {
279		DEBUG(0,("Error connecting to NETLOGON pipe\n"));
280		goto fail;
281	}
282
283	dump_database(cli, SAM_DATABASE_DOMAIN, &ret_creds);
284	dump_database(cli, SAM_DATABASE_BUILTIN, &ret_creds);
285	dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds);
286
287        nt_status = NT_STATUS_OK;
288
289fail:
290	cli_nt_session_close(cli);
291	return nt_status;
292}
293
294/* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */
295#define STRING_CHANGED (old_string && !new_string) ||\
296		    (!old_string && new_string) ||\
297		(old_string && new_string && (strcmp(old_string, new_string) != 0))
298
299static NTSTATUS
300sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)
301{
302	const char *old_string, *new_string;
303	time_t unix_time, stored_time;
304	uchar lm_passwd[16], nt_passwd[16];
305	static uchar zero_buf[16];
306
307	/* Username, fullname, home dir, dir drive, logon script, acct
308	   desc, workstations, profile. */
309
310	if (delta->hdr_acct_name.buffer) {
311		old_string = pdb_get_nt_username(account);
312		new_string = unistr2_static(&delta->uni_acct_name);
313
314		if (STRING_CHANGED) {
315			pdb_set_nt_username(account, new_string, PDB_CHANGED);
316
317		}
318
319		/* Unix username is the same - for sanity */
320		old_string = pdb_get_username( account );
321		if (STRING_CHANGED) {
322			pdb_set_username(account, new_string, PDB_CHANGED);
323		}
324	}
325
326	if (delta->hdr_full_name.buffer) {
327		old_string = pdb_get_fullname(account);
328		new_string = unistr2_static(&delta->uni_full_name);
329
330		if (STRING_CHANGED)
331			pdb_set_fullname(account, new_string, PDB_CHANGED);
332	}
333
334	if (delta->hdr_home_dir.buffer) {
335		old_string = pdb_get_homedir(account);
336		new_string = unistr2_static(&delta->uni_home_dir);
337
338		if (STRING_CHANGED)
339			pdb_set_homedir(account, new_string, PDB_CHANGED);
340	}
341
342	if (delta->hdr_dir_drive.buffer) {
343		old_string = pdb_get_dir_drive(account);
344		new_string = unistr2_static(&delta->uni_dir_drive);
345
346		if (STRING_CHANGED)
347			pdb_set_dir_drive(account, new_string, PDB_CHANGED);
348	}
349
350	if (delta->hdr_logon_script.buffer) {
351		old_string = pdb_get_logon_script(account);
352		new_string = unistr2_static(&delta->uni_logon_script);
353
354		if (STRING_CHANGED)
355			pdb_set_logon_script(account, new_string, PDB_CHANGED);
356	}
357
358	if (delta->hdr_acct_desc.buffer) {
359		old_string = pdb_get_acct_desc(account);
360		new_string = unistr2_static(&delta->uni_acct_desc);
361
362		if (STRING_CHANGED)
363			pdb_set_acct_desc(account, new_string, PDB_CHANGED);
364	}
365
366	if (delta->hdr_workstations.buffer) {
367		old_string = pdb_get_workstations(account);
368		new_string = unistr2_static(&delta->uni_workstations);
369
370		if (STRING_CHANGED)
371			pdb_set_workstations(account, new_string, PDB_CHANGED);
372	}
373
374	if (delta->hdr_profile.buffer) {
375		old_string = pdb_get_profile_path(account);
376		new_string = unistr2_static(&delta->uni_profile);
377
378		if (STRING_CHANGED)
379			pdb_set_profile_path(account, new_string, PDB_CHANGED);
380	}
381
382	if (delta->hdr_parameters.buffer) {
383		DATA_BLOB mung;
384		old_string = pdb_get_munged_dial(account);
385		mung.length = delta->hdr_parameters.uni_str_len;
386		mung.data = (uint8 *) delta->uni_parameters.buffer;
387		new_string = (mung.length == 0) ? NULL : base64_encode_data_blob(mung);
388
389		if (STRING_CHANGED)
390			pdb_set_munged_dial(account, new_string, PDB_CHANGED);
391	}
392
393	/* User and group sid */
394	if (pdb_get_user_rid(account) != delta->user_rid)
395		pdb_set_user_sid_from_rid(account, delta->user_rid, PDB_CHANGED);
396	if (pdb_get_group_rid(account) != delta->group_rid)
397		pdb_set_group_sid_from_rid(account, delta->group_rid, PDB_CHANGED);
398
399	/* Logon and password information */
400	if (!nt_time_is_zero(&delta->logon_time)) {
401		unix_time = nt_time_to_unix(&delta->logon_time);
402		stored_time = pdb_get_logon_time(account);
403		if (stored_time != unix_time)
404			pdb_set_logon_time(account, unix_time, PDB_CHANGED);
405	}
406
407	if (!nt_time_is_zero(&delta->logoff_time)) {
408		unix_time = nt_time_to_unix(&delta->logoff_time);
409		stored_time = pdb_get_logoff_time(account);
410		if (stored_time != unix_time)
411			pdb_set_logoff_time(account, unix_time,PDB_CHANGED);
412	}
413
414	/* Logon Divs */
415	if (pdb_get_logon_divs(account) != delta->logon_divs)
416		pdb_set_logon_divs(account, delta->logon_divs, PDB_CHANGED);
417
418	/* Max Logon Hours */
419	if (delta->unknown1 != pdb_get_unknown_6(account)) {
420		pdb_set_unknown_6(account, delta->unknown1, PDB_CHANGED);
421	}
422
423	/* Logon Hours Len */
424	if (delta->buf_logon_hrs.buf_len != pdb_get_hours_len(account)) {
425		pdb_set_hours_len(account, delta->buf_logon_hrs.buf_len, PDB_CHANGED);
426	}
427
428	/* Logon Hours */
429	if (delta->buf_logon_hrs.buffer) {
430		pstring old, new;
431		pdb_sethexhours(old, pdb_get_hours(account));
432		pdb_sethexhours(new, (const char *)delta->buf_logon_hrs.buffer);
433		if (!strequal(old, new))
434			pdb_set_hours(account, (const char *)delta->buf_logon_hrs.buffer, PDB_CHANGED);
435	}
436
437	if (pdb_get_bad_password_count(account) != delta->bad_pwd_count)
438		pdb_set_bad_password_count(account, delta->bad_pwd_count, PDB_CHANGED);
439
440	if (pdb_get_logon_count(account) != delta->logon_count)
441		pdb_set_logon_count(account, delta->logon_count, PDB_CHANGED);
442
443	if (!nt_time_is_zero(&delta->pwd_last_set_time)) {
444		unix_time = nt_time_to_unix(&delta->pwd_last_set_time);
445		stored_time = pdb_get_pass_last_set_time(account);
446		if (stored_time != unix_time)
447			pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED);
448	} else {
449		/* no last set time, make it now */
450		pdb_set_pass_last_set_time(account, time(NULL), PDB_CHANGED);
451	}
452
453#if 0
454/*	No kickoff time in the delta? */
455	if (!nt_time_is_zero(&delta->kickoff_time)) {
456		unix_time = nt_time_to_unix(&delta->kickoff_time);
457		stored_time = pdb_get_kickoff_time(account);
458		if (stored_time != unix_time)
459			pdb_set_kickoff_time(account, unix_time, PDB_CHANGED);
460	}
461#endif
462
463	/* Decode hashes from password hash
464	   Note that win2000 may send us all zeros for the hashes if it doesn't
465	   think this channel is secure enough - don't set the passwords at all
466	   in that case
467	*/
468	if (memcmp(delta->pass.buf_lm_pwd, zero_buf, 16) != 0) {
469		sam_pwd_hash(delta->user_rid, delta->pass.buf_lm_pwd, lm_passwd, 0);
470		pdb_set_lanman_passwd(account, lm_passwd, PDB_CHANGED);
471	}
472
473	if (memcmp(delta->pass.buf_nt_pwd, zero_buf, 16) != 0) {
474		sam_pwd_hash(delta->user_rid, delta->pass.buf_nt_pwd, nt_passwd, 0);
475		pdb_set_nt_passwd(account, nt_passwd, PDB_CHANGED);
476	}
477
478	/* TODO: account expiry time */
479
480	if (pdb_get_acct_ctrl(account) != delta->acb_info)
481		pdb_set_acct_ctrl(account, delta->acb_info, PDB_CHANGED);
482
483	pdb_set_domain(account, lp_workgroup(), PDB_CHANGED);
484
485	return NT_STATUS_OK;
486}
487
488static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
489{
490	NTSTATUS nt_ret;
491	fstring account;
492	pstring add_script;
493	SAM_ACCOUNT *sam_account=NULL;
494	GROUP_MAP map;
495	struct group *grp;
496	DOM_SID user_sid;
497	DOM_SID group_sid;
498	struct passwd *passwd;
499	fstring sid_string;
500
501	fstrcpy(account, unistr2_static(&delta->uni_acct_name));
502	d_printf("Creating account: %s\n", account);
503
504	if (!NT_STATUS_IS_OK(nt_ret = pdb_init_sam(&sam_account)))
505		return nt_ret;
506
507	if (!(passwd = Get_Pwnam(account))) {
508		/* Create appropriate user */
509		if (delta->acb_info & ACB_NORMAL) {
510			pstrcpy(add_script, lp_adduser_script());
511		} else if ( (delta->acb_info & ACB_WSTRUST) ||
512			    (delta->acb_info & ACB_SVRTRUST) ||
513			    (delta->acb_info & ACB_DOMTRUST) ) {
514			pstrcpy(add_script, lp_addmachine_script());
515		} else {
516			DEBUG(1, ("Unknown user type: %s\n",
517				  pdb_encode_acct_ctrl(delta->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
518			nt_ret = NT_STATUS_UNSUCCESSFUL;
519			goto done;
520		}
521		if (*add_script) {
522			int add_ret;
523			all_string_sub(add_script, "%u", account,
524				       sizeof(account));
525			add_ret = smbrun(add_script,NULL);
526			DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
527				 "gave %d\n", add_script, add_ret));
528		} else {
529			DEBUG(8,("fetch_account_info: no add user/machine script.  Asking winbindd\n"));
530
531			/* don't need a RID allocated since the user already has a SID */
532			if ( !winbind_create_user( account, NULL ) )
533				DEBUG(4,("fetch_account_info: winbind_create_user() failed\n"));
534		}
535
536		/* try and find the possible unix account again */
537		if ( !(passwd = Get_Pwnam(account)) ) {
538			d_printf("Could not create posix account info for '%s'\n", account);
539			nt_ret = NT_STATUS_NO_SUCH_USER;
540			goto done;
541		}
542	}
543
544	sid_copy(&user_sid, get_global_sam_sid());
545	sid_append_rid(&user_sid, delta->user_rid);
546
547	DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n", sid_to_string(sid_string, &user_sid), account));
548	if (!pdb_getsampwsid(sam_account, &user_sid)) {
549		sam_account_from_delta(sam_account, delta);
550		DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
551			  sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
552		if (!pdb_add_sam_account(sam_account)) {
553			DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
554				  account));
555			return NT_STATUS_ACCESS_DENIED;
556		}
557	} else {
558		sam_account_from_delta(sam_account, delta);
559		DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
560			  sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
561		if (!pdb_update_sam_account(sam_account)) {
562			DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
563				  account));
564			pdb_free_sam(&sam_account);
565			return NT_STATUS_ACCESS_DENIED;
566		}
567	}
568
569	group_sid = *pdb_get_group_sid(sam_account);
570
571	if (!pdb_getgrsid(&map, group_sid)) {
572		DEBUG(0, ("Primary group of %s has no mapping!\n",
573			  pdb_get_username(sam_account)));
574	} else {
575		if (map.gid != passwd->pw_gid) {
576			if (!(grp = getgrgid(map.gid))) {
577				DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
578					  (unsigned long)map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid)));
579			} else {
580				smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account));
581			}
582		}
583	}
584
585	if ( !passwd ) {
586		DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
587			pdb_get_username(sam_account)));
588	}
589
590 done:
591	pdb_free_sam(&sam_account);
592	return nt_ret;
593}
594
595static NTSTATUS
596fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)
597{
598	fstring name;
599	fstring comment;
600	struct group *grp = NULL;
601	DOM_SID group_sid;
602	fstring sid_string;
603	GROUP_MAP map;
604	BOOL insert = True;
605
606	unistr2_to_ascii(name, &delta->uni_grp_name, sizeof(name)-1);
607	unistr2_to_ascii(comment, &delta->uni_grp_desc, sizeof(comment)-1);
608
609	/* add the group to the mapping table */
610	sid_copy(&group_sid, get_global_sam_sid());
611	sid_append_rid(&group_sid, rid);
612	sid_to_string(sid_string, &group_sid);
613
614	if (pdb_getgrsid(&map, group_sid)) {
615		if ( map.gid != -1 )
616			grp = getgrgid(map.gid);
617		insert = False;
618	}
619
620	if (grp == NULL) {
621		gid_t gid;
622
623		/* No group found from mapping, find it from its name. */
624		if ((grp = getgrnam(name)) == NULL) {
625
626			/* No appropriate group found, create one */
627
628			d_printf("Creating unix group: '%s'\n", name);
629
630			if (smb_create_group(name, &gid) != 0)
631				return NT_STATUS_ACCESS_DENIED;
632
633			if ((grp = getgrnam(name)) == NULL)
634				return NT_STATUS_ACCESS_DENIED;
635		}
636	}
637
638	map.gid = grp->gr_gid;
639	map.sid = group_sid;
640	map.sid_name_use = SID_NAME_DOM_GRP;
641	fstrcpy(map.nt_name, name);
642	if (delta->hdr_grp_desc.buffer) {
643		fstrcpy(map.comment, comment);
644	} else {
645		fstrcpy(map.comment, "");
646	}
647
648	if (insert)
649		pdb_add_group_mapping_entry(&map);
650	else
651		pdb_update_group_mapping_entry(&map);
652
653	return NT_STATUS_OK;
654}
655
656static NTSTATUS
657fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
658{
659	int i;
660	TALLOC_CTX *t = NULL;
661	char **nt_members = NULL;
662	char **unix_members;
663	DOM_SID group_sid;
664	GROUP_MAP map;
665	struct group *grp;
666
667	if (delta->num_members == 0) {
668		return NT_STATUS_OK;
669	}
670
671	sid_copy(&group_sid, get_global_sam_sid());
672	sid_append_rid(&group_sid, rid);
673
674	if (!get_domain_group_from_sid(group_sid, &map)) {
675		DEBUG(0, ("Could not find global group %d\n", rid));
676		return NT_STATUS_NO_SUCH_GROUP;
677	}
678
679	if (!(grp = getgrgid(map.gid))) {
680		DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map.gid));
681		return NT_STATUS_NO_SUCH_GROUP;
682	}
683
684	d_printf("Group members of %s: ", grp->gr_name);
685
686	if (!(t = talloc_init("fetch_group_mem_info"))) {
687		DEBUG(0, ("could not talloc_init\n"));
688		return NT_STATUS_NO_MEMORY;
689	}
690
691	nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
692
693	for (i=0; i<delta->num_members; i++) {
694		NTSTATUS nt_status;
695		SAM_ACCOUNT *member = NULL;
696		DOM_SID member_sid;
697
698		if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
699			talloc_destroy(t);
700			return nt_status;
701		}
702
703		sid_copy(&member_sid, get_global_sam_sid());
704		sid_append_rid(&member_sid, delta->rids[i]);
705
706		if (!pdb_getsampwsid(member, &member_sid)) {
707			DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n",
708				  delta->rids[i], sid_string_static(&member_sid), grp->gr_name));
709			pdb_free_sam(&member);
710			continue;
711		}
712
713		if (pdb_get_group_rid(member) == rid) {
714			d_printf("%s(primary),", pdb_get_username(member));
715			pdb_free_sam(&member);
716			continue;
717		}
718
719		d_printf("%s,", pdb_get_username(member));
720		nt_members[i] = talloc_strdup(t, pdb_get_username(member));
721		pdb_free_sam(&member);
722	}
723
724	d_printf("\n");
725
726	unix_members = grp->gr_mem;
727
728	while (*unix_members) {
729		BOOL is_nt_member = False;
730		for (i=0; i<delta->num_members; i++) {
731			if (nt_members[i] == NULL) {
732				/* This was a primary group */
733				continue;
734			}
735
736			if (strcmp(*unix_members, nt_members[i]) == 0) {
737				is_nt_member = True;
738				break;
739			}
740		}
741		if (!is_nt_member) {
742			/* We look at a unix group member that is not
743			   an nt group member. So, remove it. NT is
744			   boss here. */
745			smb_delete_user_group(grp->gr_name, *unix_members);
746		}
747		unix_members += 1;
748	}
749
750	for (i=0; i<delta->num_members; i++) {
751		BOOL is_unix_member = False;
752
753		if (nt_members[i] == NULL) {
754			/* This was the primary group */
755			continue;
756		}
757
758		unix_members = grp->gr_mem;
759
760		while (*unix_members) {
761			if (strcmp(*unix_members, nt_members[i]) == 0) {
762				is_unix_member = True;
763				break;
764			}
765			unix_members += 1;
766		}
767
768		if (!is_unix_member) {
769			/* We look at a nt group member that is not a
770                           unix group member currently. So, add the nt
771                           group member. */
772			smb_add_user_group(grp->gr_name, nt_members[i]);
773		}
774	}
775
776	talloc_destroy(t);
777	return NT_STATUS_OK;
778}
779
780static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,
781				 DOM_SID dom_sid)
782{
783	fstring name;
784	fstring comment;
785	struct group *grp = NULL;
786	DOM_SID alias_sid;
787	fstring sid_string;
788	GROUP_MAP map;
789	BOOL insert = True;
790
791	unistr2_to_ascii(name, &delta->uni_als_name, sizeof(name)-1);
792	unistr2_to_ascii(comment, &delta->uni_als_desc, sizeof(comment)-1);
793
794	/* Find out whether the group is already mapped */
795	sid_copy(&alias_sid, &dom_sid);
796	sid_append_rid(&alias_sid, rid);
797	sid_to_string(sid_string, &alias_sid);
798
799	if (pdb_getgrsid(&map, alias_sid)) {
800		grp = getgrgid(map.gid);
801		insert = False;
802	}
803
804	if (grp == NULL) {
805		gid_t gid;
806
807		/* No group found from mapping, find it from its name. */
808		if ((grp = getgrnam(name)) == NULL) {
809			/* No appropriate group found, create one */
810			d_printf("Creating unix group: '%s'\n", name);
811			if (smb_create_group(name, &gid) != 0)
812				return NT_STATUS_ACCESS_DENIED;
813			if ((grp = getgrgid(gid)) == NULL)
814				return NT_STATUS_ACCESS_DENIED;
815		}
816	}
817
818	map.gid = grp->gr_gid;
819	map.sid = alias_sid;
820
821	if (sid_equal(&dom_sid, &global_sid_Builtin))
822		map.sid_name_use = SID_NAME_WKN_GRP;
823	else
824		map.sid_name_use = SID_NAME_ALIAS;
825
826	fstrcpy(map.nt_name, name);
827	fstrcpy(map.comment, comment);
828
829	if (insert)
830		pdb_add_group_mapping_entry(&map);
831	else
832		pdb_update_group_mapping_entry(&map);
833
834	return NT_STATUS_OK;
835}
836
837static NTSTATUS
838fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
839{
840#if 0 	/*
841	 * commented out right now after talking to Volker.  Can't
842	 * do much with the membership but seemed a shame to waste
843	 * somewhat working code.  Needs testing because the membership
844	 * that shows up surprises me.  Also can't do much with groups
845	 * in groups (e.g. Domain Admins being a member of Adminsitrators).
846	 * --jerry
847	 */
848
849	int i;
850	TALLOC_CTX *t = NULL;
851	char **nt_members = NULL;
852	char **unix_members;
853	DOM_SID group_sid;
854	GROUP_MAP map;
855	struct group *grp;
856	enum SID_NAME_USE sid_type;
857
858	if (delta->num_members == 0) {
859		return NT_STATUS_OK;
860	}
861
862	sid_copy(&group_sid, &dom_sid);
863	sid_append_rid(&group_sid, rid);
864
865	if (sid_equal(&dom_sid, &global_sid_Builtin)) {
866		sid_type = SID_NAME_WKN_GRP;
867		if (!get_builtin_group_from_sid(&group_sid, &map, False)) {
868			DEBUG(0, ("Could not find builtin group %s\n", sid_string_static(&group_sid)));
869			return NT_STATUS_NO_SUCH_GROUP;
870		}
871	} else {
872		sid_type = SID_NAME_ALIAS;
873		if (!get_local_group_from_sid(&group_sid, &map, False)) {
874			DEBUG(0, ("Could not find local group %s\n", sid_string_static(&group_sid)));
875			return NT_STATUS_NO_SUCH_GROUP;
876		}
877	}
878
879	if (!(grp = getgrgid(map.gid))) {
880		DEBUG(0, ("Could not find unix group %d\n", map.gid));
881		return NT_STATUS_NO_SUCH_GROUP;
882	}
883
884	d_printf("Group members of %s: ", grp->gr_name);
885
886	if (!(t = talloc_init("fetch_group_mem_info"))) {
887		DEBUG(0, ("could not talloc_init\n"));
888		return NT_STATUS_NO_MEMORY;
889	}
890
891	nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
892
893	for (i=0; i<delta->num_members; i++) {
894		NTSTATUS nt_status;
895		SAM_ACCOUNT *member = NULL;
896		DOM_SID member_sid;
897
898		if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
899			talloc_destroy(t);
900			return nt_status;
901		}
902
903		sid_copy(&member_sid, &delta->sids[i].sid);
904
905		if (!pdb_getsampwsid(member, &member_sid)) {
906			DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
907				  sid_string_static(&member_sid), grp->gr_name));
908			pdb_free_sam(&member);
909			continue;
910		}
911
912		if (pdb_get_group_rid(member) == rid) {
913			d_printf("%s(primary),", pdb_get_username(member));
914			pdb_free_sam(&member);
915			continue;
916		}
917
918		d_printf("%s,", pdb_get_username(member));
919		nt_members[i] = talloc_strdup(t, pdb_get_username(member));
920		pdb_free_sam(&member);
921	}
922
923	d_printf("\n");
924
925	unix_members = grp->gr_mem;
926
927	while (*unix_members) {
928		BOOL is_nt_member = False;
929		for (i=0; i<delta->num_members; i++) {
930			if (nt_members[i] == NULL) {
931				/* This was a primary group */
932				continue;
933			}
934
935			if (strcmp(*unix_members, nt_members[i]) == 0) {
936				is_nt_member = True;
937				break;
938			}
939		}
940		if (!is_nt_member) {
941			/* We look at a unix group member that is not
942			   an nt group member. So, remove it. NT is
943			   boss here. */
944			smb_delete_user_group(grp->gr_name, *unix_members);
945		}
946		unix_members += 1;
947	}
948
949	for (i=0; i<delta->num_members; i++) {
950		BOOL is_unix_member = False;
951
952		if (nt_members[i] == NULL) {
953			/* This was the primary group */
954			continue;
955		}
956
957		unix_members = grp->gr_mem;
958
959		while (*unix_members) {
960			if (strcmp(*unix_members, nt_members[i]) == 0) {
961				is_unix_member = True;
962				break;
963			}
964			unix_members += 1;
965		}
966
967		if (!is_unix_member) {
968			/* We look at a nt group member that is not a
969                           unix group member currently. So, add the nt
970                           group member. */
971			smb_add_user_group(grp->gr_name, nt_members[i]);
972		}
973	}
974
975	talloc_destroy(t);
976
977#endif	/* end of fetch_alias_mem() */
978
979	return NT_STATUS_OK;
980}
981
982static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta)
983{
984	time_t u_max_age, u_min_age, u_logout, u_lockoutreset, u_lockouttime;
985	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
986	pstring domname;
987
988	u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age);
989	u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age);
990	u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff);
991	u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count);
992	u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration);
993
994	unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1);
995
996	/* we don't handle BUILTIN account policies */
997	if (!strequal(domname, get_global_sam_name())) {
998		printf("skipping SAM_DOMAIN_INFO delta for '%s' (is not my domain)\n", domname);
999		return NT_STATUS_OK;
1000	}
1001
1002
1003	if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len))
1004		return nt_status;
1005
1006	if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len))
1007		return nt_status;
1008
1009	if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age))
1010		return nt_status;
1011
1012	if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age))
1013		return nt_status;
1014
1015	if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout))
1016		return nt_status;
1017
1018	if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout))
1019		return nt_status;
1020
1021	if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60))
1022		return nt_status;
1023
1024	if (u_lockouttime != -1)
1025		u_lockouttime /= 60;
1026
1027	if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime))
1028		return nt_status;
1029
1030	if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass))
1031		return nt_status;
1032
1033	return NT_STATUS_OK;
1034}
1035
1036
1037static void
1038fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
1039		DOM_SID dom_sid)
1040{
1041	switch(hdr_delta->type) {
1042	case SAM_DELTA_ACCOUNT_INFO:
1043		fetch_account_info(hdr_delta->target_rid,
1044				   &delta->account_info);
1045		break;
1046	case SAM_DELTA_GROUP_INFO:
1047		fetch_group_info(hdr_delta->target_rid,
1048				 &delta->group_info);
1049		break;
1050	case SAM_DELTA_GROUP_MEM:
1051		fetch_group_mem_info(hdr_delta->target_rid,
1052				     &delta->grp_mem_info);
1053		break;
1054	case SAM_DELTA_ALIAS_INFO:
1055		fetch_alias_info(hdr_delta->target_rid,
1056				 &delta->alias_info, dom_sid);
1057		break;
1058	case SAM_DELTA_ALIAS_MEM:
1059		fetch_alias_mem(hdr_delta->target_rid,
1060				&delta->als_mem_info, dom_sid);
1061		break;
1062	case SAM_DELTA_DOMAIN_INFO:
1063		fetch_domain_info(hdr_delta->target_rid,
1064				&delta->domain_info);
1065		break;
1066	/* The following types are recognised but not handled */
1067	case SAM_DELTA_RENAME_GROUP:
1068		d_printf("SAM_DELTA_RENAME_GROUP not handled\n");
1069		break;
1070	case SAM_DELTA_RENAME_USER:
1071		d_printf("SAM_DELTA_RENAME_USER not handled\n");
1072		break;
1073	case SAM_DELTA_RENAME_ALIAS:
1074		d_printf("SAM_DELTA_RENAME_ALIAS not handled\n");
1075		break;
1076	case SAM_DELTA_POLICY_INFO:
1077		d_printf("SAM_DELTA_POLICY_INFO not handled\n");
1078		break;
1079	case SAM_DELTA_TRUST_DOMS:
1080		d_printf("SAM_DELTA_TRUST_DOMS not handled\n");
1081		break;
1082	case SAM_DELTA_PRIVS_INFO:
1083		d_printf("SAM_DELTA_PRIVS_INFO not handled\n");
1084		break;
1085	case SAM_DELTA_SECRET_INFO:
1086		d_printf("SAM_DELTA_SECRET_INFO not handled\n");
1087		break;
1088	case SAM_DELTA_DELETE_GROUP:
1089		d_printf("SAM_DELTA_DELETE_GROUP not handled\n");
1090		break;
1091	case SAM_DELTA_DELETE_USER:
1092		d_printf("SAM_DELTA_DELETE_USER not handled\n");
1093		break;
1094	case SAM_DELTA_MODIFIED_COUNT:
1095		d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n");
1096		break;
1097	default:
1098		d_printf("Unknown delta record type %d\n", hdr_delta->type);
1099		break;
1100	}
1101}
1102
1103static NTSTATUS
1104fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds,
1105	       DOM_SID dom_sid)
1106{
1107	unsigned sync_context = 0;
1108        NTSTATUS result;
1109	int i;
1110        TALLOC_CTX *mem_ctx;
1111        SAM_DELTA_HDR *hdr_deltas;
1112        SAM_DELTA_CTR *deltas;
1113        uint32 num_deltas;
1114
1115	if (!(mem_ctx = talloc_init("fetch_database")))
1116		return NT_STATUS_NO_MEMORY;
1117
1118	switch( db_type ) {
1119	case SAM_DATABASE_DOMAIN:
1120		d_printf("Fetching DOMAIN database\n");
1121		break;
1122	case SAM_DATABASE_BUILTIN:
1123		d_printf("Fetching BUILTIN database\n");
1124		break;
1125	case SAM_DATABASE_PRIVS:
1126		d_printf("Fetching PRIVS databases\n");
1127		break;
1128	default:
1129		d_printf("Fetching unknown database type %u\n", db_type );
1130		break;
1131	}
1132
1133	do {
1134		result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds,
1135					       db_type, sync_context,
1136					       &num_deltas,
1137					       &hdr_deltas, &deltas);
1138
1139		if (NT_STATUS_IS_OK(result) ||
1140		    NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1141
1142			clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred),
1143					     ret_creds);
1144
1145			for (i = 0; i < num_deltas; i++) {
1146				fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid);
1147			}
1148		} else
1149			return result;
1150
1151		sync_context += 1;
1152	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1153
1154	talloc_destroy(mem_ctx);
1155
1156	return result;
1157}
1158
1159/* dump sam database via samsync rpc calls */
1160NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid,
1161			       const char *domain_name,
1162			       struct cli_state *cli, TALLOC_CTX *mem_ctx,
1163			       int argc, const char **argv)
1164{
1165        NTSTATUS result;
1166	uchar trust_password[16];
1167	DOM_CRED ret_creds;
1168	fstring my_dom_sid_str;
1169	fstring rem_dom_sid_str;
1170	uint32 sec_channel;
1171
1172	ZERO_STRUCT(ret_creds);
1173
1174	if (!sid_equal(domain_sid, get_global_sam_sid())) {
1175		d_printf("Cannot import users from %s at this time, "
1176			 "as the current domain:\n\t%s: %s\nconflicts "
1177			 "with the remote domain\n\t%s: %s\n"
1178			 "Perhaps you need to set: \n\n\tsecurity=user\n\tworkgroup=%s\n\n in your smb.conf?\n",
1179			 domain_name,
1180			 get_global_sam_name(), sid_to_string(my_dom_sid_str,
1181							      get_global_sam_sid()),
1182			 domain_name, sid_to_string(rem_dom_sid_str, domain_sid),
1183			 domain_name);
1184		return NT_STATUS_UNSUCCESSFUL;
1185	}
1186
1187	fstrcpy(cli->domain, domain_name);
1188
1189	if (!secrets_fetch_trust_account_password(domain_name,
1190						  trust_password, NULL,
1191						  &sec_channel)) {
1192		result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1193		d_printf("Could not retrieve domain trust secret\n");
1194		goto fail;
1195	}
1196
1197	result = cli_nt_establish_netlogon(cli, sec_channel, trust_password);
1198
1199	if (!NT_STATUS_IS_OK(result)) {
1200		d_printf("Failed to setup BDC creds\n");
1201		goto fail;
1202	}
1203
1204	result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, *domain_sid);
1205
1206	if (!NT_STATUS_IS_OK(result)) {
1207		d_printf("Failed to fetch domain database: %s\n",
1208			 nt_errstr(result));
1209		if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED))
1210			d_printf("Perhaps %s is a Windows 2000 native mode "
1211				 "domain?\n", domain_name);
1212		goto fail;
1213	}
1214
1215	result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds,
1216				global_sid_Builtin);
1217
1218	if (!NT_STATUS_IS_OK(result)) {
1219		d_printf("Failed to fetch builtin database: %s\n",
1220			 nt_errstr(result));
1221		goto fail;
1222	}
1223
1224	/* Currently we crash on PRIVS somewhere in unmarshalling */
1225	/* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */
1226
1227fail:
1228	return result;
1229}
1230