r1661: Changed the password history format so that each history entry
[bbaumbach/samba-autobuild/.git] / source3 / passdb / pdb_get_set.c
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
43 uint16 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
51 time_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
59 time_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
67 time_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
75 time_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
83 time_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
91 time_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
99 time_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
107 uint16 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
115 uint32 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
123 const uint8* pdb_get_hours (const SAM_ACCOUNT *sampass)
124 {
125         if (sampass)
126                 return (sampass->private.hours);
127         else
128                 return (NULL);
129 }
130
131 const 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
142 const 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
153 const 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 */
172 const 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 }
180 const 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
188 const 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  
202 enum 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
226 const char* pdb_get_username (const SAM_ACCOUNT *sampass)
227 {
228         if (sampass)
229                 return (sampass->private.username);
230         else
231                 return (NULL);
232 }
233
234 const char* pdb_get_domain (const SAM_ACCOUNT *sampass)
235 {
236         if (sampass)
237                 return (sampass->private.domain);
238         else
239                 return (NULL);
240 }
241
242 const 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
250 const 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
258 const 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
266 const 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
274 const 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
282 const 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
290 const 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
298 const 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
306 const char* pdb_get_workstations (const SAM_ACCOUNT *sampass)
307 {
308         if (sampass)
309                 return (sampass->private.workstations);
310         else
311                 return (NULL);
312 }
313
314 const 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
322 const 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
330 uint32 pdb_get_fields_present (const SAM_ACCOUNT *sampass)
331 {
332         if (sampass)
333                 return (sampass->private.fields_present);
334         else
335                 return (-1);
336 }
337
338 uint16 pdb_get_bad_password_count(const SAM_ACCOUNT *sampass)
339 {
340         if (sampass)
341                 return (sampass->private.bad_password_count);
342         else
343                 return 0;
344 }
345
346 uint16 pdb_get_logon_count(const SAM_ACCOUNT *sampass)
347 {
348         if (sampass)
349                 return (sampass->private.logon_count);
350         else
351                 return 0;
352 }
353
354 uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass)
355 {
356         if (sampass)
357                 return (sampass->private.unknown_6);
358         else
359                 return (-1);
360 }
361
362 void *pdb_get_backend_private_data (const SAM_ACCOUNT *sampass, const struct pdb_methods *my_methods)
363 {
364         if (sampass && my_methods == sampass->private.backend_private_methods)
365                 return sampass->private.backend_private_data;
366         else
367                 return NULL;
368 }
369
370 /*********************************************************************
371  Collection of set...() functions for SAM_ACCOUNT.
372  ********************************************************************/
373
374 BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 acct_ctrl, enum pdb_value_state flag)
375 {
376         if (!sampass)
377                 return False;
378                 
379         sampass->private.acct_ctrl = acct_ctrl;
380
381         return pdb_set_init_flags(sampass, PDB_ACCTCTRL, flag);
382 }
383
384 BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
385 {
386         if (!sampass)
387                 return False;
388
389         sampass->private.logon_time = mytime;
390
391         return pdb_set_init_flags(sampass, PDB_LOGONTIME, flag);
392 }
393
394 BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
395 {
396         if (!sampass)
397                 return False;
398
399         sampass->private.logoff_time = mytime;
400
401         return pdb_set_init_flags(sampass, PDB_LOGOFFTIME, flag);
402 }
403
404 BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
405 {
406         if (!sampass)
407                 return False;
408
409         sampass->private.kickoff_time = mytime;
410
411         return pdb_set_init_flags(sampass, PDB_KICKOFFTIME, flag);
412 }
413
414 BOOL pdb_set_bad_password_time (SAM_ACCOUNT *sampass, time_t mytime, 
415                                 enum pdb_value_state flag)
416 {
417         if (!sampass)
418                 return False;
419
420         sampass->private.bad_password_time = mytime;
421
422         return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_TIME, flag);
423 }
424
425 BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
426 {
427         if (!sampass)
428                 return False;
429
430         sampass->private.pass_can_change_time = mytime;
431
432         return pdb_set_init_flags(sampass, PDB_CANCHANGETIME, flag);
433 }
434
435 BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
436 {
437         if (!sampass)
438                 return False;
439
440         sampass->private.pass_must_change_time = mytime;
441
442         return pdb_set_init_flags(sampass, PDB_MUSTCHANGETIME, flag);
443 }
444
445 BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
446 {
447         if (!sampass)
448                 return False;
449
450         sampass->private.pass_last_set_time = mytime;
451
452         return pdb_set_init_flags(sampass, PDB_PASSLASTSET, flag);
453 }
454
455 BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len, enum pdb_value_state flag)
456 {
457         if (!sampass)
458                 return False;
459
460         sampass->private.hours_len = len;
461
462         return pdb_set_init_flags(sampass, PDB_HOURSLEN, flag);
463 }
464
465 BOOL pdb_set_logon_divs (SAM_ACCOUNT *sampass, uint16 hours, enum pdb_value_state flag)
466 {
467         if (!sampass)
468                 return False;
469
470         sampass->private.logon_divs = hours;
471
472         return pdb_set_init_flags(sampass, PDB_LOGONDIVS, flag);
473 }
474
475 /**
476  * Set flags showing what is initalised in the SAM_ACCOUNT
477  * @param sampass the SAM_ACCOUNT in question
478  * @param flag The *new* flag to be set.  Old flags preserved
479  *             this flag is only added.  
480  **/
481  
482 BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum pdb_value_state value_flag)
483 {
484         if (!sampass || !sampass->mem_ctx)
485                 return False;
486
487         if (!sampass->private.set_flags) {
488                 if ((sampass->private.set_flags = 
489                         bitmap_talloc(sampass->mem_ctx, 
490                                         PDB_COUNT))==NULL) {
491                         DEBUG(0,("bitmap_talloc failed\n"));
492                         return False;
493                 }
494         }
495         if (!sampass->private.change_flags) {
496                 if ((sampass->private.change_flags = 
497                         bitmap_talloc(sampass->mem_ctx, 
498                                         PDB_COUNT))==NULL) {
499                         DEBUG(0,("bitmap_talloc failed\n"));
500                         return False;
501                 }
502         }
503         
504         switch(value_flag) {
505                 case PDB_CHANGED:
506                         if (!bitmap_set(sampass->private.change_flags, element)) {
507                                 DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
508                                 return False;
509                         }
510                         if (!bitmap_set(sampass->private.set_flags, element)) {
511                                 DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
512                                 return False;
513                         }
514                         DEBUG(11, ("element %d -> now CHANGED\n", element)); 
515                         break;
516                 case PDB_SET:
517                         if (!bitmap_clear(sampass->private.change_flags, element)) {
518                                 DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
519                                 return False;
520                         }
521                         if (!bitmap_set(sampass->private.set_flags, element)) {
522                                 DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
523                                 return False;
524                         }
525                         DEBUG(10, ("element %d -> now SET\n", element)); 
526                         break;
527                 case PDB_DEFAULT:
528                 default:
529                         if (!bitmap_clear(sampass->private.change_flags, element)) {
530                                 DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
531                                 return False;
532                         }
533                         if (!bitmap_clear(sampass->private.set_flags, element)) {
534                                 DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
535                                 return False;
536                         }
537                         DEBUG(11, ("element %d -> now DEFAULT\n", element)); 
538                         break;
539         }
540
541         return True;
542 }
543
544 BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, const DOM_SID *u_sid, enum pdb_value_state flag)
545 {
546         if (!sampass || !u_sid)
547                 return False;
548         
549         sid_copy(&sampass->private.user_sid, u_sid);
550
551         DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n", 
552                     sid_string_static(&sampass->private.user_sid)));
553
554         return pdb_set_init_flags(sampass, PDB_USERSID, flag);
555 }
556
557 BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb_value_state flag)
558 {
559         DOM_SID new_sid;
560         
561         if (!sampass || !u_sid)
562                 return False;
563
564         DEBUG(10, ("pdb_set_user_sid_from_string: setting user sid %s\n",
565                    u_sid));
566
567         if (!string_to_sid(&new_sid, u_sid)) { 
568                 DEBUG(1, ("pdb_set_user_sid_from_string: %s isn't a valid SID!\n", u_sid));
569                 return False;
570         }
571          
572         if (!pdb_set_user_sid(sampass, &new_sid, flag)) {
573                 DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", u_sid));
574                 return False;
575         }
576
577         return True;
578 }
579
580 BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, const DOM_SID *g_sid, enum pdb_value_state flag)
581 {
582         if (!sampass || !g_sid)
583                 return False;
584
585         sid_copy(&sampass->private.group_sid, g_sid);
586
587         DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", 
588                     sid_string_static(&sampass->private.group_sid)));
589
590         return pdb_set_init_flags(sampass, PDB_GROUPSID, flag);
591 }
592
593 BOOL pdb_set_group_sid_from_string (SAM_ACCOUNT *sampass, fstring g_sid, enum pdb_value_state flag)
594 {
595         DOM_SID new_sid;
596         if (!sampass || !g_sid)
597                 return False;
598
599         DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n",
600                    g_sid));
601
602         if (!string_to_sid(&new_sid, g_sid)) { 
603                 DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid));
604                 return False;
605         }
606          
607         if (!pdb_set_group_sid(sampass, &new_sid, flag)) {
608                 DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", g_sid));
609                 return False;
610         }
611         return True;
612 }
613
614 /*********************************************************************
615  Set the user's UNIX name.
616  ********************************************************************/
617
618 BOOL pdb_set_username(SAM_ACCOUNT *sampass, const char *username, enum pdb_value_state flag)
619 {
620         if (!sampass)
621                 return False;
622  
623         if (username) { 
624                 DEBUG(10, ("pdb_set_username: setting username %s, was %s\n", username,
625                         (sampass->private.username)?(sampass->private.username):"NULL"));
626
627                 sampass->private.username = talloc_strdup(sampass->mem_ctx, username);
628
629                 if (!sampass->private.username) {
630                         DEBUG(0, ("pdb_set_username: talloc_strdup() failed!\n"));
631                         return False;
632                 }
633
634         } else {
635                 sampass->private.username = PDB_NOT_QUITE_NULL;
636         }
637         
638         return pdb_set_init_flags(sampass, PDB_USERNAME, flag);
639 }
640
641 /*********************************************************************
642  Set the domain name.
643  ********************************************************************/
644
645 BOOL pdb_set_domain(SAM_ACCOUNT *sampass, const char *domain, enum pdb_value_state flag)
646 {
647         if (!sampass)
648                 return False;
649
650         if (domain) { 
651                 DEBUG(10, ("pdb_set_domain: setting domain %s, was %s\n", domain,
652                         (sampass->private.domain)?(sampass->private.domain):"NULL"));
653
654                 sampass->private.domain = talloc_strdup(sampass->mem_ctx, domain);
655
656                 if (!sampass->private.domain) {
657                         DEBUG(0, ("pdb_set_domain: talloc_strdup() failed!\n"));
658                         return False;
659                 }
660
661         } else {
662                 sampass->private.domain = PDB_NOT_QUITE_NULL;
663         }
664
665         return pdb_set_init_flags(sampass, PDB_DOMAIN, flag);
666 }
667
668 /*********************************************************************
669  Set the user's NT name.
670  ********************************************************************/
671
672 BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, const char *nt_username, enum pdb_value_state flag)
673 {
674         if (!sampass)
675                 return False;
676
677         if (nt_username) { 
678                 DEBUG(10, ("pdb_set_nt_username: setting nt username %s, was %s\n", nt_username,
679                         (sampass->private.nt_username)?(sampass->private.nt_username):"NULL"));
680  
681                 sampass->private.nt_username = talloc_strdup(sampass->mem_ctx, nt_username);
682                 
683                 if (!sampass->private.nt_username) {
684                         DEBUG(0, ("pdb_set_nt_username: talloc_strdup() failed!\n"));
685                         return False;
686                 }
687
688         } else {
689                 sampass->private.nt_username = PDB_NOT_QUITE_NULL;
690         }
691
692         return pdb_set_init_flags(sampass, PDB_NTUSERNAME, flag);
693 }
694
695 /*********************************************************************
696  Set the user's full name.
697  ********************************************************************/
698
699 BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, const char *full_name, enum pdb_value_state flag)
700 {
701         if (!sampass)
702                 return False;
703
704         if (full_name) { 
705                 DEBUG(10, ("pdb_set_full_name: setting full name %s, was %s\n", full_name,
706                         (sampass->private.full_name)?(sampass->private.full_name):"NULL"));
707         
708                 sampass->private.full_name = talloc_strdup(sampass->mem_ctx, full_name);
709
710                 if (!sampass->private.full_name) {
711                         DEBUG(0, ("pdb_set_fullname: talloc_strdup() failed!\n"));
712                         return False;
713                 }
714
715         } else {
716                 sampass->private.full_name = PDB_NOT_QUITE_NULL;
717         }
718
719         return pdb_set_init_flags(sampass, PDB_FULLNAME, flag);
720 }
721
722 /*********************************************************************
723  Set the user's logon script.
724  ********************************************************************/
725
726 BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, enum pdb_value_state flag)
727 {
728         if (!sampass)
729                 return False;
730
731         if (logon_script) { 
732                 DEBUG(10, ("pdb_set_logon_script: setting logon script %s, was %s\n", logon_script,
733                         (sampass->private.logon_script)?(sampass->private.logon_script):"NULL"));
734  
735                 sampass->private.logon_script = talloc_strdup(sampass->mem_ctx, logon_script);
736
737                 if (!sampass->private.logon_script) {
738                         DEBUG(0, ("pdb_set_logon_script: talloc_strdup() failed!\n"));
739                         return False;
740                 }
741
742         } else {
743                 sampass->private.logon_script = PDB_NOT_QUITE_NULL;
744         }
745         
746         return pdb_set_init_flags(sampass, PDB_LOGONSCRIPT, flag);
747 }
748
749 /*********************************************************************
750  Set the user's profile path.
751  ********************************************************************/
752
753 BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, enum pdb_value_state flag)
754 {
755         if (!sampass)
756                 return False;
757
758         if (profile_path) { 
759                 DEBUG(10, ("pdb_set_profile_path: setting profile path %s, was %s\n", profile_path,
760                         (sampass->private.profile_path)?(sampass->private.profile_path):"NULL"));
761  
762                 sampass->private.profile_path = talloc_strdup(sampass->mem_ctx, profile_path);
763                 
764                 if (!sampass->private.profile_path) {
765                         DEBUG(0, ("pdb_set_profile_path: talloc_strdup() failed!\n"));
766                         return False;
767                 }
768
769         } else {
770                 sampass->private.profile_path = PDB_NOT_QUITE_NULL;
771         }
772
773         return pdb_set_init_flags(sampass, PDB_PROFILE, flag);
774 }
775
776 /*********************************************************************
777  Set the user's directory drive.
778  ********************************************************************/
779
780 BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, enum pdb_value_state flag)
781 {
782         if (!sampass)
783                 return False;
784
785         if (dir_drive) { 
786                 DEBUG(10, ("pdb_set_dir_drive: setting dir drive %s, was %s\n", dir_drive,
787                         (sampass->private.dir_drive)?(sampass->private.dir_drive):"NULL"));
788  
789                 sampass->private.dir_drive = talloc_strdup(sampass->mem_ctx, dir_drive);
790                 
791                 if (!sampass->private.dir_drive) {
792                         DEBUG(0, ("pdb_set_dir_drive: talloc_strdup() failed!\n"));
793                         return False;
794                 }
795
796         } else {
797                 sampass->private.dir_drive = PDB_NOT_QUITE_NULL;
798         }
799         
800         return pdb_set_init_flags(sampass, PDB_DRIVE, flag);
801 }
802
803 /*********************************************************************
804  Set the user's home directory.
805  ********************************************************************/
806
807 BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, enum pdb_value_state flag)
808 {
809         if (!sampass)
810                 return False;
811
812         if (home_dir) { 
813                 DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", home_dir,
814                         (sampass->private.home_dir)?(sampass->private.home_dir):"NULL"));
815  
816                 sampass->private.home_dir = talloc_strdup(sampass->mem_ctx, home_dir);
817                 
818                 if (!sampass->private.home_dir) {
819                         DEBUG(0, ("pdb_set_home_dir: talloc_strdup() failed!\n"));
820                         return False;
821                 }
822
823         } else {
824                 sampass->private.home_dir = PDB_NOT_QUITE_NULL;
825         }
826
827         return pdb_set_init_flags(sampass, PDB_SMBHOME, flag);
828 }
829
830 /*********************************************************************
831  Set the user's unix home directory.
832  ********************************************************************/
833
834 BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir, enum pdb_value_state flag)
835 {
836         if (!sampass)
837                 return False;
838
839         if (unix_home_dir) { 
840                 DEBUG(10, ("pdb_set_unix_homedir: setting home dir %s, was %s\n", unix_home_dir,
841                         (sampass->private.unix_home_dir)?(sampass->private.unix_home_dir):"NULL"));
842  
843                 sampass->private.unix_home_dir = talloc_strdup(sampass->mem_ctx, 
844                                                           unix_home_dir);
845                 
846                 if (!sampass->private.unix_home_dir) {
847                         DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n"));
848                         return False;
849                 }
850
851         } else {
852                 sampass->private.unix_home_dir = PDB_NOT_QUITE_NULL;
853         }
854
855         return pdb_set_init_flags(sampass, PDB_UNIXHOMEDIR, flag);
856 }
857
858 /*********************************************************************
859  Set the user's account description.
860  ********************************************************************/
861
862 BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, const char *acct_desc, enum pdb_value_state flag)
863 {
864         if (!sampass)
865                 return False;
866
867         if (acct_desc) { 
868                 sampass->private.acct_desc = talloc_strdup(sampass->mem_ctx, acct_desc);
869
870                 if (!sampass->private.acct_desc) {
871                         DEBUG(0, ("pdb_set_acct_desc: talloc_strdup() failed!\n"));
872                         return False;
873                 }
874
875         } else {
876                 sampass->private.acct_desc = PDB_NOT_QUITE_NULL;
877         }
878
879         return pdb_set_init_flags(sampass, PDB_ACCTDESC, flag);
880 }
881
882 /*********************************************************************
883  Set the user's workstation allowed list.
884  ********************************************************************/
885
886 BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, const char *workstations, enum pdb_value_state flag)
887 {
888         if (!sampass)
889                 return False;
890
891         if (workstations) { 
892                 DEBUG(10, ("pdb_set_workstations: setting workstations %s, was %s\n", workstations,
893                         (sampass->private.workstations)?(sampass->private.workstations):"NULL"));
894  
895                 sampass->private.workstations = talloc_strdup(sampass->mem_ctx, workstations);
896
897                 if (!sampass->private.workstations) {
898                         DEBUG(0, ("pdb_set_workstations: talloc_strdup() failed!\n"));
899                         return False;
900                 }
901
902         } else {
903                 sampass->private.workstations = PDB_NOT_QUITE_NULL;
904         }
905
906         return pdb_set_init_flags(sampass, PDB_WORKSTATIONS, flag);
907 }
908
909 /*********************************************************************
910  Set the user's 'unknown_str', whatever the heck this actually is...
911  ********************************************************************/
912
913 BOOL pdb_set_unknown_str (SAM_ACCOUNT *sampass, const char *unknown_str, enum pdb_value_state flag)
914 {
915         if (!sampass)
916                 return False;
917
918         if (unknown_str) { 
919                 sampass->private.unknown_str = talloc_strdup(sampass->mem_ctx, unknown_str);
920                 
921                 if (!sampass->private.unknown_str) {
922                         DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
923                         return False;
924                 }
925
926         } else {
927                 sampass->private.unknown_str = PDB_NOT_QUITE_NULL;
928         }
929
930         return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
931 }
932
933 /*********************************************************************
934  Set the user's dial string.
935  ********************************************************************/
936
937 BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, const char *munged_dial, enum pdb_value_state flag)
938 {
939         if (!sampass)
940                 return False;
941
942         if (munged_dial) { 
943                 sampass->private.munged_dial = talloc_strdup(sampass->mem_ctx, munged_dial);
944                 
945                 if (!sampass->private.munged_dial) {
946                         DEBUG(0, ("pdb_set_munged_dial: talloc_strdup() failed!\n"));
947                         return False;
948                 }
949
950         } else {
951                 sampass->private.munged_dial = PDB_NOT_QUITE_NULL;
952         }
953
954         return pdb_set_init_flags(sampass, PDB_MUNGEDDIAL, flag);
955 }
956
957 /*********************************************************************
958  Set the user's NT hash.
959  ********************************************************************/
960
961 BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum pdb_value_state flag)
962 {
963         if (!sampass)
964                 return False;
965
966         data_blob_clear_free(&sampass->private.nt_pw);
967         
968        if (pwd) {
969                sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN);
970        } else {
971                sampass->private.nt_pw = data_blob(NULL, 0);
972        }
973
974         return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag);
975 }
976
977 /*********************************************************************
978  Set the user's LM hash.
979  ********************************************************************/
980
981 BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], enum pdb_value_state flag)
982 {
983         if (!sampass)
984                 return False;
985
986         data_blob_clear_free(&sampass->private.lm_pw);
987         
988        if (pwd) {
989                sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN);
990        } else {
991                sampass->private.lm_pw = data_blob(NULL, 0);
992        }
993
994         return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag);
995 }
996
997 /*********************************************************************
998  Set the user's password history hash. historyLen is the number of 
999  PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN length
1000  entries to store in the history - this must match the size of the uint8 array
1001  in pwd.
1002 ********************************************************************/
1003
1004 BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag)
1005 {
1006         if (!sampass)
1007                 return False;
1008
1009         if (historyLen && pwd){
1010                 sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx,
1011                                                 pwd, historyLen*PW_HISTORY_ENTRY_LEN);
1012                 if (!sampass->private.nt_pw_his.length) {
1013                         DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n"));
1014                         return False;
1015                 }
1016         } else {
1017                 sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0);
1018         }
1019
1020         return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag);
1021 }
1022
1023 /*********************************************************************
1024  Set the user's plaintext password only (base procedure, see helper
1025  below)
1026  ********************************************************************/
1027
1028 BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const char *password, enum pdb_value_state flag)
1029 {
1030         if (!sampass)
1031                 return False;
1032
1033         if (password) { 
1034                 if (sampass->private.plaintext_pw!=NULL) 
1035                         memset(sampass->private.plaintext_pw,'\0',strlen(sampass->private.plaintext_pw)+1);
1036
1037                 sampass->private.plaintext_pw = talloc_strdup(sampass->mem_ctx, password);
1038                 
1039                 if (!sampass->private.plaintext_pw) {
1040                         DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
1041                         return False;
1042                 }
1043
1044         } else {
1045                 sampass->private.plaintext_pw = NULL;
1046         }
1047
1048         return pdb_set_init_flags(sampass, PDB_PLAINTEXT_PW, flag);
1049 }
1050
1051 BOOL pdb_set_fields_present (SAM_ACCOUNT *sampass, uint32 fields_present, enum pdb_value_state flag)
1052 {
1053         if (!sampass)
1054                 return False;
1055
1056         sampass->private.fields_present = fields_present;
1057         
1058         return pdb_set_init_flags(sampass, PDB_FIELDS_PRESENT, flag);
1059 }
1060
1061 BOOL pdb_set_bad_password_count(SAM_ACCOUNT *sampass, uint16 bad_password_count, enum pdb_value_state flag)
1062 {
1063         if (!sampass)
1064                 return False;
1065
1066         sampass->private.bad_password_count = bad_password_count;
1067
1068         return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag);
1069 }
1070
1071 BOOL pdb_set_logon_count(SAM_ACCOUNT *sampass, uint16 logon_count, enum pdb_value_state flag)
1072 {
1073         if (!sampass)
1074                 return False;
1075
1076         sampass->private.logon_count = logon_count;
1077
1078         return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag);
1079 }
1080
1081 BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag)
1082 {
1083         if (!sampass)
1084                 return False;
1085
1086         sampass->private.unknown_6 = unkn;
1087
1088         return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
1089 }
1090
1091 BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
1092 {
1093         if (!sampass)
1094                 return False;
1095
1096         if (!hours) {
1097                 memset ((char *)sampass->private.hours, 0, MAX_HOURS_LEN);
1098                 return True;
1099         }
1100         
1101         memcpy (sampass->private.hours, hours, MAX_HOURS_LEN);
1102
1103         return pdb_set_init_flags(sampass, PDB_HOURS, flag);
1104 }
1105
1106 BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data, 
1107                                    void (*free_fn)(void **), 
1108                                    const struct pdb_methods *my_methods, 
1109                                    enum pdb_value_state flag)
1110 {
1111         if (!sampass)
1112                 return False;
1113
1114         if (sampass->private.backend_private_data && sampass->private.backend_private_data_free_fn) {
1115                 sampass->private.backend_private_data_free_fn(&sampass->private.backend_private_data);
1116         }
1117
1118         sampass->private.backend_private_data = private_data;
1119         sampass->private.backend_private_data_free_fn = free_fn;
1120         sampass->private.backend_private_methods = my_methods;
1121
1122         return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag);
1123 }
1124
1125
1126 /* Helpful interfaces to the above */
1127
1128 /*********************************************************************
1129  Sets the last changed times and must change times for a normal
1130  password change.
1131  ********************************************************************/
1132
1133 BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
1134 {
1135         uint32 expire;
1136         uint32 min_age;
1137
1138         if (!sampass)
1139                 return False;
1140         
1141         if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
1142                 return False;
1143
1144         if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) 
1145             || (expire==(uint32)-1) || (expire == 0)) {
1146                 if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
1147                         return False;
1148         } else {
1149                 if (!pdb_set_pass_must_change_time (sampass, 
1150                                                     pdb_get_pass_last_set_time(sampass)
1151                                                     + expire, PDB_CHANGED))
1152                         return False;
1153         }
1154         
1155         if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age) 
1156             || (min_age==(uint32)-1)) {
1157                 if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
1158                         return False;
1159         } else {
1160                 if (!pdb_set_pass_can_change_time (sampass, 
1161                                                     pdb_get_pass_last_set_time(sampass)
1162                                                     + min_age, PDB_CHANGED))
1163                         return False;
1164         }
1165         return True;
1166 }
1167
1168 /*********************************************************************
1169  Set the user's PLAINTEXT password.  Used as an interface to the above.
1170  Also sets the last change time to NOW.
1171  ********************************************************************/
1172
1173 BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
1174 {
1175         uchar new_lanman_p16[LM_HASH_LEN];
1176         uchar new_nt_p16[NT_HASH_LEN];
1177
1178         if (!sampass || !plaintext)
1179                 return False;
1180
1181         /* Calculate the MD4 hash (NT compatible) of the password */
1182         E_md4hash(plaintext, new_nt_p16);
1183
1184         if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) 
1185                 return False;
1186
1187         if (!E_deshash(plaintext, new_lanman_p16)) {
1188                 /* E_deshash returns false for 'long' passwords (> 14
1189                    DOS chars).  This allows us to match Win2k, which
1190                    does not store a LM hash for these passwords (which
1191                    would reduce the effective password length to 14 */
1192
1193                 if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) 
1194                         return False;
1195         } else {
1196                 if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) 
1197                         return False;
1198         }
1199
1200         if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) 
1201                 return False;
1202
1203         if (!pdb_set_pass_changed_now (sampass))
1204                 return False;
1205
1206         /* Store the password history. */
1207         if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
1208                 uchar *pwhistory;
1209                 uint32 pwHistLen;
1210                 account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
1211                 if (pwHistLen != 0){
1212                         uint32 current_history_len;
1213                         /* We need to make sure we don't have a race condition here - the
1214                            account policy history length can change between when the pw_history
1215                            was first loaded into the SAM_ACCOUNT struct and now.... JRA. */
1216                         pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);
1217
1218                         if (current_history_len != pwHistLen) {
1219                                 /* After closing and reopening SAM_ACCOUNT the history
1220                                         values will sync up. We can't do this here. */
1221
1222                                 /* current_history_len > pwHistLen is not a problem - we
1223                                         have more history than we need. */
1224
1225                                 if (current_history_len < pwHistLen) {
1226                                         /* Ensure we have space for the needed history. */
1227                                         uchar *new_history = talloc(sampass->mem_ctx,
1228                                                                 pwHistLen*PW_HISTORY_ENTRY_LEN);
1229                                         /* And copy it into the new buffer. */
1230                                         if (current_history_len) {
1231                                                 memcpy(new_history, pwhistory,
1232                                                         current_history_len*PW_HISTORY_ENTRY_LEN);
1233                                         }
1234                                         /* Clearing out any extra space. */
1235                                         memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN],
1236                                                 '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN);
1237                                         /* Finally replace it. */
1238                                         pwhistory = new_history;
1239                                 }
1240                         }
1241                         if (pwhistory && pwHistLen){
1242                                 /* Make room for the new password in the history list. */
1243                                 if (pwHistLen > 1) {
1244                                         memmove(&pwhistory[PW_HISTORY_ENTRY_LEN],
1245                                                 pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN );
1246                                 }
1247                                 /* Create the new salt as the first part of the history entry. */
1248                                 generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN);
1249
1250                                 /* Generate the md5 hash of the salt+new password as the second
1251                                         part of the history entry. */
1252
1253                                 E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]);
1254                                 pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);
1255                         } else {
1256                                 DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n"));
1257                         }
1258                 } else {
1259                         /* Set the history length to zero. */
1260                         pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
1261                 }
1262         }
1263
1264         return True;
1265 }
1266
1267 /* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */
1268 uint32 pdb_build_fields_present (SAM_ACCOUNT *sampass)
1269 {
1270         /* value set to all for testing */
1271         return 0x00ffffff;
1272 }