1/*
2   Unix SMB/CIFS implementation.
3   SAM_ACCOUNT access routines
4   Copyright (C) Jeremy Allison 		1996-2001
5   Copyright (C) Luke Kenneth Casson Leighton 	1996-1998
6   Copyright (C) Gerald (Jerry) Carter		2000-2001
7   Copyright (C) Andrew Bartlett		2001-2002
8   Copyright (C) Stefan (metze) Metzmacher	2002
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25#include "includes.h"
26
27#undef DBGC_CLASS
28#define DBGC_CLASS DBGC_PASSDB
29
30/**
31 * @todo Redefine this to NULL, but this changes the API because
32 *       much of samba assumes that the pdb_get...() funtions
33 *       return pstrings.  (ie not null-pointers).
34 *       See also pdb_fill_default_sam().
35 */
36
37#define PDB_NOT_QUITE_NULL ""
38
39/*********************************************************************
40 Collection of get...() functions for SAM_ACCOUNT.
41 ********************************************************************/
42
43uint16 pdb_get_acct_ctrl (const SAM_ACCOUNT *sampass)
44{
45	if (sampass)
46		return (sampass->private.acct_ctrl);
47	else
48		return (ACB_DISABLED);
49}
50
51time_t pdb_get_logon_time (const SAM_ACCOUNT *sampass)
52{
53	if (sampass)
54		return (sampass->private.logon_time);
55	else
56		return (0);
57}
58
59time_t pdb_get_logoff_time (const SAM_ACCOUNT *sampass)
60{
61	if (sampass)
62		return (sampass->private.logoff_time);
63	else
64		return (-1);
65}
66
67time_t pdb_get_kickoff_time (const SAM_ACCOUNT *sampass)
68{
69	if (sampass)
70		return (sampass->private.kickoff_time);
71	else
72		return (-1);
73}
74
75time_t pdb_get_bad_password_time (const SAM_ACCOUNT *sampass)
76{
77	if (sampass)
78		return (sampass->private.bad_password_time);
79	else
80		return (-1);
81}
82
83time_t pdb_get_pass_last_set_time (const SAM_ACCOUNT *sampass)
84{
85	if (sampass)
86		return (sampass->private.pass_last_set_time);
87	else
88		return (-1);
89}
90
91time_t pdb_get_pass_can_change_time (const SAM_ACCOUNT *sampass)
92{
93	if (sampass)
94		return (sampass->private.pass_can_change_time);
95	else
96		return (-1);
97}
98
99time_t pdb_get_pass_must_change_time (const SAM_ACCOUNT *sampass)
100{
101	if (sampass)
102		return (sampass->private.pass_must_change_time);
103	else
104		return (-1);
105}
106
107uint16 pdb_get_logon_divs (const SAM_ACCOUNT *sampass)
108{
109	if (sampass)
110		return (sampass->private.logon_divs);
111	else
112		return (-1);
113}
114
115uint32 pdb_get_hours_len (const SAM_ACCOUNT *sampass)
116{
117	if (sampass)
118		return (sampass->private.hours_len);
119	else
120		return (-1);
121}
122
123const uint8* pdb_get_hours (const SAM_ACCOUNT *sampass)
124{
125	if (sampass)
126		return (sampass->private.hours);
127	else
128		return (NULL);
129}
130
131const uint8* pdb_get_nt_passwd (const SAM_ACCOUNT *sampass)
132{
133	if (sampass) {
134		SMB_ASSERT((!sampass->private.nt_pw.data)
135			   || sampass->private.nt_pw.length == NT_HASH_LEN);
136		return ((uint8*)sampass->private.nt_pw.data);
137	}
138	else
139		return (NULL);
140}
141
142const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass)
143{
144	if (sampass) {
145		SMB_ASSERT((!sampass->private.lm_pw.data)
146			   || sampass->private.lm_pw.length == LM_HASH_LEN);
147		return ((uint8*)sampass->private.lm_pw.data);
148	}
149	else
150		return (NULL);
151}
152
153const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_hist_len)
154{
155	if (sampass) {
156		SMB_ASSERT((!sampass->private.nt_pw_his.data)
157		   || ((sampass->private.nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0));
158		*current_hist_len = sampass->private.nt_pw_his.length / PW_HISTORY_ENTRY_LEN;
159		return ((uint8*)sampass->private.nt_pw_his.data);
160	} else {
161		*current_hist_len = 0;
162		return (NULL);
163	}
164}
165
166/* Return the plaintext password if known.  Most of the time
167   it isn't, so don't assume anything magic about this function.
168
169   Used to pass the plaintext to passdb backends that might
170   want to store more than just the NTLM hashes.
171*/
172const char* pdb_get_plaintext_passwd (const SAM_ACCOUNT *sampass)
173{
174	if (sampass) {
175		return (sampass->private.plaintext_pw);
176	}
177	else
178		return (NULL);
179}
180const DOM_SID *pdb_get_user_sid(const SAM_ACCOUNT *sampass)
181{
182	if (sampass)
183		return &sampass->private.user_sid;
184	else
185		return (NULL);
186}
187
188const DOM_SID *pdb_get_group_sid(const SAM_ACCOUNT *sampass)
189{
190	if (sampass)
191		return &sampass->private.group_sid;
192	else
193		return (NULL);
194}
195
196/**
197 * Get flags showing what is initalised in the SAM_ACCOUNT
198 * @param sampass the SAM_ACCOUNT in question
199 * @return the flags indicating the members initialised in the struct.
200 **/
201
202enum pdb_value_state pdb_get_init_flags (const SAM_ACCOUNT *sampass, enum pdb_elements element)
203{
204	enum pdb_value_state ret = PDB_DEFAULT;
205
206        if (!sampass || !sampass->private.change_flags || !sampass->private.set_flags)
207        	return ret;
208
209        if (bitmap_query(sampass->private.set_flags, element)) {
210		DEBUG(11, ("element %d: SET\n", element));
211        	ret = PDB_SET;
212	}
213
214        if (bitmap_query(sampass->private.change_flags, element)) {
215		DEBUG(11, ("element %d: CHANGED\n", element));
216        	ret = PDB_CHANGED;
217	}
218
219	if (ret == PDB_DEFAULT) {
220		DEBUG(11, ("element %d: DEFAULT\n", element));
221	}
222
223        return ret;
224}
225
226const char* pdb_get_username (const SAM_ACCOUNT *sampass)
227{
228	if (sampass)
229		return (sampass->private.username);
230	else
231		return (NULL);
232}
233
234const char* pdb_get_domain (const SAM_ACCOUNT *sampass)
235{
236	if (sampass)
237		return (sampass->private.domain);
238	else
239		return (NULL);
240}
241
242const char* pdb_get_nt_username (const SAM_ACCOUNT *sampass)
243{
244	if (sampass)
245		return (sampass->private.nt_username);
246	else
247		return (NULL);
248}
249
250const char* pdb_get_fullname (const SAM_ACCOUNT *sampass)
251{
252	if (sampass)
253		return (sampass->private.full_name);
254	else
255		return (NULL);
256}
257
258const char* pdb_get_homedir (const SAM_ACCOUNT *sampass)
259{
260	if (sampass)
261		return (sampass->private.home_dir);
262	else
263		return (NULL);
264}
265
266const char* pdb_get_unix_homedir (const SAM_ACCOUNT *sampass)
267{
268	if (sampass)
269		return (sampass->private.unix_home_dir);
270	else
271		return (NULL);
272}
273
274const char* pdb_get_dir_drive (const SAM_ACCOUNT *sampass)
275{
276	if (sampass)
277		return (sampass->private.dir_drive);
278	else
279		return (NULL);
280}
281
282const char* pdb_get_logon_script (const SAM_ACCOUNT *sampass)
283{
284	if (sampass)
285		return (sampass->private.logon_script);
286	else
287		return (NULL);
288}
289
290const char* pdb_get_profile_path (const SAM_ACCOUNT *sampass)
291{
292	if (sampass)
293		return (sampass->private.profile_path);
294	else
295		return (NULL);
296}
297
298const char* pdb_get_acct_desc (const SAM_ACCOUNT *sampass)
299{
300	if (sampass)
301		return (sampass->private.acct_desc);
302	else
303		return (NULL);
304}
305
306const char* pdb_get_workstations (const SAM_ACCOUNT *sampass)
307{
308	if (sampass)
309		return (sampass->private.workstations);
310	else
311		return (NULL);
312}
313
314const char* pdb_get_unknown_str (const SAM_ACCOUNT *sampass)
315{
316	if (sampass)
317		return (sampass->private.unknown_str);
318	else
319		return (NULL);
320}
321
322const char* pdb_get_munged_dial (const SAM_ACCOUNT *sampass)
323{
324	if (sampass)
325		return (sampass->private.munged_dial);
326	else
327		return (NULL);
328}
329
330uint16 pdb_get_bad_password_count(const SAM_ACCOUNT *sampass)
331{
332	if (sampass)
333		return (sampass->private.bad_password_count);
334	else
335		return 0;
336}
337
338uint16 pdb_get_logon_count(const SAM_ACCOUNT *sampass)
339{
340	if (sampass)
341		return (sampass->private.logon_count);
342	else
343		return 0;
344}
345
346uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass)
347{
348	if (sampass)
349		return (sampass->private.unknown_6);
350	else
351		return (-1);
352}
353
354void *pdb_get_backend_private_data (const SAM_ACCOUNT *sampass, const struct pdb_methods *my_methods)
355{
356	if (sampass && my_methods == sampass->private.backend_private_methods)
357		return sampass->private.backend_private_data;
358	else
359		return NULL;
360}
361
362/*********************************************************************
363 Collection of set...() functions for SAM_ACCOUNT.
364 ********************************************************************/
365
366BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 acct_ctrl, enum pdb_value_state flag)
367{
368	if (!sampass)
369		return False;
370
371	sampass->private.acct_ctrl = acct_ctrl;
372
373	return pdb_set_init_flags(sampass, PDB_ACCTCTRL, flag);
374}
375
376BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
377{
378	if (!sampass)
379		return False;
380
381	sampass->private.logon_time = mytime;
382
383	return pdb_set_init_flags(sampass, PDB_LOGONTIME, flag);
384}
385
386BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
387{
388	if (!sampass)
389		return False;
390
391	sampass->private.logoff_time = mytime;
392
393	return pdb_set_init_flags(sampass, PDB_LOGOFFTIME, flag);
394}
395
396BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
397{
398	if (!sampass)
399		return False;
400
401	sampass->private.kickoff_time = mytime;
402
403	return pdb_set_init_flags(sampass, PDB_KICKOFFTIME, flag);
404}
405
406BOOL pdb_set_bad_password_time (SAM_ACCOUNT *sampass, time_t mytime,
407				enum pdb_value_state flag)
408{
409	if (!sampass)
410		return False;
411
412	sampass->private.bad_password_time = mytime;
413
414	return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_TIME, flag);
415}
416
417BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
418{
419	if (!sampass)
420		return False;
421
422	sampass->private.pass_can_change_time = mytime;
423
424	return pdb_set_init_flags(sampass, PDB_CANCHANGETIME, flag);
425}
426
427BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
428{
429	if (!sampass)
430		return False;
431
432	sampass->private.pass_must_change_time = mytime;
433
434	return pdb_set_init_flags(sampass, PDB_MUSTCHANGETIME, flag);
435}
436
437BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
438{
439	if (!sampass)
440		return False;
441
442	sampass->private.pass_last_set_time = mytime;
443
444	return pdb_set_init_flags(sampass, PDB_PASSLASTSET, flag);
445}
446
447BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len, enum pdb_value_state flag)
448{
449	if (!sampass)
450		return False;
451
452	sampass->private.hours_len = len;
453
454	return pdb_set_init_flags(sampass, PDB_HOURSLEN, flag);
455}
456
457BOOL pdb_set_logon_divs (SAM_ACCOUNT *sampass, uint16 hours, enum pdb_value_state flag)
458{
459	if (!sampass)
460		return False;
461
462	sampass->private.logon_divs = hours;
463
464	return pdb_set_init_flags(sampass, PDB_LOGONDIVS, flag);
465}
466
467/**
468 * Set flags showing what is initalised in the SAM_ACCOUNT
469 * @param sampass the SAM_ACCOUNT in question
470 * @param flag The *new* flag to be set.  Old flags preserved
471 *             this flag is only added.
472 **/
473
474BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum pdb_value_state value_flag)
475{
476        if (!sampass || !sampass->mem_ctx)
477                return False;
478
479        if (!sampass->private.set_flags) {
480        	if ((sampass->private.set_flags =
481        		bitmap_talloc(sampass->mem_ctx,
482        				PDB_COUNT))==NULL) {
483        		DEBUG(0,("bitmap_talloc failed\n"));
484        		return False;
485        	}
486        }
487        if (!sampass->private.change_flags) {
488        	if ((sampass->private.change_flags =
489        		bitmap_talloc(sampass->mem_ctx,
490        				PDB_COUNT))==NULL) {
491        		DEBUG(0,("bitmap_talloc failed\n"));
492        		return False;
493        	}
494        }
495
496        switch(value_flag) {
497        	case PDB_CHANGED:
498        		if (!bitmap_set(sampass->private.change_flags, element)) {
499				DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
500				return False;
501			}
502        		if (!bitmap_set(sampass->private.set_flags, element)) {
503				DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
504				return False;
505			}
506			DEBUG(11, ("element %d -> now CHANGED\n", element));
507        		break;
508        	case PDB_SET:
509        		if (!bitmap_clear(sampass->private.change_flags, element)) {
510				DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
511				return False;
512			}
513        		if (!bitmap_set(sampass->private.set_flags, element)) {
514				DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
515				return False;
516			}
517			DEBUG(11, ("element %d -> now SET\n", element));
518        		break;
519        	case PDB_DEFAULT:
520        	default:
521        		if (!bitmap_clear(sampass->private.change_flags, element)) {
522				DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
523				return False;
524			}
525        		if (!bitmap_clear(sampass->private.set_flags, element)) {
526				DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
527				return False;
528			}
529			DEBUG(11, ("element %d -> now DEFAULT\n", element));
530        		break;
531	}
532
533        return True;
534}
535
536BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, const DOM_SID *u_sid, enum pdb_value_state flag)
537{
538	if (!sampass || !u_sid)
539		return False;
540
541	sid_copy(&sampass->private.user_sid, u_sid);
542
543	DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n",
544		    sid_string_static(&sampass->private.user_sid)));
545
546	return pdb_set_init_flags(sampass, PDB_USERSID, flag);
547}
548
549BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb_value_state flag)
550{
551	DOM_SID new_sid;
552
553	if (!sampass || !u_sid)
554		return False;
555
556	DEBUG(10, ("pdb_set_user_sid_from_string: setting user sid %s\n",
557		   u_sid));
558
559	if (!string_to_sid(&new_sid, u_sid)) {
560		DEBUG(1, ("pdb_set_user_sid_from_string: %s isn't a valid SID!\n", u_sid));
561		return False;
562	}
563
564	if (!pdb_set_user_sid(sampass, &new_sid, flag)) {
565		DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", u_sid));
566		return False;
567	}
568
569	return True;
570}
571
572BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, const DOM_SID *g_sid, enum pdb_value_state flag)
573{
574	if (!sampass || !g_sid)
575		return False;
576
577	sid_copy(&sampass->private.group_sid, g_sid);
578
579	DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n",
580		    sid_string_static(&sampass->private.group_sid)));
581
582	return pdb_set_init_flags(sampass, PDB_GROUPSID, flag);
583}
584
585BOOL pdb_set_group_sid_from_string (SAM_ACCOUNT *sampass, fstring g_sid, enum pdb_value_state flag)
586{
587	DOM_SID new_sid;
588	if (!sampass || !g_sid)
589		return False;
590
591	DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n",
592		   g_sid));
593
594	if (!string_to_sid(&new_sid, g_sid)) {
595		DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid));
596		return False;
597	}
598
599	if (!pdb_set_group_sid(sampass, &new_sid, flag)) {
600		DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", g_sid));
601		return False;
602	}
603	return True;
604}
605
606/*********************************************************************
607 Set the user's UNIX name.
608 ********************************************************************/
609
610BOOL pdb_set_username(SAM_ACCOUNT *sampass, const char *username, enum pdb_value_state flag)
611{
612	if (!sampass)
613		return False;
614
615	if (username) {
616		DEBUG(10, ("pdb_set_username: setting username %s, was %s\n", username,
617			(sampass->private.username)?(sampass->private.username):"NULL"));
618
619		sampass->private.username = talloc_strdup(sampass->mem_ctx, username);
620
621		if (!sampass->private.username) {
622			DEBUG(0, ("pdb_set_username: talloc_strdup() failed!\n"));
623			return False;
624		}
625
626	} else {
627		sampass->private.username = PDB_NOT_QUITE_NULL;
628	}
629
630	return pdb_set_init_flags(sampass, PDB_USERNAME, flag);
631}
632
633/*********************************************************************
634 Set the domain name.
635 ********************************************************************/
636
637BOOL pdb_set_domain(SAM_ACCOUNT *sampass, const char *domain, enum pdb_value_state flag)
638{
639	if (!sampass)
640		return False;
641
642	if (domain) {
643		DEBUG(10, ("pdb_set_domain: setting domain %s, was %s\n", domain,
644			(sampass->private.domain)?(sampass->private.domain):"NULL"));
645
646		sampass->private.domain = talloc_strdup(sampass->mem_ctx, domain);
647
648		if (!sampass->private.domain) {
649			DEBUG(0, ("pdb_set_domain: talloc_strdup() failed!\n"));
650			return False;
651		}
652
653	} else {
654		sampass->private.domain = PDB_NOT_QUITE_NULL;
655	}
656
657	return pdb_set_init_flags(sampass, PDB_DOMAIN, flag);
658}
659
660/*********************************************************************
661 Set the user's NT name.
662 ********************************************************************/
663
664BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, const char *nt_username, enum pdb_value_state flag)
665{
666	if (!sampass)
667		return False;
668
669	if (nt_username) {
670		DEBUG(10, ("pdb_set_nt_username: setting nt username %s, was %s\n", nt_username,
671			(sampass->private.nt_username)?(sampass->private.nt_username):"NULL"));
672
673		sampass->private.nt_username = talloc_strdup(sampass->mem_ctx, nt_username);
674
675		if (!sampass->private.nt_username) {
676			DEBUG(0, ("pdb_set_nt_username: talloc_strdup() failed!\n"));
677			return False;
678		}
679
680	} else {
681		sampass->private.nt_username = PDB_NOT_QUITE_NULL;
682	}
683
684	return pdb_set_init_flags(sampass, PDB_NTUSERNAME, flag);
685}
686
687/*********************************************************************
688 Set the user's full name.
689 ********************************************************************/
690
691BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, const char *full_name, enum pdb_value_state flag)
692{
693	if (!sampass)
694		return False;
695
696	if (full_name) {
697		DEBUG(10, ("pdb_set_full_name: setting full name %s, was %s\n", full_name,
698			(sampass->private.full_name)?(sampass->private.full_name):"NULL"));
699
700		sampass->private.full_name = talloc_strdup(sampass->mem_ctx, full_name);
701
702		if (!sampass->private.full_name) {
703			DEBUG(0, ("pdb_set_fullname: talloc_strdup() failed!\n"));
704			return False;
705		}
706
707	} else {
708		sampass->private.full_name = PDB_NOT_QUITE_NULL;
709	}
710
711	return pdb_set_init_flags(sampass, PDB_FULLNAME, flag);
712}
713
714/*********************************************************************
715 Set the user's logon script.
716 ********************************************************************/
717
718BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, enum pdb_value_state flag)
719{
720	if (!sampass)
721		return False;
722
723	if (logon_script) {
724		DEBUG(10, ("pdb_set_logon_script: setting logon script %s, was %s\n", logon_script,
725			(sampass->private.logon_script)?(sampass->private.logon_script):"NULL"));
726
727		sampass->private.logon_script = talloc_strdup(sampass->mem_ctx, logon_script);
728
729		if (!sampass->private.logon_script) {
730			DEBUG(0, ("pdb_set_logon_script: talloc_strdup() failed!\n"));
731			return False;
732		}
733
734	} else {
735		sampass->private.logon_script = PDB_NOT_QUITE_NULL;
736	}
737
738	return pdb_set_init_flags(sampass, PDB_LOGONSCRIPT, flag);
739}
740
741/*********************************************************************
742 Set the user's profile path.
743 ********************************************************************/
744
745BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, enum pdb_value_state flag)
746{
747	if (!sampass)
748		return False;
749
750	if (profile_path) {
751		DEBUG(10, ("pdb_set_profile_path: setting profile path %s, was %s\n", profile_path,
752			(sampass->private.profile_path)?(sampass->private.profile_path):"NULL"));
753
754		sampass->private.profile_path = talloc_strdup(sampass->mem_ctx, profile_path);
755
756		if (!sampass->private.profile_path) {
757			DEBUG(0, ("pdb_set_profile_path: talloc_strdup() failed!\n"));
758			return False;
759		}
760
761	} else {
762		sampass->private.profile_path = PDB_NOT_QUITE_NULL;
763	}
764
765	return pdb_set_init_flags(sampass, PDB_PROFILE, flag);
766}
767
768/*********************************************************************
769 Set the user's directory drive.
770 ********************************************************************/
771
772BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, enum pdb_value_state flag)
773{
774	if (!sampass)
775		return False;
776
777	if (dir_drive) {
778		DEBUG(10, ("pdb_set_dir_drive: setting dir drive %s, was %s\n", dir_drive,
779			(sampass->private.dir_drive)?(sampass->private.dir_drive):"NULL"));
780
781		sampass->private.dir_drive = talloc_strdup(sampass->mem_ctx, dir_drive);
782
783		if (!sampass->private.dir_drive) {
784			DEBUG(0, ("pdb_set_dir_drive: talloc_strdup() failed!\n"));
785			return False;
786		}
787
788	} else {
789		sampass->private.dir_drive = PDB_NOT_QUITE_NULL;
790	}
791
792	return pdb_set_init_flags(sampass, PDB_DRIVE, flag);
793}
794
795/*********************************************************************
796 Set the user's home directory.
797 ********************************************************************/
798
799BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, enum pdb_value_state flag)
800{
801	if (!sampass)
802		return False;
803
804	if (home_dir) {
805		DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", home_dir,
806			(sampass->private.home_dir)?(sampass->private.home_dir):"NULL"));
807
808		sampass->private.home_dir = talloc_strdup(sampass->mem_ctx, home_dir);
809
810		if (!sampass->private.home_dir) {
811			DEBUG(0, ("pdb_set_home_dir: talloc_strdup() failed!\n"));
812			return False;
813		}
814
815	} else {
816		sampass->private.home_dir = PDB_NOT_QUITE_NULL;
817	}
818
819	return pdb_set_init_flags(sampass, PDB_SMBHOME, flag);
820}
821
822/*********************************************************************
823 Set the user's unix home directory.
824 ********************************************************************/
825
826BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir, enum pdb_value_state flag)
827{
828	if (!sampass)
829		return False;
830
831	if (unix_home_dir) {
832		DEBUG(10, ("pdb_set_unix_homedir: setting home dir %s, was %s\n", unix_home_dir,
833			(sampass->private.unix_home_dir)?(sampass->private.unix_home_dir):"NULL"));
834
835		sampass->private.unix_home_dir = talloc_strdup(sampass->mem_ctx,
836							  unix_home_dir);
837
838		if (!sampass->private.unix_home_dir) {
839			DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n"));
840			return False;
841		}
842
843	} else {
844		sampass->private.unix_home_dir = PDB_NOT_QUITE_NULL;
845	}
846
847	return pdb_set_init_flags(sampass, PDB_UNIXHOMEDIR, flag);
848}
849
850/*********************************************************************
851 Set the user's account description.
852 ********************************************************************/
853
854BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, const char *acct_desc, enum pdb_value_state flag)
855{
856	if (!sampass)
857		return False;
858
859	if (acct_desc) {
860		sampass->private.acct_desc = talloc_strdup(sampass->mem_ctx, acct_desc);
861
862		if (!sampass->private.acct_desc) {
863			DEBUG(0, ("pdb_set_acct_desc: talloc_strdup() failed!\n"));
864			return False;
865		}
866
867	} else {
868		sampass->private.acct_desc = PDB_NOT_QUITE_NULL;
869	}
870
871	return pdb_set_init_flags(sampass, PDB_ACCTDESC, flag);
872}
873
874/*********************************************************************
875 Set the user's workstation allowed list.
876 ********************************************************************/
877
878BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, const char *workstations, enum pdb_value_state flag)
879{
880	if (!sampass)
881		return False;
882
883	if (workstations) {
884		DEBUG(10, ("pdb_set_workstations: setting workstations %s, was %s\n", workstations,
885			(sampass->private.workstations)?(sampass->private.workstations):"NULL"));
886
887		sampass->private.workstations = talloc_strdup(sampass->mem_ctx, workstations);
888
889		if (!sampass->private.workstations) {
890			DEBUG(0, ("pdb_set_workstations: talloc_strdup() failed!\n"));
891			return False;
892		}
893
894	} else {
895		sampass->private.workstations = PDB_NOT_QUITE_NULL;
896	}
897
898	return pdb_set_init_flags(sampass, PDB_WORKSTATIONS, flag);
899}
900
901/*********************************************************************
902 Set the user's 'unknown_str', whatever the heck this actually is...
903 ********************************************************************/
904
905BOOL pdb_set_unknown_str (SAM_ACCOUNT *sampass, const char *unknown_str, enum pdb_value_state flag)
906{
907	if (!sampass)
908		return False;
909
910	if (unknown_str) {
911		sampass->private.unknown_str = talloc_strdup(sampass->mem_ctx, unknown_str);
912
913		if (!sampass->private.unknown_str) {
914			DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
915			return False;
916		}
917
918	} else {
919		sampass->private.unknown_str = PDB_NOT_QUITE_NULL;
920	}
921
922	return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
923}
924
925/*********************************************************************
926 Set the user's dial string.
927 ********************************************************************/
928
929BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, const char *munged_dial, enum pdb_value_state flag)
930{
931	if (!sampass)
932		return False;
933
934	if (munged_dial) {
935		sampass->private.munged_dial = talloc_strdup(sampass->mem_ctx, munged_dial);
936
937		if (!sampass->private.munged_dial) {
938			DEBUG(0, ("pdb_set_munged_dial: talloc_strdup() failed!\n"));
939			return False;
940		}
941
942	} else {
943		sampass->private.munged_dial = PDB_NOT_QUITE_NULL;
944	}
945
946	return pdb_set_init_flags(sampass, PDB_MUNGEDDIAL, flag);
947}
948
949/*********************************************************************
950 Set the user's NT hash.
951 ********************************************************************/
952
953BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum pdb_value_state flag)
954{
955	if (!sampass)
956		return False;
957
958	data_blob_clear_free(&sampass->private.nt_pw);
959
960       if (pwd) {
961               sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN);
962       } else {
963               sampass->private.nt_pw = data_blob(NULL, 0);
964       }
965
966	return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag);
967}
968
969/*********************************************************************
970 Set the user's LM hash.
971 ********************************************************************/
972
973BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], enum pdb_value_state flag)
974{
975	if (!sampass)
976		return False;
977
978	data_blob_clear_free(&sampass->private.lm_pw);
979
980       if (pwd) {
981               sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN);
982       } else {
983               sampass->private.lm_pw = data_blob(NULL, 0);
984       }
985
986	return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag);
987}
988
989/*********************************************************************
990 Set the user's password history hash. historyLen is the number of
991 PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN length
992 entries to store in the history - this must match the size of the uint8 array
993 in pwd.
994********************************************************************/
995
996BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag)
997{
998	if (!sampass)
999		return False;
1000
1001	if (historyLen && pwd){
1002		sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx,
1003						pwd, historyLen*PW_HISTORY_ENTRY_LEN);
1004		if (!sampass->private.nt_pw_his.length) {
1005			DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n"));
1006			return False;
1007		}
1008	} else {
1009		sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0);
1010	}
1011
1012	return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag);
1013}
1014
1015/*********************************************************************
1016 Set the user's plaintext password only (base procedure, see helper
1017 below)
1018 ********************************************************************/
1019
1020BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const char *password, enum pdb_value_state flag)
1021{
1022	if (!sampass)
1023		return False;
1024
1025	if (password) {
1026		if (sampass->private.plaintext_pw!=NULL)
1027			memset(sampass->private.plaintext_pw,'\0',strlen(sampass->private.plaintext_pw)+1);
1028
1029		sampass->private.plaintext_pw = talloc_strdup(sampass->mem_ctx, password);
1030
1031		if (!sampass->private.plaintext_pw) {
1032			DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
1033			return False;
1034		}
1035
1036	} else {
1037		sampass->private.plaintext_pw = NULL;
1038	}
1039
1040	return pdb_set_init_flags(sampass, PDB_PLAINTEXT_PW, flag);
1041}
1042
1043BOOL pdb_set_bad_password_count(SAM_ACCOUNT *sampass, uint16 bad_password_count, enum pdb_value_state flag)
1044{
1045	if (!sampass)
1046		return False;
1047
1048	sampass->private.bad_password_count = bad_password_count;
1049
1050	return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag);
1051}
1052
1053BOOL pdb_set_logon_count(SAM_ACCOUNT *sampass, uint16 logon_count, enum pdb_value_state flag)
1054{
1055	if (!sampass)
1056		return False;
1057
1058	sampass->private.logon_count = logon_count;
1059
1060	return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag);
1061}
1062
1063BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag)
1064{
1065	if (!sampass)
1066		return False;
1067
1068	sampass->private.unknown_6 = unkn;
1069
1070	return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
1071}
1072
1073BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
1074{
1075	if (!sampass)
1076		return False;
1077
1078	if (!hours) {
1079		memset ((char *)sampass->private.hours, 0, MAX_HOURS_LEN);
1080		return True;
1081	}
1082
1083	memcpy (sampass->private.hours, hours, MAX_HOURS_LEN);
1084
1085	return pdb_set_init_flags(sampass, PDB_HOURS, flag);
1086}
1087
1088BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data,
1089				   void (*free_fn)(void **),
1090				   const struct pdb_methods *my_methods,
1091				   enum pdb_value_state flag)
1092{
1093	if (!sampass)
1094		return False;
1095
1096	if (sampass->private.backend_private_data && sampass->private.backend_private_data_free_fn) {
1097		sampass->private.backend_private_data_free_fn(&sampass->private.backend_private_data);
1098	}
1099
1100	sampass->private.backend_private_data = private_data;
1101	sampass->private.backend_private_data_free_fn = free_fn;
1102	sampass->private.backend_private_methods = my_methods;
1103
1104	return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag);
1105}
1106
1107
1108/* Helpful interfaces to the above */
1109
1110/*********************************************************************
1111 Sets the last changed times and must change times for a normal
1112 password change.
1113 ********************************************************************/
1114
1115BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
1116{
1117	uint32 expire;
1118	uint32 min_age;
1119
1120	if (!sampass)
1121		return False;
1122
1123	if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
1124		return False;
1125
1126	if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire)
1127	    || (expire==(uint32)-1) || (expire == 0)) {
1128		if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
1129			return False;
1130	} else {
1131		if (!pdb_set_pass_must_change_time (sampass,
1132						    pdb_get_pass_last_set_time(sampass)
1133						    + expire, PDB_CHANGED))
1134			return False;
1135	}
1136
1137	if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age)
1138	    || (min_age==(uint32)-1)) {
1139		if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
1140			return False;
1141	} else {
1142		if (!pdb_set_pass_can_change_time (sampass,
1143						    pdb_get_pass_last_set_time(sampass)
1144						    + min_age, PDB_CHANGED))
1145			return False;
1146	}
1147	return True;
1148}
1149
1150/*********************************************************************
1151 Set the user's PLAINTEXT password.  Used as an interface to the above.
1152 Also sets the last change time to NOW.
1153 ********************************************************************/
1154
1155BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
1156{
1157	uchar new_lanman_p16[LM_HASH_LEN];
1158	uchar new_nt_p16[NT_HASH_LEN];
1159
1160	if (!sampass || !plaintext)
1161		return False;
1162
1163	/* Calculate the MD4 hash (NT compatible) of the password */
1164	E_md4hash(plaintext, new_nt_p16);
1165
1166	if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED))
1167		return False;
1168
1169	if (!E_deshash(plaintext, new_lanman_p16)) {
1170		/* E_deshash returns false for 'long' passwords (> 14
1171		   DOS chars).  This allows us to match Win2k, which
1172		   does not store a LM hash for these passwords (which
1173		   would reduce the effective password length to 14 */
1174
1175		if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED))
1176			return False;
1177	} else {
1178		if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED))
1179			return False;
1180	}
1181
1182	if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED))
1183		return False;
1184
1185	if (!pdb_set_pass_changed_now (sampass))
1186		return False;
1187
1188	/* Store the password history. */
1189	if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
1190		uchar *pwhistory;
1191		uint32 pwHistLen;
1192		account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
1193		if (pwHistLen != 0){
1194			uint32 current_history_len;
1195			/* We need to make sure we don't have a race condition here - the
1196			   account policy history length can change between when the pw_history
1197			   was first loaded into the SAM_ACCOUNT struct and now.... JRA. */
1198			pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);
1199
1200			if (current_history_len != pwHistLen) {
1201				/* After closing and reopening SAM_ACCOUNT the history
1202					values will sync up. We can't do this here. */
1203
1204				/* current_history_len > pwHistLen is not a problem - we
1205					have more history than we need. */
1206
1207				if (current_history_len < pwHistLen) {
1208					/* Ensure we have space for the needed history. */
1209					uchar *new_history = TALLOC(sampass->mem_ctx,
1210								pwHistLen*PW_HISTORY_ENTRY_LEN);
1211					/* And copy it into the new buffer. */
1212					if (current_history_len) {
1213						memcpy(new_history, pwhistory,
1214							current_history_len*PW_HISTORY_ENTRY_LEN);
1215					}
1216					/* Clearing out any extra space. */
1217					memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN],
1218						'\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN);
1219					/* Finally replace it. */
1220					pwhistory = new_history;
1221				}
1222			}
1223			if (pwhistory && pwHistLen){
1224				/* Make room for the new password in the history list. */
1225				if (pwHistLen > 1) {
1226					memmove(&pwhistory[PW_HISTORY_ENTRY_LEN],
1227						pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN );
1228				}
1229				/* Create the new salt as the first part of the history entry. */
1230				generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN);
1231
1232				/* Generate the md5 hash of the salt+new password as the second
1233					part of the history entry. */
1234
1235				E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]);
1236				pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);
1237			} else {
1238				DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n"));
1239			}
1240		} else {
1241			/* Set the history length to zero. */
1242			pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
1243		}
1244	}
1245
1246	return True;
1247}
1248
1249/* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */
1250uint32 pdb_build_fields_present (SAM_ACCOUNT *sampass)
1251{
1252	/* value set to all for testing */
1253	return 0x00ffffff;
1254}
1255