• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/passdb/
1/*
2   Unix SMB/CIFS implementation.
3   Password and authentication handling
4   Copyright (C) Jeremy Allison 		1996-2001
5   Copyright (C) Luke Kenneth Casson Leighton 	1996-1998
6   Copyright (C) Gerald (Jerry) Carter		2000-2006
7   Copyright (C) Andrew Bartlett		2001-2002
8   Copyright (C) Simo Sorce			2003
9   Copyright (C) Volker Lendecke 		2006
10
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 3 of the License, or
14   (at your option) any later version.
15
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "includes.h"
26#include "../libcli/auth/libcli_auth.h"
27
28#undef DBGC_CLASS
29#define DBGC_CLASS DBGC_PASSDB
30
31/******************************************************************
32 Get the default domain/netbios name to be used when
33 testing authentication.
34
35 LEGACY: this function provides the legacy domain mapping used with
36	 the lp_map_untrusted_to_domain() parameter
37******************************************************************/
38
39const char *my_sam_name(void)
40{
41       /* Standalone servers can only use the local netbios name */
42       if ( lp_server_role() == ROLE_STANDALONE )
43               return global_myname();
44
45       /* Default to the DOMAIN name when not specified */
46       return lp_workgroup();
47}
48
49/**********************************************************************
50***********************************************************************/
51
52static int samu_destroy(struct samu *user)
53{
54	data_blob_clear_free( &user->lm_pw );
55	data_blob_clear_free( &user->nt_pw );
56
57	if ( user->plaintext_pw )
58		memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
59
60	return 0;
61}
62
63/**********************************************************************
64 generate a new struct samuser
65***********************************************************************/
66
67struct samu *samu_new( TALLOC_CTX *ctx )
68{
69	struct samu *user;
70
71	if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
72		DEBUG(0,("samuser_new: Talloc failed!\n"));
73		return NULL;
74	}
75
76	talloc_set_destructor( user, samu_destroy );
77
78	/* no initial methods */
79
80	user->methods = NULL;
81
82        /* Don't change these timestamp settings without a good reason.
83           They are important for NT member server compatibility. */
84
85	user->logon_time            = (time_t)0;
86	user->pass_last_set_time    = (time_t)0;
87	user->pass_can_change_time  = (time_t)0;
88	user->logoff_time           = get_time_t_max();
89	user->kickoff_time          = get_time_t_max();
90	user->pass_must_change_time = get_time_t_max();
91	user->fields_present        = 0x00ffffff;
92	user->logon_divs = 168; 	/* hours per week */
93	user->hours_len = 21; 		/* 21 times 8 bits = 168 */
94	memset(user->hours, 0xff, user->hours_len); /* available at all hours */
95	user->bad_password_count = 0;
96	user->logon_count = 0;
97	user->unknown_6 = 0x000004ec; /* don't know */
98
99	/* Some parts of samba strlen their pdb_get...() returns,
100	   so this keeps the interface unchanged for now. */
101
102	user->username = "";
103	user->domain = "";
104	user->nt_username = "";
105	user->full_name = "";
106	user->home_dir = "";
107	user->logon_script = "";
108	user->profile_path = "";
109	user->acct_desc = "";
110	user->workstations = "";
111	user->comment = "";
112	user->munged_dial = "";
113
114	user->plaintext_pw = NULL;
115
116	/* Unless we know otherwise have a Account Control Bit
117	   value of 'normal user'.  This helps User Manager, which
118	   asks for a filtered list of users. */
119
120	user->acct_ctrl = ACB_NORMAL;
121
122	return user;
123}
124
125static int count_commas(const char *str)
126{
127	int num_commas = 0;
128	const char *comma = str;
129
130	while ((comma = strchr(comma, ',')) != NULL) {
131		comma += 1;
132		num_commas += 1;
133	}
134	return num_commas;
135}
136
137/*********************************************************************
138 Initialize a struct samu from a struct passwd including the user
139 and group SIDs.  The *user structure is filled out with the Unix
140 attributes and a user SID.
141*********************************************************************/
142
143static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
144{
145	const char *guest_account = lp_guestaccount();
146	const char *domain = global_myname();
147	char *fullname;
148	uint32 urid;
149
150	if ( !pwd ) {
151		return NT_STATUS_NO_SUCH_USER;
152	}
153
154	/* Basic properties based upon the Unix account information */
155
156	pdb_set_username(user, pwd->pw_name, PDB_SET);
157
158	fullname = NULL;
159
160	if (count_commas(pwd->pw_gecos) == 3) {
161		/*
162		 * Heuristic: This seems to be a gecos field that has been
163		 * edited by chfn(1). Only use the part before the first
164		 * comma. Fixes bug 5198.
165		 */
166		fullname = talloc_strndup(
167			talloc_tos(), pwd->pw_gecos,
168			strchr(pwd->pw_gecos, ',') - pwd->pw_gecos);
169	}
170
171	if (fullname != NULL) {
172		pdb_set_fullname(user, fullname, PDB_SET);
173	} else {
174		pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
175	}
176	TALLOC_FREE(fullname);
177
178	pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
179#if 0
180	/* This can lead to a primary group of S-1-22-2-XX which
181	   will be rejected by other parts of the Samba code.
182	   Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)
183	   --jerry */
184
185	gid_to_sid(&group_sid, pwd->pw_gid);
186	pdb_set_group_sid(user, &group_sid, PDB_SET);
187#endif
188
189	/* save the password structure for later use */
190
191	user->unix_pw = tcopy_passwd( user, pwd );
192
193	/* Special case for the guest account which must have a RID of 501 */
194
195	if ( strequal( pwd->pw_name, guest_account ) ) {
196		if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
197			return NT_STATUS_NO_SUCH_USER;
198		}
199		return NT_STATUS_OK;
200	}
201
202	/* Non-guest accounts...Check for a workstation or user account */
203
204	if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
205		/* workstation */
206
207		if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
208			DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
209				pwd->pw_name));
210			return NT_STATUS_INVALID_COMPUTER_NAME;
211		}
212	}
213	else {
214		/* user */
215
216		if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
217			DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
218				pwd->pw_name));
219			return NT_STATUS_INVALID_ACCOUNT_NAME;
220		}
221
222		/* set some basic attributes */
223
224		pdb_set_profile_path(user, talloc_sub_specified(user,
225			lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
226			PDB_DEFAULT);
227		pdb_set_homedir(user, talloc_sub_specified(user,
228			lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
229			PDB_DEFAULT);
230		pdb_set_dir_drive(user, talloc_sub_specified(user,
231			lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
232			PDB_DEFAULT);
233		pdb_set_logon_script(user, talloc_sub_specified(user,
234			lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
235			PDB_DEFAULT);
236	}
237
238	/* Now deal with the user SID.  If we have a backend that can generate
239	   RIDs, then do so.  But sometimes the caller just wanted a structure
240	   initialized and will fill in these fields later (such as from a
241	   netr_SamInfo3 structure) */
242
243	if ( create && (pdb_capabilities() & PDB_CAP_STORE_RIDS)) {
244		uint32 user_rid;
245		DOM_SID user_sid;
246
247		if ( !pdb_new_rid( &user_rid ) ) {
248			DEBUG(3, ("Could not allocate a new RID\n"));
249			return NT_STATUS_ACCESS_DENIED;
250		}
251
252		sid_copy( &user_sid, get_global_sam_sid() );
253		sid_append_rid( &user_sid, user_rid );
254
255		if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
256			DEBUG(3, ("pdb_set_user_sid failed\n"));
257			return NT_STATUS_INTERNAL_ERROR;
258		}
259
260		return NT_STATUS_OK;
261	}
262
263	/* generate a SID for the user with the RID algorithm */
264
265	urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
266
267	if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
268		return NT_STATUS_INTERNAL_ERROR;
269	}
270
271	return NT_STATUS_OK;
272}
273
274/********************************************************************
275 Set the Unix user attributes
276********************************************************************/
277
278NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
279{
280	return samu_set_unix_internal( user, pwd, False );
281}
282
283NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
284{
285	return samu_set_unix_internal( user, pwd, True );
286}
287
288/**********************************************************
289 Encode the account control bits into a string.
290 length = length of string to encode into (including terminating
291 null). length *MUST BE MORE THAN 2* !
292 **********************************************************/
293
294char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
295{
296	fstring acct_str;
297	char *result;
298
299	size_t i = 0;
300
301	SMB_ASSERT(length <= sizeof(acct_str));
302
303	acct_str[i++] = '[';
304
305	if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
306	if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
307	if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
308	if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T';
309	if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
310	if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
311	if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
312	if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
313	if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
314	if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
315	if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
316
317	for ( ; i < length - 2 ; i++ )
318		acct_str[i] = ' ';
319
320	i = length - 2;
321	acct_str[i++] = ']';
322	acct_str[i++] = '\0';
323
324	result = talloc_strdup(talloc_tos(), acct_str);
325	SMB_ASSERT(result != NULL);
326	return result;
327}
328
329/**********************************************************
330 Decode the account control bits from a string.
331 **********************************************************/
332
333uint32_t pdb_decode_acct_ctrl(const char *p)
334{
335	uint32_t acct_ctrl = 0;
336	bool finished = false;
337
338	/*
339	 * Check if the account type bits have been encoded after the
340	 * NT password (in the form [NDHTUWSLXI]).
341	 */
342
343	if (*p != '[')
344		return 0;
345
346	for (p++; *p && !finished; p++) {
347		switch (*p) {
348			case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
349			case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
350			case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
351			case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ }
352			case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ }
353			case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ }
354			case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ }
355			case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
356			case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
357			case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ }
358			case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
359            case ' ': { break; }
360			case ':':
361			case '\n':
362			case '\0':
363			case ']':
364			default:  { finished = true; }
365		}
366	}
367
368	return acct_ctrl;
369}
370
371/*************************************************************
372 Routine to set 32 hex password characters from a 16 byte array.
373**************************************************************/
374
375void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
376{
377	if (pwd != NULL) {
378		int i;
379		for (i = 0; i < 16; i++)
380			slprintf(&p[i*2], 3, "%02X", pwd[i]);
381	} else {
382		if (acct_ctrl & ACB_PWNOTREQ)
383			safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
384		else
385			safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
386	}
387}
388
389/*************************************************************
390 Routine to get the 32 hex characters and turn them
391 into a 16 byte array.
392**************************************************************/
393
394bool pdb_gethexpwd(const char *p, unsigned char *pwd)
395{
396	int i;
397	unsigned char   lonybble, hinybble;
398	const char      *hexchars = "0123456789ABCDEF";
399	char           *p1, *p2;
400
401	if (!p)
402		return false;
403
404	for (i = 0; i < 32; i += 2) {
405		hinybble = toupper_ascii(p[i]);
406		lonybble = toupper_ascii(p[i + 1]);
407
408		p1 = strchr(hexchars, hinybble);
409		p2 = strchr(hexchars, lonybble);
410
411		if (!p1 || !p2)
412			return false;
413
414		hinybble = PTR_DIFF(p1, hexchars);
415		lonybble = PTR_DIFF(p2, hexchars);
416
417		pwd[i / 2] = (hinybble << 4) | lonybble;
418	}
419	return true;
420}
421
422/*************************************************************
423 Routine to set 42 hex hours characters from a 21 byte array.
424**************************************************************/
425
426void pdb_sethexhours(char *p, const unsigned char *hours)
427{
428	if (hours != NULL) {
429		int i;
430		for (i = 0; i < 21; i++) {
431			slprintf(&p[i*2], 3, "%02X", hours[i]);
432		}
433	} else {
434		safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
435	}
436}
437
438/*************************************************************
439 Routine to get the 42 hex characters and turn them
440 into a 21 byte array.
441**************************************************************/
442
443bool pdb_gethexhours(const char *p, unsigned char *hours)
444{
445	int i;
446	unsigned char   lonybble, hinybble;
447	const char      *hexchars = "0123456789ABCDEF";
448	char           *p1, *p2;
449
450	if (!p) {
451		return (False);
452	}
453
454	for (i = 0; i < 42; i += 2) {
455		hinybble = toupper_ascii(p[i]);
456		lonybble = toupper_ascii(p[i + 1]);
457
458		p1 = strchr(hexchars, hinybble);
459		p2 = strchr(hexchars, lonybble);
460
461		if (!p1 || !p2) {
462			return (False);
463		}
464
465		hinybble = PTR_DIFF(p1, hexchars);
466		lonybble = PTR_DIFF(p2, hexchars);
467
468		hours[i / 2] = (hinybble << 4) | lonybble;
469	}
470	return (True);
471}
472
473/********************************************************************
474********************************************************************/
475
476int algorithmic_rid_base(void)
477{
478	int rid_offset;
479
480	rid_offset = lp_algorithmic_rid_base();
481
482	if (rid_offset < BASE_RID) {
483		/* Try to prevent admin foot-shooting, we can't put algorithmic
484		   rids below 1000, that's the 'well known RIDs' on NT */
485		DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
486		rid_offset = BASE_RID;
487	}
488	if (rid_offset & 1) {
489		DEBUG(0, ("algorithmic rid base must be even\n"));
490		rid_offset += 1;
491	}
492	return rid_offset;
493}
494
495/*******************************************************************
496 Converts NT user RID to a UNIX uid.
497 ********************************************************************/
498
499uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
500{
501	int rid_offset = algorithmic_rid_base();
502	return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
503}
504
505uid_t max_algorithmic_uid(void)
506{
507	return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
508}
509
510/*******************************************************************
511 converts UNIX uid to an NT User RID.
512 ********************************************************************/
513
514uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
515{
516	int rid_offset = algorithmic_rid_base();
517	return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
518}
519
520/*******************************************************************
521 Converts NT group RID to a UNIX gid.
522 ********************************************************************/
523
524gid_t pdb_group_rid_to_gid(uint32 group_rid)
525{
526	int rid_offset = algorithmic_rid_base();
527	return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
528}
529
530gid_t max_algorithmic_gid(void)
531{
532	return pdb_group_rid_to_gid(0xffffffff);
533}
534
535/*******************************************************************
536 converts NT Group RID to a UNIX uid.
537
538 warning: you must not call that function only
539 you must do a call to the group mapping first.
540 there is not anymore a direct link between the gid and the rid.
541 ********************************************************************/
542
543uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
544{
545	int rid_offset = algorithmic_rid_base();
546	return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
547}
548
549/*******************************************************************
550 Decides if a RID is a well known RID.
551 ********************************************************************/
552
553static bool rid_is_well_known(uint32 rid)
554{
555	/* Not using rid_offset here, because this is the actual
556	   NT fixed value (1000) */
557
558	return (rid < BASE_RID);
559}
560
561/*******************************************************************
562 Decides if a RID is a user or group RID.
563 ********************************************************************/
564
565bool algorithmic_pdb_rid_is_user(uint32 rid)
566{
567	if ( rid_is_well_known(rid) ) {
568		/*
569		 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
570		 * and DOMAIN_USER_RID_GUEST.
571		 */
572		if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
573			return True;
574	} else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
575		return True;
576	}
577	return False;
578}
579
580/*******************************************************************
581 Convert a name into a SID. Used in the lookup name rpc.
582 ********************************************************************/
583
584bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
585			    enum lsa_SidType *type)
586{
587	GROUP_MAP map;
588	bool ret;
589
590	/* Windows treats "MACHINE\None" as a special name for
591	   rid 513 on non-DCs.  You cannot create a user or group
592	   name "None" on Windows.  You will get an error that
593	   the group already exists. */
594
595	if ( strequal( name, "None" ) ) {
596		*rid = DOMAIN_GROUP_RID_USERS;
597		*type = SID_NAME_DOM_GRP;
598
599		return True;
600	}
601
602	/* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
603	 * correctly in the case where foo also exists as a user. If the flag
604	 * is set, don't look for users at all. */
605
606	if ((flags & LOOKUP_NAME_GROUP) == 0) {
607		struct samu *sam_account = NULL;
608		DOM_SID user_sid;
609
610		if ( !(sam_account = samu_new( NULL )) ) {
611			return False;
612		}
613
614		become_root();
615		ret =  pdb_getsampwnam(sam_account, name);
616		unbecome_root();
617
618		if (ret) {
619			sid_copy(&user_sid, pdb_get_user_sid(sam_account));
620		}
621
622		TALLOC_FREE(sam_account);
623
624		if (ret) {
625			if (!sid_check_is_in_our_domain(&user_sid)) {
626				DEBUG(0, ("User %s with invalid SID %s in passdb\n",
627					  name, sid_string_dbg(&user_sid)));
628				return False;
629			}
630
631			sid_peek_rid(&user_sid, rid);
632			*type = SID_NAME_USER;
633			return True;
634		}
635	}
636
637	/*
638	 * Maybe it is a group ?
639	 */
640
641	become_root();
642	ret = pdb_getgrnam(&map, name);
643	unbecome_root();
644
645 	if (!ret) {
646		return False;
647	}
648
649	/* BUILTIN groups are looked up elsewhere */
650	if (!sid_check_is_in_our_domain(&map.sid)) {
651		DEBUG(10, ("Found group %s (%s) not in our domain -- "
652			   "ignoring.", name, sid_string_dbg(&map.sid)));
653		return False;
654	}
655
656	/* yes it's a mapped group */
657	sid_peek_rid(&map.sid, rid);
658	*type = map.sid_name_use;
659	return True;
660}
661
662/*************************************************************
663 Change a password entry in the local passdb backend.
664
665 Assumptions:
666  - always called as root
667  - ignores the account type except when adding a new account
668  - will create/delete the unix account if the relative
669    add/delete user script is configured
670
671 *************************************************************/
672
673NTSTATUS local_password_change(const char *user_name,
674				int local_flags,
675				const char *new_passwd,
676				char **pp_err_str,
677				char **pp_msg_str)
678{
679	TALLOC_CTX *tosctx;
680	struct samu *sam_pass;
681	uint32_t acb;
682	uint32_t rid;
683	NTSTATUS result;
684	bool user_exists;
685	int ret = -1;
686
687	*pp_err_str = NULL;
688	*pp_msg_str = NULL;
689
690	tosctx = talloc_tos();
691
692	sam_pass = samu_new(tosctx);
693	if (!sam_pass) {
694		result = NT_STATUS_NO_MEMORY;
695		goto done;
696	}
697
698	/* Get the smb passwd entry for this user */
699	user_exists = pdb_getsampwnam(sam_pass, user_name);
700
701	/* Check delete first, we don't need to do anything else if we
702	 * are going to delete the acocunt */
703	if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
704
705		result = pdb_delete_user(tosctx, sam_pass);
706		if (!NT_STATUS_IS_OK(result)) {
707			ret = asprintf(pp_err_str,
708					"Failed to delete entry for user %s.\n",
709					user_name);
710			if (ret < 0) {
711				*pp_err_str = NULL;
712			}
713			result = NT_STATUS_UNSUCCESSFUL;
714		} else {
715			ret = asprintf(pp_msg_str,
716					"Deleted user %s.\n",
717					user_name);
718			if (ret < 0) {
719				*pp_msg_str = NULL;
720			}
721		}
722		goto done;
723	}
724
725	if (user_exists && (local_flags & LOCAL_ADD_USER)) {
726		/* the entry already existed */
727		local_flags &= ~LOCAL_ADD_USER;
728	}
729
730	if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
731		ret = asprintf(pp_err_str,
732				"Failed to find entry for user %s.\n",
733				user_name);
734		if (ret < 0) {
735			*pp_err_str = NULL;
736		}
737		result = NT_STATUS_NO_SUCH_USER;
738		goto done;
739	}
740
741	/* First thing add the new user if we are required to do so */
742	if (local_flags & LOCAL_ADD_USER) {
743
744		if (local_flags & LOCAL_TRUST_ACCOUNT) {
745			acb = ACB_WSTRUST;
746		} else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
747			acb = ACB_DOMTRUST;
748		} else {
749			acb = ACB_NORMAL;
750		}
751
752		result = pdb_create_user(tosctx, user_name, acb, &rid);
753		if (!NT_STATUS_IS_OK(result)) {
754			ret = asprintf(pp_err_str,
755					"Failed to add entry for user %s.\n",
756					user_name);
757			if (ret < 0) {
758				*pp_err_str = NULL;
759			}
760			result = NT_STATUS_UNSUCCESSFUL;
761			goto done;
762		}
763
764		sam_pass = samu_new(tosctx);
765		if (!sam_pass) {
766			result = NT_STATUS_NO_MEMORY;
767			goto done;
768		}
769
770		/* Now get back the smb passwd entry for this new user */
771		user_exists = pdb_getsampwnam(sam_pass, user_name);
772		if (!user_exists) {
773			ret = asprintf(pp_err_str,
774					"Failed to add entry for user %s.\n",
775					user_name);
776			if (ret < 0) {
777				*pp_err_str = NULL;
778			}
779			result = NT_STATUS_UNSUCCESSFUL;
780			goto done;
781		}
782	}
783
784	acb = pdb_get_acct_ctrl(sam_pass);
785
786	/*
787	 * We are root - just write the new password
788	 * and the valid last change time.
789	 */
790	if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
791		acb |= ACB_PWNOTREQ;
792		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
793			ret = asprintf(pp_err_str,
794					"Failed to set 'no password required' "
795					"flag for user %s.\n", user_name);
796			if (ret < 0) {
797				*pp_err_str = NULL;
798			}
799			result = NT_STATUS_UNSUCCESSFUL;
800			goto done;
801		}
802	}
803
804	if (local_flags & LOCAL_SET_PASSWORD) {
805		/*
806		 * If we're dealing with setting a completely empty user account
807		 * ie. One with a password of 'XXXX', but not set disabled (like
808		 * an account created from scratch) then if the old password was
809		 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
810		 * We remove that as we're giving this user their first password
811		 * and the decision hasn't really been made to disable them (ie.
812		 * don't create them disabled). JRA.
813		 */
814		if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
815		    (acb & ACB_DISABLED)) {
816			acb &= (~ACB_DISABLED);
817			if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
818				ret = asprintf(pp_err_str,
819						"Failed to unset 'disabled' "
820						"flag for user %s.\n",
821						user_name);
822				if (ret < 0) {
823					*pp_err_str = NULL;
824				}
825				result = NT_STATUS_UNSUCCESSFUL;
826				goto done;
827			}
828		}
829
830		acb &= (~ACB_PWNOTREQ);
831		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
832			ret = asprintf(pp_err_str,
833					"Failed to unset 'no password required'"
834					" flag for user %s.\n", user_name);
835			if (ret < 0) {
836				*pp_err_str = NULL;
837			}
838			result = NT_STATUS_UNSUCCESSFUL;
839			goto done;
840		}
841
842		if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
843			ret = asprintf(pp_err_str,
844					"Failed to set password for "
845					"user %s.\n", user_name);
846				if (ret < 0) {
847				*pp_err_str = NULL;
848			}
849			result = NT_STATUS_UNSUCCESSFUL;
850			goto done;
851		}
852	}
853
854	if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
855		acb |= ACB_DISABLED;
856		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
857			ret = asprintf(pp_err_str,
858					"Failed to set 'disabled' flag for "
859					"user %s.\n", user_name);
860			if (ret < 0) {
861				*pp_err_str = NULL;
862			}
863			result = NT_STATUS_UNSUCCESSFUL;
864			goto done;
865		}
866	}
867
868	if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
869		acb &= (~ACB_DISABLED);
870		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
871			ret = asprintf(pp_err_str,
872					"Failed to unset 'disabled' flag for "
873					"user %s.\n", user_name);
874			if (ret < 0) {
875				*pp_err_str = NULL;
876			}
877			result = NT_STATUS_UNSUCCESSFUL;
878			goto done;
879		}
880	}
881
882	/* now commit changes if any */
883	result = pdb_update_sam_account(sam_pass);
884	if (!NT_STATUS_IS_OK(result)) {
885		ret = asprintf(pp_err_str,
886				"Failed to modify entry for user %s.\n",
887				user_name);
888		if (ret < 0) {
889			*pp_err_str = NULL;
890		}
891		goto done;
892	}
893
894	if (local_flags & LOCAL_ADD_USER) {
895		ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
896	} else if (local_flags & LOCAL_DISABLE_USER) {
897		ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
898	} else if (local_flags & LOCAL_ENABLE_USER) {
899		ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
900	} else if (local_flags & LOCAL_SET_NO_PASSWORD) {
901		ret = asprintf(pp_msg_str,
902				"User %s password set to none.\n", user_name);
903	}
904
905	if (ret < 0) {
906		*pp_msg_str = NULL;
907	}
908
909	result = NT_STATUS_OK;
910
911done:
912	TALLOC_FREE(sam_pass);
913	return result;
914}
915
916/**********************************************************************
917 Marshall/unmarshall struct samu structs.
918 *********************************************************************/
919
920#define SAMU_BUFFER_FORMAT_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
921#define SAMU_BUFFER_FORMAT_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
922#define SAMU_BUFFER_FORMAT_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
923#define SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
924/* nothing changed between V3 and V4 */
925
926/*********************************************************************
927*********************************************************************/
928
929static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
930{
931
932	/* times are stored as 32bit integer
933	   take care on system with 64bit wide time_t
934	   --SSS */
935	uint32	logon_time,
936		logoff_time,
937		kickoff_time,
938		pass_last_set_time,
939		pass_can_change_time,
940		pass_must_change_time;
941	char *username = NULL;
942	char *domain = NULL;
943	char *nt_username = NULL;
944	char *dir_drive = NULL;
945	char *unknown_str = NULL;
946	char *munged_dial = NULL;
947	char *fullname = NULL;
948	char *homedir = NULL;
949	char *logon_script = NULL;
950	char *profile_path = NULL;
951	char *acct_desc = NULL;
952	char *workstations = NULL;
953	uint32	username_len, domain_len, nt_username_len,
954		dir_drive_len, unknown_str_len, munged_dial_len,
955		fullname_len, homedir_len, logon_script_len,
956		profile_path_len, acct_desc_len, workstations_len;
957
958	uint32	user_rid, group_rid, remove_me, hours_len, unknown_6;
959	uint16	acct_ctrl, logon_divs;
960	uint16	bad_password_count, logon_count;
961	uint8	*hours = NULL;
962	uint8	*lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
963	uint32		len = 0;
964	uint32		lm_pw_len, nt_pw_len, hourslen;
965	bool ret = True;
966
967	if(sampass == NULL || buf == NULL) {
968		DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
969		return False;
970	}
971
972/* SAMU_BUFFER_FORMAT_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
973
974	/* unpack the buffer into variables */
975	len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
976		&logon_time,						/* d */
977		&logoff_time,						/* d */
978		&kickoff_time,						/* d */
979		&pass_last_set_time,					/* d */
980		&pass_can_change_time,					/* d */
981		&pass_must_change_time,					/* d */
982		&username_len, &username,				/* B */
983		&domain_len, &domain,					/* B */
984		&nt_username_len, &nt_username,				/* B */
985		&fullname_len, &fullname,				/* B */
986		&homedir_len, &homedir,					/* B */
987		&dir_drive_len, &dir_drive,				/* B */
988		&logon_script_len, &logon_script,			/* B */
989		&profile_path_len, &profile_path,			/* B */
990		&acct_desc_len, &acct_desc,				/* B */
991		&workstations_len, &workstations,			/* B */
992		&unknown_str_len, &unknown_str,				/* B */
993		&munged_dial_len, &munged_dial,				/* B */
994		&user_rid,						/* d */
995		&group_rid,						/* d */
996		&lm_pw_len, &lm_pw_ptr,					/* B */
997		&nt_pw_len, &nt_pw_ptr,					/* B */
998		&acct_ctrl,						/* w */
999		&remove_me, /* remove on the next TDB_FORMAT upgarde */	/* d */
1000		&logon_divs,						/* w */
1001		&hours_len,						/* d */
1002		&hourslen, &hours,					/* B */
1003		&bad_password_count,					/* w */
1004		&logon_count,						/* w */
1005		&unknown_6);						/* d */
1006
1007	if (len == (uint32) -1)  {
1008		ret = False;
1009		goto done;
1010	}
1011
1012	pdb_set_logon_time(sampass, logon_time, PDB_SET);
1013	pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1014	pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1015	pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1016	pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1017	pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1018
1019	pdb_set_username(sampass, username, PDB_SET);
1020	pdb_set_domain(sampass, domain, PDB_SET);
1021	pdb_set_nt_username(sampass, nt_username, PDB_SET);
1022	pdb_set_fullname(sampass, fullname, PDB_SET);
1023
1024	if (homedir) {
1025		pdb_set_homedir(sampass, homedir, PDB_SET);
1026	}
1027	else {
1028		pdb_set_homedir(sampass,
1029			talloc_sub_basic(sampass, username, domain,
1030					 lp_logon_home()),
1031			PDB_DEFAULT);
1032	}
1033
1034	if (dir_drive)
1035		pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1036	else {
1037		pdb_set_dir_drive(sampass,
1038			talloc_sub_basic(sampass, username, domain,
1039					 lp_logon_drive()),
1040			PDB_DEFAULT);
1041	}
1042
1043	if (logon_script)
1044		pdb_set_logon_script(sampass, logon_script, PDB_SET);
1045	else {
1046		pdb_set_logon_script(sampass,
1047			talloc_sub_basic(sampass, username, domain,
1048					 lp_logon_script()),
1049			PDB_DEFAULT);
1050	}
1051
1052	if (profile_path) {
1053		pdb_set_profile_path(sampass, profile_path, PDB_SET);
1054	} else {
1055		pdb_set_profile_path(sampass,
1056			talloc_sub_basic(sampass, username, domain,
1057					 lp_logon_path()),
1058			PDB_DEFAULT);
1059	}
1060
1061	pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1062	pdb_set_workstations(sampass, workstations, PDB_SET);
1063	pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1064
1065	if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1066		if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1067			ret = False;
1068			goto done;
1069		}
1070	}
1071
1072	if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1073		if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1074			ret = False;
1075			goto done;
1076		}
1077	}
1078
1079	pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1080	pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1081	pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1082	pdb_set_hours_len(sampass, hours_len, PDB_SET);
1083	pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1084	pdb_set_logon_count(sampass, logon_count, PDB_SET);
1085	pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1086	pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1087	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1088	pdb_set_hours(sampass, hours, PDB_SET);
1089
1090done:
1091
1092	SAFE_FREE(username);
1093	SAFE_FREE(domain);
1094	SAFE_FREE(nt_username);
1095	SAFE_FREE(fullname);
1096	SAFE_FREE(homedir);
1097	SAFE_FREE(dir_drive);
1098	SAFE_FREE(logon_script);
1099	SAFE_FREE(profile_path);
1100	SAFE_FREE(acct_desc);
1101	SAFE_FREE(workstations);
1102	SAFE_FREE(munged_dial);
1103	SAFE_FREE(unknown_str);
1104	SAFE_FREE(lm_pw_ptr);
1105	SAFE_FREE(nt_pw_ptr);
1106	SAFE_FREE(hours);
1107
1108	return ret;
1109}
1110
1111/*********************************************************************
1112*********************************************************************/
1113
1114static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1115{
1116
1117	/* times are stored as 32bit integer
1118	   take care on system with 64bit wide time_t
1119	   --SSS */
1120	uint32	logon_time,
1121		logoff_time,
1122		kickoff_time,
1123		bad_password_time,
1124		pass_last_set_time,
1125		pass_can_change_time,
1126		pass_must_change_time;
1127	char *username = NULL;
1128	char *domain = NULL;
1129	char *nt_username = NULL;
1130	char *dir_drive = NULL;
1131	char *unknown_str = NULL;
1132	char *munged_dial = NULL;
1133	char *fullname = NULL;
1134	char *homedir = NULL;
1135	char *logon_script = NULL;
1136	char *profile_path = NULL;
1137	char *acct_desc = NULL;
1138	char *workstations = NULL;
1139	uint32	username_len, domain_len, nt_username_len,
1140		dir_drive_len, unknown_str_len, munged_dial_len,
1141		fullname_len, homedir_len, logon_script_len,
1142		profile_path_len, acct_desc_len, workstations_len;
1143
1144	uint32	user_rid, group_rid, remove_me, hours_len, unknown_6;
1145	uint16	acct_ctrl, logon_divs;
1146	uint16	bad_password_count, logon_count;
1147	uint8	*hours = NULL;
1148	uint8	*lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1149	uint32		len = 0;
1150	uint32		lm_pw_len, nt_pw_len, hourslen;
1151	bool ret = True;
1152
1153	if(sampass == NULL || buf == NULL) {
1154		DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1155		return False;
1156	}
1157
1158/* SAMU_BUFFER_FORMAT_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1159
1160	/* unpack the buffer into variables */
1161	len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1162		&logon_time,						/* d */
1163		&logoff_time,						/* d */
1164		&kickoff_time,						/* d */
1165		/* Change from V0 is addition of bad_password_time field. */
1166		&bad_password_time,					/* d */
1167		&pass_last_set_time,					/* d */
1168		&pass_can_change_time,					/* d */
1169		&pass_must_change_time,					/* d */
1170		&username_len, &username,				/* B */
1171		&domain_len, &domain,					/* B */
1172		&nt_username_len, &nt_username,				/* B */
1173		&fullname_len, &fullname,				/* B */
1174		&homedir_len, &homedir,					/* B */
1175		&dir_drive_len, &dir_drive,				/* B */
1176		&logon_script_len, &logon_script,			/* B */
1177		&profile_path_len, &profile_path,			/* B */
1178		&acct_desc_len, &acct_desc,				/* B */
1179		&workstations_len, &workstations,			/* B */
1180		&unknown_str_len, &unknown_str,				/* B */
1181		&munged_dial_len, &munged_dial,				/* B */
1182		&user_rid,						/* d */
1183		&group_rid,						/* d */
1184		&lm_pw_len, &lm_pw_ptr,					/* B */
1185		&nt_pw_len, &nt_pw_ptr,					/* B */
1186		&acct_ctrl,						/* w */
1187		&remove_me,						/* d */
1188		&logon_divs,						/* w */
1189		&hours_len,						/* d */
1190		&hourslen, &hours,					/* B */
1191		&bad_password_count,					/* w */
1192		&logon_count,						/* w */
1193		&unknown_6);						/* d */
1194
1195	if (len == (uint32) -1)  {
1196		ret = False;
1197		goto done;
1198	}
1199
1200	pdb_set_logon_time(sampass, logon_time, PDB_SET);
1201	pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1202	pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1203
1204	/* Change from V0 is addition of bad_password_time field. */
1205	pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1206	pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1207	pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1208	pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1209
1210	pdb_set_username(sampass, username, PDB_SET);
1211	pdb_set_domain(sampass, domain, PDB_SET);
1212	pdb_set_nt_username(sampass, nt_username, PDB_SET);
1213	pdb_set_fullname(sampass, fullname, PDB_SET);
1214
1215	if (homedir) {
1216		pdb_set_homedir(sampass, homedir, PDB_SET);
1217	}
1218	else {
1219		pdb_set_homedir(sampass,
1220			talloc_sub_basic(sampass, username, domain,
1221					 lp_logon_home()),
1222			PDB_DEFAULT);
1223	}
1224
1225	if (dir_drive)
1226		pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1227	else {
1228		pdb_set_dir_drive(sampass,
1229			talloc_sub_basic(sampass, username, domain,
1230					 lp_logon_drive()),
1231			PDB_DEFAULT);
1232	}
1233
1234	if (logon_script)
1235		pdb_set_logon_script(sampass, logon_script, PDB_SET);
1236	else {
1237		pdb_set_logon_script(sampass,
1238			talloc_sub_basic(sampass, username, domain,
1239					 lp_logon_script()),
1240			PDB_DEFAULT);
1241	}
1242
1243	if (profile_path) {
1244		pdb_set_profile_path(sampass, profile_path, PDB_SET);
1245	} else {
1246		pdb_set_profile_path(sampass,
1247			talloc_sub_basic(sampass, username, domain,
1248					 lp_logon_path()),
1249			PDB_DEFAULT);
1250	}
1251
1252	pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1253	pdb_set_workstations(sampass, workstations, PDB_SET);
1254	pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1255
1256	if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1257		if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1258			ret = False;
1259			goto done;
1260		}
1261	}
1262
1263	if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1264		if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1265			ret = False;
1266			goto done;
1267		}
1268	}
1269
1270	pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1271
1272	pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1273	pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1274	pdb_set_hours_len(sampass, hours_len, PDB_SET);
1275	pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1276	pdb_set_logon_count(sampass, logon_count, PDB_SET);
1277	pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1278	pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1279	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1280	pdb_set_hours(sampass, hours, PDB_SET);
1281
1282done:
1283
1284	SAFE_FREE(username);
1285	SAFE_FREE(domain);
1286	SAFE_FREE(nt_username);
1287	SAFE_FREE(fullname);
1288	SAFE_FREE(homedir);
1289	SAFE_FREE(dir_drive);
1290	SAFE_FREE(logon_script);
1291	SAFE_FREE(profile_path);
1292	SAFE_FREE(acct_desc);
1293	SAFE_FREE(workstations);
1294	SAFE_FREE(munged_dial);
1295	SAFE_FREE(unknown_str);
1296	SAFE_FREE(lm_pw_ptr);
1297	SAFE_FREE(nt_pw_ptr);
1298	SAFE_FREE(hours);
1299
1300	return ret;
1301}
1302
1303static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1304{
1305
1306	/* times are stored as 32bit integer
1307	   take care on system with 64bit wide time_t
1308	   --SSS */
1309	uint32	logon_time,
1310		logoff_time,
1311		kickoff_time,
1312		bad_password_time,
1313		pass_last_set_time,
1314		pass_can_change_time,
1315		pass_must_change_time;
1316	char *username = NULL;
1317	char *domain = NULL;
1318	char *nt_username = NULL;
1319	char *dir_drive = NULL;
1320	char *unknown_str = NULL;
1321	char *munged_dial = NULL;
1322	char *fullname = NULL;
1323	char *homedir = NULL;
1324	char *logon_script = NULL;
1325	char *profile_path = NULL;
1326	char *acct_desc = NULL;
1327	char *workstations = NULL;
1328	uint32	username_len, domain_len, nt_username_len,
1329		dir_drive_len, unknown_str_len, munged_dial_len,
1330		fullname_len, homedir_len, logon_script_len,
1331		profile_path_len, acct_desc_len, workstations_len;
1332
1333	uint32	user_rid, group_rid, hours_len, unknown_6;
1334	uint16	acct_ctrl, logon_divs;
1335	uint16	bad_password_count, logon_count;
1336	uint8	*hours = NULL;
1337	uint8	*lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1338	uint32		len = 0;
1339	uint32		lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1340	uint32 pwHistLen = 0;
1341	bool ret = True;
1342	fstring tmp_string;
1343	bool expand_explicit = lp_passdb_expand_explicit();
1344
1345	if(sampass == NULL || buf == NULL) {
1346		DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1347		return False;
1348	}
1349
1350/* SAMU_BUFFER_FORMAT_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1351
1352	/* unpack the buffer into variables */
1353	len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1354		&logon_time,						/* d */
1355		&logoff_time,						/* d */
1356		&kickoff_time,						/* d */
1357		&bad_password_time,					/* d */
1358		&pass_last_set_time,					/* d */
1359		&pass_can_change_time,					/* d */
1360		&pass_must_change_time,					/* d */
1361		&username_len, &username,				/* B */
1362		&domain_len, &domain,					/* B */
1363		&nt_username_len, &nt_username,				/* B */
1364		&fullname_len, &fullname,				/* B */
1365		&homedir_len, &homedir,					/* B */
1366		&dir_drive_len, &dir_drive,				/* B */
1367		&logon_script_len, &logon_script,			/* B */
1368		&profile_path_len, &profile_path,			/* B */
1369		&acct_desc_len, &acct_desc,				/* B */
1370		&workstations_len, &workstations,			/* B */
1371		&unknown_str_len, &unknown_str,				/* B */
1372		&munged_dial_len, &munged_dial,				/* B */
1373		&user_rid,						/* d */
1374		&group_rid,						/* d */
1375		&lm_pw_len, &lm_pw_ptr,					/* B */
1376		&nt_pw_len, &nt_pw_ptr,					/* B */
1377		/* Change from V1 is addition of password history field. */
1378		&nt_pw_hist_len, &nt_pw_hist_ptr,			/* B */
1379		&acct_ctrl,						/* w */
1380		/* Also "remove_me" field was removed. */
1381		&logon_divs,						/* w */
1382		&hours_len,						/* d */
1383		&hourslen, &hours,					/* B */
1384		&bad_password_count,					/* w */
1385		&logon_count,						/* w */
1386		&unknown_6);						/* d */
1387
1388	if (len == (uint32) -1)  {
1389		ret = False;
1390		goto done;
1391	}
1392
1393	pdb_set_logon_time(sampass, logon_time, PDB_SET);
1394	pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1395	pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1396	pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1397	pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1398	pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1399	pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1400
1401	pdb_set_username(sampass, username, PDB_SET);
1402	pdb_set_domain(sampass, domain, PDB_SET);
1403	pdb_set_nt_username(sampass, nt_username, PDB_SET);
1404	pdb_set_fullname(sampass, fullname, PDB_SET);
1405
1406	if (homedir) {
1407		fstrcpy( tmp_string, homedir );
1408		if (expand_explicit) {
1409			standard_sub_basic( username, domain, tmp_string,
1410					    sizeof(tmp_string) );
1411		}
1412		pdb_set_homedir(sampass, tmp_string, PDB_SET);
1413	}
1414	else {
1415		pdb_set_homedir(sampass,
1416			talloc_sub_basic(sampass, username, domain,
1417					 lp_logon_home()),
1418			PDB_DEFAULT);
1419	}
1420
1421	if (dir_drive)
1422		pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1423	else
1424		pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1425
1426	if (logon_script) {
1427		fstrcpy( tmp_string, logon_script );
1428		if (expand_explicit) {
1429			standard_sub_basic( username, domain, tmp_string,
1430					    sizeof(tmp_string) );
1431		}
1432		pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1433	}
1434	else {
1435		pdb_set_logon_script(sampass,
1436			talloc_sub_basic(sampass, username, domain,
1437					 lp_logon_script()),
1438			PDB_DEFAULT);
1439	}
1440
1441	if (profile_path) {
1442		fstrcpy( tmp_string, profile_path );
1443		if (expand_explicit) {
1444			standard_sub_basic( username, domain, tmp_string,
1445					    sizeof(tmp_string) );
1446		}
1447		pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1448	}
1449	else {
1450		pdb_set_profile_path(sampass,
1451			talloc_sub_basic(sampass, username, domain,
1452					 lp_logon_path()),
1453			PDB_DEFAULT);
1454	}
1455
1456	pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1457	pdb_set_workstations(sampass, workstations, PDB_SET);
1458	pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1459
1460	if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1461		if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1462			ret = False;
1463			goto done;
1464		}
1465	}
1466
1467	if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1468		if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1469			ret = False;
1470			goto done;
1471		}
1472	}
1473
1474	/* Change from V1 is addition of password history field. */
1475	pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1476	if (pwHistLen) {
1477		uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1478		if (!pw_hist) {
1479			ret = False;
1480			goto done;
1481		}
1482		memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1483		if (nt_pw_hist_ptr && nt_pw_hist_len) {
1484			int i;
1485			SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1486			nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1487			for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1488				memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1489					&nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1490					PW_HISTORY_ENTRY_LEN);
1491			}
1492		}
1493		if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1494			SAFE_FREE(pw_hist);
1495			ret = False;
1496			goto done;
1497		}
1498		SAFE_FREE(pw_hist);
1499	} else {
1500		pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1501	}
1502
1503	pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1504	pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1505	pdb_set_hours_len(sampass, hours_len, PDB_SET);
1506	pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1507	pdb_set_logon_count(sampass, logon_count, PDB_SET);
1508	pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1509	pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1510	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1511	pdb_set_hours(sampass, hours, PDB_SET);
1512
1513done:
1514
1515	SAFE_FREE(username);
1516	SAFE_FREE(domain);
1517	SAFE_FREE(nt_username);
1518	SAFE_FREE(fullname);
1519	SAFE_FREE(homedir);
1520	SAFE_FREE(dir_drive);
1521	SAFE_FREE(logon_script);
1522	SAFE_FREE(profile_path);
1523	SAFE_FREE(acct_desc);
1524	SAFE_FREE(workstations);
1525	SAFE_FREE(munged_dial);
1526	SAFE_FREE(unknown_str);
1527	SAFE_FREE(lm_pw_ptr);
1528	SAFE_FREE(nt_pw_ptr);
1529	SAFE_FREE(nt_pw_hist_ptr);
1530	SAFE_FREE(hours);
1531
1532	return ret;
1533}
1534
1535/*********************************************************************
1536*********************************************************************/
1537
1538static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1539{
1540
1541	/* times are stored as 32bit integer
1542	   take care on system with 64bit wide time_t
1543	   --SSS */
1544	uint32	logon_time,
1545		logoff_time,
1546		kickoff_time,
1547		bad_password_time,
1548		pass_last_set_time,
1549		pass_can_change_time,
1550		pass_must_change_time;
1551	char *username = NULL;
1552	char *domain = NULL;
1553	char *nt_username = NULL;
1554	char *dir_drive = NULL;
1555	char *comment = NULL;
1556	char *munged_dial = NULL;
1557	char *fullname = NULL;
1558	char *homedir = NULL;
1559	char *logon_script = NULL;
1560	char *profile_path = NULL;
1561	char *acct_desc = NULL;
1562	char *workstations = NULL;
1563	uint32	username_len, domain_len, nt_username_len,
1564		dir_drive_len, comment_len, munged_dial_len,
1565		fullname_len, homedir_len, logon_script_len,
1566		profile_path_len, acct_desc_len, workstations_len;
1567
1568	uint32	user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1569	uint16  logon_divs;
1570	uint16	bad_password_count, logon_count;
1571	uint8	*hours = NULL;
1572	uint8	*lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1573	uint32		len = 0;
1574	uint32		lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1575	uint32 pwHistLen = 0;
1576	bool ret = True;
1577	fstring tmp_string;
1578	bool expand_explicit = lp_passdb_expand_explicit();
1579
1580	if(sampass == NULL || buf == NULL) {
1581		DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1582		return False;
1583	}
1584
1585/* SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1586
1587	/* unpack the buffer into variables */
1588	len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1589		&logon_time,						/* d */
1590		&logoff_time,						/* d */
1591		&kickoff_time,						/* d */
1592		&bad_password_time,					/* d */
1593		&pass_last_set_time,					/* d */
1594		&pass_can_change_time,					/* d */
1595		&pass_must_change_time,					/* d */
1596		&username_len, &username,				/* B */
1597		&domain_len, &domain,					/* B */
1598		&nt_username_len, &nt_username,				/* B */
1599		&fullname_len, &fullname,				/* B */
1600		&homedir_len, &homedir,					/* B */
1601		&dir_drive_len, &dir_drive,				/* B */
1602		&logon_script_len, &logon_script,			/* B */
1603		&profile_path_len, &profile_path,			/* B */
1604		&acct_desc_len, &acct_desc,				/* B */
1605		&workstations_len, &workstations,			/* B */
1606		&comment_len, &comment,					/* B */
1607		&munged_dial_len, &munged_dial,				/* B */
1608		&user_rid,						/* d */
1609		&group_rid,						/* d */
1610		&lm_pw_len, &lm_pw_ptr,					/* B */
1611		&nt_pw_len, &nt_pw_ptr,					/* B */
1612		/* Change from V1 is addition of password history field. */
1613		&nt_pw_hist_len, &nt_pw_hist_ptr,			/* B */
1614		/* Change from V2 is the uint32 acb_mask */
1615		&acct_ctrl,						/* d */
1616		/* Also "remove_me" field was removed. */
1617		&logon_divs,						/* w */
1618		&hours_len,						/* d */
1619		&hourslen, &hours,					/* B */
1620		&bad_password_count,					/* w */
1621		&logon_count,						/* w */
1622		&unknown_6);						/* d */
1623
1624	if (len == (uint32) -1)  {
1625		ret = False;
1626		goto done;
1627	}
1628
1629	pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1630	pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1631	pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1632	pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1633	pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1634	pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1635	pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1636
1637	pdb_set_username(sampass, username, PDB_SET);
1638	pdb_set_domain(sampass, domain, PDB_SET);
1639	pdb_set_nt_username(sampass, nt_username, PDB_SET);
1640	pdb_set_fullname(sampass, fullname, PDB_SET);
1641
1642	if (homedir) {
1643		fstrcpy( tmp_string, homedir );
1644		if (expand_explicit) {
1645			standard_sub_basic( username, domain, tmp_string,
1646					    sizeof(tmp_string) );
1647		}
1648		pdb_set_homedir(sampass, tmp_string, PDB_SET);
1649	}
1650	else {
1651		pdb_set_homedir(sampass,
1652			talloc_sub_basic(sampass, username, domain,
1653					 lp_logon_home()),
1654			PDB_DEFAULT);
1655	}
1656
1657	if (dir_drive)
1658		pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1659	else
1660		pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1661
1662	if (logon_script) {
1663		fstrcpy( tmp_string, logon_script );
1664		if (expand_explicit) {
1665			standard_sub_basic( username, domain, tmp_string,
1666					    sizeof(tmp_string) );
1667		}
1668		pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1669	}
1670	else {
1671		pdb_set_logon_script(sampass,
1672			talloc_sub_basic(sampass, username, domain,
1673					 lp_logon_script()),
1674			PDB_DEFAULT);
1675	}
1676
1677	if (profile_path) {
1678		fstrcpy( tmp_string, profile_path );
1679		if (expand_explicit) {
1680			standard_sub_basic( username, domain, tmp_string,
1681					    sizeof(tmp_string) );
1682		}
1683		pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1684	}
1685	else {
1686		pdb_set_profile_path(sampass,
1687			talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1688			PDB_DEFAULT);
1689	}
1690
1691	pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1692	pdb_set_comment(sampass, comment, PDB_SET);
1693	pdb_set_workstations(sampass, workstations, PDB_SET);
1694	pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1695
1696	if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1697		if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1698			ret = False;
1699			goto done;
1700		}
1701	}
1702
1703	if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1704		if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1705			ret = False;
1706			goto done;
1707		}
1708	}
1709
1710	pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1711	if (pwHistLen) {
1712		uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1713		if (!pw_hist) {
1714			ret = False;
1715			goto done;
1716		}
1717		memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1718		if (nt_pw_hist_ptr && nt_pw_hist_len) {
1719			int i;
1720			SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1721			nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1722			for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1723				memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1724					&nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1725					PW_HISTORY_ENTRY_LEN);
1726			}
1727		}
1728		if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1729			SAFE_FREE(pw_hist);
1730			ret = False;
1731			goto done;
1732		}
1733		SAFE_FREE(pw_hist);
1734	} else {
1735		pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1736	}
1737
1738	pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1739	pdb_set_hours_len(sampass, hours_len, PDB_SET);
1740	pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1741	pdb_set_logon_count(sampass, logon_count, PDB_SET);
1742	pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1743	/* Change from V2 is the uint32 acct_ctrl */
1744	pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1745	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1746	pdb_set_hours(sampass, hours, PDB_SET);
1747
1748done:
1749
1750	SAFE_FREE(username);
1751	SAFE_FREE(domain);
1752	SAFE_FREE(nt_username);
1753	SAFE_FREE(fullname);
1754	SAFE_FREE(homedir);
1755	SAFE_FREE(dir_drive);
1756	SAFE_FREE(logon_script);
1757	SAFE_FREE(profile_path);
1758	SAFE_FREE(acct_desc);
1759	SAFE_FREE(workstations);
1760	SAFE_FREE(munged_dial);
1761	SAFE_FREE(comment);
1762	SAFE_FREE(lm_pw_ptr);
1763	SAFE_FREE(nt_pw_ptr);
1764	SAFE_FREE(nt_pw_hist_ptr);
1765	SAFE_FREE(hours);
1766
1767	return ret;
1768}
1769
1770/*********************************************************************
1771*********************************************************************/
1772
1773static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1774{
1775	size_t len, buflen;
1776
1777	/* times are stored as 32bit integer
1778	   take care on system with 64bit wide time_t
1779	   --SSS */
1780	uint32	logon_time,
1781		logoff_time,
1782		kickoff_time,
1783		bad_password_time,
1784		pass_last_set_time,
1785		pass_can_change_time,
1786		pass_must_change_time;
1787
1788	uint32  user_rid, group_rid;
1789
1790	const char *username;
1791	const char *domain;
1792	const char *nt_username;
1793	const char *dir_drive;
1794	const char *comment;
1795	const char *munged_dial;
1796	const char *fullname;
1797	const char *homedir;
1798	const char *logon_script;
1799	const char *profile_path;
1800	const char *acct_desc;
1801	const char *workstations;
1802	uint32	username_len, domain_len, nt_username_len,
1803		dir_drive_len, comment_len, munged_dial_len,
1804		fullname_len, homedir_len, logon_script_len,
1805		profile_path_len, acct_desc_len, workstations_len;
1806
1807	const uint8 *lm_pw;
1808	const uint8 *nt_pw;
1809	const uint8 *nt_pw_hist;
1810	uint32	lm_pw_len = 16;
1811	uint32	nt_pw_len = 16;
1812	uint32  nt_pw_hist_len;
1813	uint32 pwHistLen = 0;
1814
1815	*buf = NULL;
1816	buflen = 0;
1817
1818	logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1819	logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1820	kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1821	bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1822	pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1823	pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1824	pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1825
1826	user_rid = pdb_get_user_rid(sampass);
1827	group_rid = pdb_get_group_rid(sampass);
1828
1829	username = pdb_get_username(sampass);
1830	if (username) {
1831		username_len = strlen(username) +1;
1832	} else {
1833		username_len = 0;
1834	}
1835
1836	domain = pdb_get_domain(sampass);
1837	if (domain) {
1838		domain_len = strlen(domain) +1;
1839	} else {
1840		domain_len = 0;
1841	}
1842
1843	nt_username = pdb_get_nt_username(sampass);
1844	if (nt_username) {
1845		nt_username_len = strlen(nt_username) +1;
1846	} else {
1847		nt_username_len = 0;
1848	}
1849
1850	fullname = pdb_get_fullname(sampass);
1851	if (fullname) {
1852		fullname_len = strlen(fullname) +1;
1853	} else {
1854		fullname_len = 0;
1855	}
1856
1857	/*
1858	 * Only updates fields which have been set (not defaults from smb.conf)
1859	 */
1860
1861	if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1862		dir_drive = pdb_get_dir_drive(sampass);
1863	} else {
1864		dir_drive = NULL;
1865	}
1866	if (dir_drive) {
1867		dir_drive_len = strlen(dir_drive) +1;
1868	} else {
1869		dir_drive_len = 0;
1870	}
1871
1872	if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1873		homedir = pdb_get_homedir(sampass);
1874	} else {
1875		homedir = NULL;
1876	}
1877	if (homedir) {
1878		homedir_len = strlen(homedir) +1;
1879	} else {
1880		homedir_len = 0;
1881	}
1882
1883	if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1884		logon_script = pdb_get_logon_script(sampass);
1885	} else {
1886		logon_script = NULL;
1887	}
1888	if (logon_script) {
1889		logon_script_len = strlen(logon_script) +1;
1890	} else {
1891		logon_script_len = 0;
1892	}
1893
1894	if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1895		profile_path = pdb_get_profile_path(sampass);
1896	} else {
1897		profile_path = NULL;
1898	}
1899	if (profile_path) {
1900		profile_path_len = strlen(profile_path) +1;
1901	} else {
1902		profile_path_len = 0;
1903	}
1904
1905	lm_pw = pdb_get_lanman_passwd(sampass);
1906	if (!lm_pw) {
1907		lm_pw_len = 0;
1908	}
1909
1910	nt_pw = pdb_get_nt_passwd(sampass);
1911	if (!nt_pw) {
1912		nt_pw_len = 0;
1913	}
1914
1915	pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1916	nt_pw_hist =  pdb_get_pw_history(sampass, &nt_pw_hist_len);
1917	if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1918		nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1919	} else {
1920		nt_pw_hist_len = 0;
1921	}
1922
1923	acct_desc = pdb_get_acct_desc(sampass);
1924	if (acct_desc) {
1925		acct_desc_len = strlen(acct_desc) +1;
1926	} else {
1927		acct_desc_len = 0;
1928	}
1929
1930	workstations = pdb_get_workstations(sampass);
1931	if (workstations) {
1932		workstations_len = strlen(workstations) +1;
1933	} else {
1934		workstations_len = 0;
1935	}
1936
1937	comment = pdb_get_comment(sampass);
1938	if (comment) {
1939		comment_len = strlen(comment) +1;
1940	} else {
1941		comment_len = 0;
1942	}
1943
1944	munged_dial = pdb_get_munged_dial(sampass);
1945	if (munged_dial) {
1946		munged_dial_len = strlen(munged_dial) +1;
1947	} else {
1948		munged_dial_len = 0;
1949	}
1950
1951/* SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1952
1953	/* one time to get the size needed */
1954	len = tdb_pack(NULL, 0,  SAMU_BUFFER_FORMAT_V3,
1955		logon_time,				/* d */
1956		logoff_time,				/* d */
1957		kickoff_time,				/* d */
1958		bad_password_time,			/* d */
1959		pass_last_set_time,			/* d */
1960		pass_can_change_time,			/* d */
1961		pass_must_change_time,			/* d */
1962		username_len, username,			/* B */
1963		domain_len, domain,			/* B */
1964		nt_username_len, nt_username,		/* B */
1965		fullname_len, fullname,			/* B */
1966		homedir_len, homedir,			/* B */
1967		dir_drive_len, dir_drive,		/* B */
1968		logon_script_len, logon_script,		/* B */
1969		profile_path_len, profile_path,		/* B */
1970		acct_desc_len, acct_desc,		/* B */
1971		workstations_len, workstations,		/* B */
1972		comment_len, comment,			/* B */
1973		munged_dial_len, munged_dial,		/* B */
1974		user_rid,				/* d */
1975		group_rid,				/* d */
1976		lm_pw_len, lm_pw,			/* B */
1977		nt_pw_len, nt_pw,			/* B */
1978		nt_pw_hist_len, nt_pw_hist,		/* B */
1979		pdb_get_acct_ctrl(sampass),		/* d */
1980		pdb_get_logon_divs(sampass),		/* w */
1981		pdb_get_hours_len(sampass),		/* d */
1982		MAX_HOURS_LEN, pdb_get_hours(sampass),	/* B */
1983		pdb_get_bad_password_count(sampass),	/* w */
1984		pdb_get_logon_count(sampass),		/* w */
1985		pdb_get_unknown_6(sampass));		/* d */
1986
1987	if (size_only) {
1988		return buflen;
1989	}
1990
1991	/* malloc the space needed */
1992	if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1993		DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1994		return (-1);
1995	}
1996
1997	/* now for the real call to tdb_pack() */
1998	buflen = tdb_pack(*buf, len,  SAMU_BUFFER_FORMAT_V3,
1999		logon_time,				/* d */
2000		logoff_time,				/* d */
2001		kickoff_time,				/* d */
2002		bad_password_time,			/* d */
2003		pass_last_set_time,			/* d */
2004		pass_can_change_time,			/* d */
2005		pass_must_change_time,			/* d */
2006		username_len, username,			/* B */
2007		domain_len, domain,			/* B */
2008		nt_username_len, nt_username,		/* B */
2009		fullname_len, fullname,			/* B */
2010		homedir_len, homedir,			/* B */
2011		dir_drive_len, dir_drive,		/* B */
2012		logon_script_len, logon_script,		/* B */
2013		profile_path_len, profile_path,		/* B */
2014		acct_desc_len, acct_desc,		/* B */
2015		workstations_len, workstations,		/* B */
2016		comment_len, comment,			/* B */
2017		munged_dial_len, munged_dial,		/* B */
2018		user_rid,				/* d */
2019		group_rid,				/* d */
2020		lm_pw_len, lm_pw,			/* B */
2021		nt_pw_len, nt_pw,			/* B */
2022		nt_pw_hist_len, nt_pw_hist,		/* B */
2023		pdb_get_acct_ctrl(sampass),		/* d */
2024		pdb_get_logon_divs(sampass),		/* w */
2025		pdb_get_hours_len(sampass),		/* d */
2026		MAX_HOURS_LEN, pdb_get_hours(sampass),	/* B */
2027		pdb_get_bad_password_count(sampass),	/* w */
2028		pdb_get_logon_count(sampass),		/* w */
2029		pdb_get_unknown_6(sampass));		/* d */
2030
2031	/* check to make sure we got it correct */
2032	if (buflen != len) {
2033		DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
2034			  (unsigned long)buflen, (unsigned long)len));
2035		/* error */
2036		SAFE_FREE (*buf);
2037		return (-1);
2038	}
2039
2040	return (buflen);
2041}
2042
2043static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
2044{
2045	/* nothing changed between V3 and V4 */
2046	return init_samu_from_buffer_v3(sampass, buf, buflen);
2047}
2048
2049static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
2050{
2051	/* nothing changed between V3 and V4 */
2052	return init_buffer_from_samu_v3(buf, sampass, size_only);
2053}
2054
2055/**********************************************************************
2056 Intialize a struct samu struct from a BYTE buffer of size len
2057 *********************************************************************/
2058
2059bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
2060			   uint8 *buf, uint32 buflen)
2061{
2062	switch (level) {
2063	case SAMU_BUFFER_V0:
2064		return init_samu_from_buffer_v0(sampass, buf, buflen);
2065	case SAMU_BUFFER_V1:
2066		return init_samu_from_buffer_v1(sampass, buf, buflen);
2067	case SAMU_BUFFER_V2:
2068		return init_samu_from_buffer_v2(sampass, buf, buflen);
2069	case SAMU_BUFFER_V3:
2070		return init_samu_from_buffer_v3(sampass, buf, buflen);
2071	case SAMU_BUFFER_V4:
2072		return init_samu_from_buffer_v4(sampass, buf, buflen);
2073	}
2074
2075	return false;
2076}
2077
2078/**********************************************************************
2079 Intialize a BYTE buffer from a struct samu struct
2080 *********************************************************************/
2081
2082uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
2083{
2084	return init_buffer_from_samu_v4(buf, sampass, size_only);
2085}
2086
2087/*********************************************************************
2088*********************************************************************/
2089
2090bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2091{
2092	uint8 *buf = NULL;
2093	int len;
2094
2095	len = init_buffer_from_samu(&buf, src, False);
2096	if (len == -1 || !buf) {
2097		SAFE_FREE(buf);
2098		return False;
2099	}
2100
2101	if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2102		free(buf);
2103		return False;
2104	}
2105
2106	dst->methods = src->methods;
2107
2108	if ( src->unix_pw ) {
2109		dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2110		if (!dst->unix_pw) {
2111			free(buf);
2112			return False;
2113		}
2114	}
2115
2116	if (src->group_sid) {
2117		pdb_set_group_sid(dst, src->group_sid, PDB_SET);
2118	}
2119
2120	free(buf);
2121	return True;
2122}
2123
2124/*********************************************************************
2125 Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME
2126*********************************************************************/
2127
2128bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2129{
2130	time_t LastBadPassword;
2131	uint16 BadPasswordCount;
2132	uint32 resettime;
2133	bool res;
2134
2135	BadPasswordCount = pdb_get_bad_password_count(sampass);
2136	if (!BadPasswordCount) {
2137		DEBUG(9, ("No bad password attempts.\n"));
2138		return True;
2139	}
2140
2141	become_root();
2142	res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime);
2143	unbecome_root();
2144
2145	if (!res) {
2146		DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2147		return False;
2148	}
2149
2150	/* First, check if there is a reset time to compare */
2151	if ((resettime == (uint32) -1) || (resettime == 0)) {
2152		DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2153		return True;
2154	}
2155
2156	LastBadPassword = pdb_get_bad_password_time(sampass);
2157	DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n",
2158		   (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2159	if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2160		pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2161		pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2162		if (updated) {
2163			*updated = True;
2164		}
2165	}
2166
2167	return True;
2168}
2169
2170/*********************************************************************
2171 Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION
2172*********************************************************************/
2173
2174bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2175{
2176	uint32 duration;
2177	time_t LastBadPassword;
2178	bool res;
2179
2180	if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2181		DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2182			pdb_get_username(sampass)));
2183		return True;
2184	}
2185
2186	become_root();
2187	res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration);
2188	unbecome_root();
2189
2190	if (!res) {
2191		DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2192		return False;
2193	}
2194
2195	/* First, check if there is a duration to compare */
2196	if ((duration == (uint32) -1)  || (duration == 0)) {
2197		DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2198		return True;
2199	}
2200
2201	LastBadPassword = pdb_get_bad_password_time(sampass);
2202	DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2203		  pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2204
2205	if (LastBadPassword == (time_t)0) {
2206		DEBUG(1,("pdb_update_autolock_flag: Account %s "
2207			 "administratively locked out with no bad password "
2208			 "time. Leaving locked out.\n",
2209			 pdb_get_username(sampass) ));
2210		return True;
2211	}
2212
2213	if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2214		pdb_set_acct_ctrl(sampass,
2215				  pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2216				  PDB_CHANGED);
2217		pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2218		pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2219		if (updated) {
2220			*updated = True;
2221		}
2222	}
2223
2224	return True;
2225}
2226
2227/*********************************************************************
2228 Increment the bad_password_count
2229*********************************************************************/
2230
2231bool pdb_increment_bad_password_count(struct samu *sampass)
2232{
2233	uint32 account_policy_lockout;
2234	bool autolock_updated = False, badpw_updated = False;
2235	bool ret;
2236
2237	/* Retrieve the account lockout policy */
2238	become_root();
2239	ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2240	unbecome_root();
2241	if ( !ret ) {
2242		DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2243		return False;
2244	}
2245
2246	/* If there is no policy, we don't need to continue checking */
2247	if (!account_policy_lockout) {
2248		DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2249		return True;
2250	}
2251
2252	/* Check if the autolock needs to be cleared */
2253	if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2254		return False;
2255
2256	/* Check if the badpw count needs to be reset */
2257	if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2258		return False;
2259
2260	/*
2261	  Ok, now we can assume that any resetting that needs to be
2262	  done has been done, and just get on with incrementing
2263	  and autolocking if necessary
2264	*/
2265
2266	pdb_set_bad_password_count(sampass,
2267				   pdb_get_bad_password_count(sampass)+1,
2268				   PDB_CHANGED);
2269	pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2270
2271
2272	if (pdb_get_bad_password_count(sampass) < account_policy_lockout)
2273		return True;
2274
2275	if (!pdb_set_acct_ctrl(sampass,
2276			       pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2277			       PDB_CHANGED)) {
2278		DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n"));
2279		return False;
2280	}
2281
2282	return True;
2283}
2284
2285bool is_dc_trusted_domain_situation(const char *domain_name)
2286{
2287	return IS_DC && !strequal(domain_name, lp_workgroup());
2288}
2289
2290/*******************************************************************
2291 Wrapper around retrieving the clear text trust account password.
2292 appropriate account name is stored in account_name.
2293 Caller must free password, but not account_name.
2294*******************************************************************/
2295
2296bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2297			const char **account_name,
2298			enum netr_SchannelType *channel)
2299{
2300	char *pwd;
2301	time_t last_set_time;
2302
2303	/* if we are a DC and this is not our domain, then lookup an account
2304	 * for the domain trust */
2305
2306	if (is_dc_trusted_domain_situation(domain)) {
2307		if (!lp_allow_trusted_domains()) {
2308			return false;
2309		}
2310
2311		if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2312					   &last_set_time))
2313		{
2314			DEBUG(0, ("get_trust_pw: could not fetch trust "
2315				"account password for trusted domain %s\n",
2316				domain));
2317			return false;
2318		}
2319
2320		if (channel != NULL) {
2321			*channel = SEC_CHAN_DOMAIN;
2322		}
2323
2324		if (account_name != NULL) {
2325			*account_name = lp_workgroup();
2326		}
2327
2328		return true;
2329	}
2330
2331	/*
2332	 * Since we can only be member of one single domain, we are now
2333	 * in a member situation:
2334	 *
2335	 *  -  Either we are a DC (selfjoined) and the domain is our
2336	 *     own domain.
2337	 *  -  Or we are on a member and the domain is our own or some
2338	 *     other (potentially trusted) domain.
2339	 *
2340	 * In both cases, we can only get the machine account password
2341	 * for our own domain to connect to our own dc. (For a member,
2342	 * request to trusted domains are performed through our dc.)
2343	 *
2344	 * So we simply use our own domain name to retrieve the
2345	 * machine account passowrd and ignore the request domain here.
2346	 */
2347
2348	pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2349
2350	if (pwd != NULL) {
2351		*ret_pwd = pwd;
2352		if (account_name != NULL) {
2353			*account_name = global_myname();
2354		}
2355
2356		return true;
2357	}
2358
2359	DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2360		  "account password for domain %s\n", domain));
2361	return false;
2362}
2363
2364/*******************************************************************
2365 Wrapper around retrieving the trust account password.
2366 appropriate account name is stored in account_name.
2367*******************************************************************/
2368
2369bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2370		       const char **account_name,
2371		       enum netr_SchannelType *channel)
2372{
2373	char *pwd = NULL;
2374	time_t last_set_time;
2375
2376	if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2377		E_md4hash(pwd, ret_pwd);
2378		SAFE_FREE(pwd);
2379		return true;
2380	} else if (is_dc_trusted_domain_situation(domain)) {
2381		return false;
2382	}
2383
2384	/* as a fallback, try to get the hashed pwd directly from the tdb... */
2385
2386	if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2387							&last_set_time,
2388							channel))
2389	{
2390		if (account_name != NULL) {
2391			*account_name = global_myname();
2392		}
2393
2394		return true;
2395	}
2396
2397	DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2398		"password for domain %s\n", domain));
2399	return False;
2400}
2401
2402struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2403						struct samu *pw)
2404{
2405	struct samr_LogonHours hours;
2406	const int units_per_week = 168;
2407
2408	ZERO_STRUCT(hours);
2409	hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2410	if (!hours.bits) {
2411		return hours;
2412	}
2413
2414	hours.units_per_week = units_per_week;
2415	memset(hours.bits, 0xFF, units_per_week);
2416
2417	if (pdb_get_hours(pw)) {
2418		memcpy(hours.bits, pdb_get_hours(pw),
2419		       MIN(pdb_get_hours_len(pw), units_per_week));
2420	}
2421
2422	return hours;
2423}
2424